Skip to content
LoidoltTheme 0.11.1
Svelte 5

Patterns

How the pieces go together.

The compositions worth copying: the editor shell, the responsive navigation swap, and the states a data view has to cover.

The editor shell

Top bar, context bar, and a three-column workspace. The columns follow the panes that are actually rendered, so the same component serves a one-, two-, or three-column tool.

Topo StudioProject 04
TerrainCrater LakeReal-data preview ready
Preview Crater Lake

12 layers · SVG

Guides on
<!-- A pane collapses by not being rendered, so nothing inside it
     stays in the tab order while it is hidden. -->
<Workspace {sidebarOpen} {inspectorOpen}>…</Workspace>

Narrow viewports

Below the compact breakpoint a navigation column has nowhere to sit. Swap it for a Drawer: same content, modal presentation, focus trapped while it is open. This site does exactly that — narrow the window and the component list moves behind Browse.

The drawer that replaces the column
<script lang="ts">
  import { breakpointQuery, createMediaQuery, Drawer, Sidebar, Workspace } from '@loidolt/theme-svelte';

  const compact = createMediaQuery(breakpointQuery('compact'));
  let navOpen = $state(false);
</script>

{#if compact.matches}
  <Drawer title="Navigation" bind:open={navOpen}>
    {#snippet trigger()}Menu{/snippet}
    {@render nav()}
  </Drawer>
{/if}

<Workspace sidebarOpen={!compact.matches}>
  {#snippet sidebar()}<Sidebar label="Navigation">{@render nav()}</Sidebar>{/snippet}
  <main>…</main>
</Workspace>

Data states

A list has four states, not one: loading, empty, populated, and error. Skeleton covers the first, EmptyState the second, and Alert the last. The table cannot count your rows, so decide the empty case where the data is.

{#snippet nothingYet()}
  <EmptyState title="No cut files yet" description="Import a drawing to get started." />
{/snippet}

<Table caption="Cut files" columns={3} empty={rows.length === 0 ? nothingYet : undefined}>
  …
</Table>