Skip to content

Navigation state

Navigation state

Clicking a row opens that record without your page doing any routing. The shell owns record navigation, the views own their state, and both live in the URL, so a pasted link reopens what was on screen.

The record sheet

A record opens as a sheet over the current page, rendered by its collection’s +representation.svelte, or by the generated RecordShell when there is none. The open sheets are a stack in the URL (?record=<collection>/<id>): a record opened from an open sheet stacks on it, and closing a sheet pops it. Views open rows on their own; code calls openRecord(collection, id) from @norbital-ai/ui, with 'new' for a create sheet.

<script lang="ts">
  // src/lib/record-form.svelte (templates/construction, excerpt): a create opens the new record
  import { Form, RecordShell, openRecord } from '@norbital-ai/ui';
  // …
  const of = $derived(view.collection);
  const record = $derived(view.mode !== 'create' ? view.record : null);
</script>

<RecordShell {of} mode={view.mode} {...record == null ? {} : { id: record.id }}>
  <Form
    {of}
    mode={view.mode}
    {...record == null
      ? { values: view.mode === 'create' ? view.values : {} }
      : { id: record.id, record }}
    onOutcome={(outcome) => {
      const created = outcome.kind === 'committed' ? outcome.records[0] : undefined;
      if (view.mode === 'create' && created !== undefined) openRecord(of, created.id);
    }}
  >
    {@render children()}
  </Form>
</RecordShell>

View state

?record=quotes/<id>                         the record sheet stack, one entry per open sheet
&quotes.where={"status":{"eq":"sent"}}       the viewer's filter (never the author's where)
&quotes.order=doc_no:desc,account.name:asc   the viewer's sort, up to four keys
&quotes.q=QT-2026                            the search box
&quotes.after=<cursor>                       the page

A Table or Board keeps the viewer’s filter, sort, search and page in the URL under its key — the collection name by default; set key when a page shows the same collection twice. The author’s where is never in the URL. On load each condition and each sort key is decoded on its own against the collection: one that no longer applies is dropped with a notice and the rest apply, so a link never puts a view in an error state.

  • Apps — apps, pages and groups
  • UI components — RecordShell, representations and the view popover