Next Steps
Get started with Kumo
<script lang="ts">
import { ArrowRight } from 'phosphor-svelte';
import { Button, LayerCard } from 'kumo-svelte';
</script>
<LayerCard>
<LayerCard.Secondary class="flex items-center justify-between">
<div>Next Steps</div>
<Button variant="ghost" size="sm" shape="square" aria-label="Go to next steps">
<ArrowRight class="size-4" />
</Button>
</LayerCard.Secondary>
<LayerCard.Primary>Get started with Kumo</LayerCard.Primary>
</LayerCard> Installation
Barrel
import { LayerCard } from 'kumo-svelte'; Granular
import { LayerCard } from 'kumo-svelte/components/layer-card';Usage
<script lang="ts">import { LayerCard } from "kumo-svelte";</script> <LayerCard class="w-[250px]"> <LayerCard.Secondary>Documentation</LayerCard.Secondary> <LayerCard.Primary>Learn how to use Kumo components</LayerCard.Primary> </LayerCard> LayerCard also supports a simple surface-style mode for cases
where you do not need a secondary header row. In those cases, render content
directly inside LayerCard instead of wrapping it in LayerCard.Primary. <script lang="ts">import { LayerCard } from "kumo-svelte";</script> <LayerCard class="w-[250px] p-4"> Learn how to use Kumo components </LayerCard>Examples
Basic Card
Getting Started
Quick start guide for new users
<script lang="ts">
import { LayerCard } from 'kumo-svelte';
</script>
<LayerCard class="w-[250px]">
<LayerCard.Secondary>Getting Started</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm text-kumo-subtle">Quick start guide for new users</p>
</LayerCard.Primary>
</LayerCard> Surface-style Card
For simple card containers, render content directly inside LayerCard without LayerCard.Primary.
Quick start guide for new users
<script lang="ts">
import { LayerCard } from 'kumo-svelte';
</script>
<LayerCard class="w-[250px] p-4">
<p class="text-sm text-kumo-subtle">Quick start guide for new users</p>
</LayerCard> Multiple Cards
Components
Browse all components
Examples
View code examples
<script lang="ts">
import { LayerCard } from 'kumo-svelte';
</script>
<div class="flex gap-4">
<LayerCard class="w-[200px]">
<LayerCard.Secondary>Components</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm">Browse all components</p>
</LayerCard.Primary>
</LayerCard>
<LayerCard class="w-[200px]">
<LayerCard.Secondary>Examples</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm">View code examples</p>
</LayerCard.Primary>
</LayerCard>
</div> Filter Toolbar with Small Tabs
Combine Tabs size="sm" with Input size="sm" inside a
LayerCard for compact filter toolbars. Both share the same h-6.5 (26px) height.
Subrequests
Origin Requests Duration
challenges.cloudflare.com
2xx 1
95.4msUnknown
2xx 19 4xx 7
463.7msapi.example.com
2xx 42 4xx 3
128.1msShowing 3 of 3
<script lang="ts">
import { Badge, Input, LayerCard, Tabs } from 'kumo-svelte';
const ORIGINS = [
{ origin: 'challenges.cloudflare.com', s2xx: 1, s4xx: 0, duration: '95.4ms' },
{ origin: 'Unknown', s2xx: 19, s4xx: 7, duration: '463.7ms' },
{ origin: 'api.example.com', s2xx: 42, s4xx: 3, duration: '128.1ms' }
];
type StatusFilter = 'all' | '2xx' | '3xx' | '4xx' | '5xx';
let filter: StatusFilter = $state('all');
let search = $state('');
const tabs = [
{ value: 'all', label: 'All' },
{ value: '2xx', label: '2xx' },
{ value: '3xx', label: '3xx' },
{ value: '4xx', label: '4xx' },
{ value: '5xx', label: '5xx' }
];
const filtered = $derived(
ORIGINS.filter((origin) => {
if (filter === '2xx' && origin.s2xx === 0) return false;
if (filter === '4xx' && origin.s4xx === 0) return false;
if (search && !origin.origin.toLowerCase().includes(search.toLowerCase())) return false;
return true;
})
);
</script>
<LayerCard class="w-full max-w-[540px]">
<LayerCard.Secondary>Subrequests</LayerCard.Secondary>
<LayerCard.Primary>
<div class="mb-2 flex items-center gap-3">
<Input
size="sm"
placeholder="Filter origins..."
aria-label="Filter origins"
bind:value={search}
class="min-w-0 flex-1"
/>
<Tabs
variant="segmented"
size="sm"
class="shrink-0"
{tabs}
bind:value={filter}
/>
</div>
<div class="-mx-1 text-sm">
<div
class="grid grid-cols-[1fr_auto_auto] gap-x-4 border-b border-kumo-fill px-1 pb-2 text-xs font-medium text-kumo-subtle"
>
<span>Origin</span>
<span class="w-28 text-right">Requests</span>
<span class="w-20 text-right">Duration</span>
</div>
{#each filtered as row, i (row.origin)}
<div
class={[
'grid grid-cols-[1fr_auto_auto] items-center gap-x-4 px-1 py-2.5',
i < filtered.length - 1 && 'border-b border-kumo-hairline'
]}
>
<span class="truncate font-medium text-kumo-default">{row.origin}</span>
<div class="flex w-28 items-center justify-end gap-1.5">
{#if row.s2xx > 0}
<Badge variant="success">2xx {row.s2xx}</Badge>
{/if}
{#if row.s4xx > 0}
<Badge variant="error">4xx {row.s4xx}</Badge>
{/if}
</div>
<span class="w-20 text-right text-kumo-subtle">{row.duration}</span>
</div>
{/each}
</div>
<div class="-mx-1 border-t border-kumo-fill pt-2 text-xs text-kumo-subtle">
Showing {filtered.length} of {ORIGINS.length}
</div>
</LayerCard.Primary>
</LayerCard> Test IDs
LayerCard.Primary and LayerCard.Secondary accept all
standard HTML attributes, including data-testid for testing. Getting Started
Quick start guide for new users
<script lang="ts">
import { LayerCard } from 'kumo-svelte';
</script>
<LayerCard class="w-[250px]">
<LayerCard.Secondary data-testid="card-header">
Getting Started
</LayerCard.Secondary>
<LayerCard.Primary data-testid="card-body">
<p class="text-sm text-kumo-subtle">Quick start guide for new users</p>
</LayerCard.Primary>
</LayerCard> API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| children | Snippet | - | Child snippet rendered by the component. |
| class | string | - | Additional classes merged onto the root element. |
| as | string | "div" | as prop. |