Skip to content
CodeAtlas UI

Layout

Page layouts

Ready-made page layouts for lists, forms, settings and dashboards, built from AppList, AppForm, AppSettings and PageShell.

<script>
  import { AppList, AppForm, AppSettings, PageShell } from "@codeatlasdev/ui";
</script>

These layouts fill the content area of the app shell and manage their own scrolling, so give them a parent with a fixed or flexible height. AppForm has its own page, see AppForm.

AppList

Pass data and the layout handles search, filters and pagination.

Users

4 of 4

UserRoleStatus
AL
Ana Lima
AdminActive
CM
Carlos Melo
EditorActive
DK
Diana Kwan
ViewerInactive
ES
Eduardo S.
EditorActive
Code
svelte
<script lang="ts">
  import { AppList, Button, FilterGroup, SimpleTable, StatusChip, UserCell } from '@codeatlasdev/ui';
  import { Plus } from '@lucide/svelte';

  const ALL = [
    { id: 1, name: 'Ana Lima', email: 'ana@acme.com', role: 'Admin', status: 'active' },
    { id: 2, name: 'Carlos Melo', email: 'carlos@apex.io', role: 'Editor', status: 'active' },
    { id: 3, name: 'Diana Kwan', email: 'diana@nova.dev', role: 'Viewer', status: 'inactive' },
    { id: 4, name: 'Eduardo S.', email: 'edu@mesh.ai', role: 'Editor', status: 'active' },
  ];
  const roleOpts = [
    { value: 'Admin', label: 'Admin' },
    { value: 'Editor', label: 'Editor' },
    { value: 'Viewer', label: 'Viewer' },
  ];
</script>

<div class="frame">
  <AppList title="Users" data={ALL} searchKeys={['name', 'email']} perPage={4}>
    {#snippet actions()}
      <Button variant="filled" size="sm">
        {#snippet leading()}<Plus size={14} />{/snippet}
        New user
      </Button>
    {/snippet}
    {#snippet filters(list)}
      <FilterGroup options={roleOpts} value={list.filters['role'] ?? 'all'} onchange={(v) => list.setFilter('role', v)} />
    {/snippet}
    {#snippet children(list)}
      <SimpleTable>
        <thead><tr><th>User</th><th>Role</th><th>Status</th></tr></thead>
        <tbody>
          {#each list.rows as u (u.id)}
            <tr>
              <td><UserCell name={u.name} email={u.email} /></td>
              <td>{u.role}</td>
              <td><StatusChip status={u.status === 'active' ? 'success' : 'neutral'} label={u.status === 'active' ? 'Active' : 'Inactive'} /></td>
            </tr>
          {/each}
        </tbody>
      </SimpleTable>
    {/snippet}
  </AppList>
</div>

<style>
  .frame {
    width: 100%;
    height: 420px;
    border-radius: var(--ca-radius-lg);
    box-shadow: inset 0 0 0 1px var(--ca-outline-subtle);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
</style>

AppSettings

Side navigation plus content. The active tab is managed internally.

Settings

Workspace
Code
svelte
<script lang="ts">
  import { AppSettings, Button, FormSection, Switch, TextField } from '@codeatlasdev/ui';
  import { Settings, Shield } from '@lucide/svelte';

  const TABS = [
    { value: 'general', label: 'General', icon: Settings },
    { value: 'security', label: 'Security', icon: Shield },
  ];
  let wsName = $state('My Workspace');
</script>

<div class="frame">
  <AppSettings title="Settings" tabs={TABS}>
    {#snippet actions()}
      <Button variant="filled" size="sm">Save</Button>
    {/snippet}
    {#snippet children(tab)}
      {#if tab === 'general'}
        <FormSection title="Workspace">
          <TextField label="Name" bind:value={wsName} />
          <TextField label="Slug" value="my-workspace" />
        </FormSection>
      {:else if tab === 'security'}
        <FormSection title="Authentication" layout="list">
          <Switch label="Two-factor authentication" />
          <Switch label="Single sign-on (SSO)" />
        </FormSection>
      {/if}
    {/snippet}
  </AppSettings>
</div>

<style>
  .frame {
    width: 100%;
    height: 380px;
    border-radius: var(--ca-radius-lg);
    box-shadow: inset 0 0 0 1px var(--ca-outline-subtle);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
</style>

PageShell

A scrollable container for dashboards and non-CRUD pages.

Dashboard

Revenue

$118k
↑+23.4%

Users

24.8k
↑+8.1%

Growth

34%
↑+5.6%

Uptime

99.9%
↑+0.1%

Chart or data table goes here

Code
svelte
<script lang="ts">
  import { PageShell, KpiCard, GlassCard, Grid } from '@codeatlasdev/ui';
  import { Users, DollarSign, TrendingUp, Activity } from '@lucide/svelte';
</script>

<div class="frame">
  <PageShell title="Dashboard">
    <Grid cols="repeat(auto-fill,minmax(160px,1fr))" gap={12}>
      <KpiCard title="Revenue" value="$118k" trend={23.4} icon={DollarSign} />
      <KpiCard title="Users" value="24.8k" trend={8.1} icon={Users} />
      <KpiCard title="Growth" value="34%" trend={5.6} icon={TrendingUp} />
      <KpiCard title="Uptime" value="99.9%" trend={0.1} icon={Activity} />
    </Grid>
    <GlassCard full>
      <p class="placeholder">Chart or data table goes here</p>
    </GlassCard>
  </PageShell>
</div>

<style>
  .frame {
    width: 100%;
    height: 420px;
    border-radius: var(--ca-radius-lg);
    box-shadow: inset 0 0 0 1px var(--ca-outline-subtle);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .placeholder {
    margin: 0;
    height: 120px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ca-text-hint);
    font-size: var(--ca-font-size-body2);
  }
</style>

AppList props

PropTypeDefaultDescription
titlestring–Page title.
descriptionstring–Subtitle. Derived from the list count when omitted in data mode.
dataT[]–Full dataset. When set, AppList manages search, filters and pagination.
searchKeys(keyof T)[]–Fields included in text search. Defaults to all string fields.
perPagenumber20Rows per page.
idKeykeyof T'id'Row identifier field.
searchPlaceholderstring–Placeholder of the search input.
ofLabelstring'of'Word between the numbers in the count and page info.
filtersSnippet<[ListCtx]>–Extra filter controls after the search input.
childrenSnippet<[ListCtx]> | Snippet–Table or grid content. Receives the list context in data mode.
actionsSnippet–Top-right slot for the primary action.
toolbarSnippet–Manual toolbar, used only without data.
emptySnippet<[ListCtx]> | Snippet–Shown when filtered rows are zero.
footerSnippet–Manual footer, used only without data.
maxWidthstring–Maximum width of the content.
classstring''Extra class names.

AppSettings props

PropTypeDefaultDescription
titlestring–Page title.
descriptionstring–Subtitle.
tabs{ value, label, icon?, badge?, danger? }[]–Side navigation entries.
defaultTabstring–Initial tab. Defaults to the first.
activeTabstring–Bindable active tab for external control.
onTabChange(value: string) => void–Called when the tab changes.
actionsSnippet–Top-right slot for save and cancel buttons.
childrenSnippet<[string]>–Content. Receives the active tab value.
classstring''Extra class names.