Component library
One component per need
Exactly what an app may use, one example each. A variant is a property on the component, never a new component. A new component or variant needs Daniel's yes.
Needs
Behov → komponent. Allt annat byggs inte ur designsystemet.
| Behov | Komponent |
|---|---|
| Sida och platta | Page + PageSection |
| Dashboard: grupp av små plattor | DashboardGroup |
| Skal: meny | ShellMenu |
| Skal: konto och enhet (M2) | ShellFooter |
| Knapp | Button |
| Status | Badge |
| Formulärfält | Label, Input, Textarea, Select, Checkbox |
| Meddelande på sidan | Alert |
| Kvitto efter en handling | Toaster (toast) |
| Dialog | Dialog |
| Sidopanel | Sheet |
| Meny | DropdownMenu |
| Hjälptext vid hovring | Tooltip |
| Ruta som fälls ut vid klick | Popover |
| Flikar | Tabs |
| Fäll ut och ihop | Collapsible |
| Laddar | Skeleton |
| Tabell | Table |
| Sifferkort | Stat |
| Tomt läge | EmptyState |
| Datans ålder | Freshness |
| Länk som förhämtar | FwLink |
| Diagram | ChartStack |
| Minigraf i en rad | MiniSpark, MiniProgress |
| Appens ikon | FaviconCube |
Page + PageSection
Rubrik och verktygsrad på bakgrunden, allt annat i plattor. PageSection är plattan; PageFrame och SiteHeader är ramen runt.
Tokens: --background, --surface, --panel-border, --space-2
Invoices
Fakturor per unit, senaste 30 dagarna.
Summering
Öppna
Skickade
Försenade
Fakturor
| Request | Merchant | Unit | Amount |
|---|---|---|---|
| REQ-2041 | Sam Sport AB | SAM | 1 234,50 |
| REQ-2042 | Hepp Design och Inredning Aktiebolag i Göteborg | HEP | 89,00 |
| REQ-2043 | Gesh Shoes AB | GSH | 12 840,75 |
| REQ-2044 | Sam Sport AB | SAM | −310,00 |
En vanlig section utan PageSection: layouten gör den till en platta.
| Request | Owner |
|---|---|
| REQ-2041 | a.lind |
| REQ-2042 | j.holm |
DashboardGroup
Rubriken på rutnätet och bara små plattor, ingen stor platta runt gruppen (oaas-api#21832). columns är en egenskap.
Tokens: --surface, --panel-border
Dagens nyckeltal
Varianter i core
Öppna avvikelser
Typography
Tokens: --foreground, --muted-foreground, --leading-body, --h2-size
Label · 13 px, white, uppercase
Heading · 26 px
Section heading · 26 px
Subheading · 13 px, uppercase
Body text is 13 px on an 18 px line (--leading-body) and always muted. The bright text colour is reserved for headings, labels in focus, data and values. Numbers use Swedish formatting: 1 234,50 SEK and 12 408 rows. A link in running text is underlined.
Badge
variant: success, warning, error, count; pulse blinks.
Tokens: --lamp-success, --lamp-warning, --lamp-danger
Label, Input, Textarea, Select, Checkbox
Ett val av flera är Select, på/av är Checkbox.
Tokens: --border, --primary, --control-h, --muted-foreground-2
Visible to everyone who can see the pump.
Alert
variant: info, success, warning, destructive.
Tokens: --lamp-success, --lamp-warning, --lamp-danger, --muted-foreground
Warning
Toaster
toast.success / toast.error ur sonner; Toaster står en gång i appens rot.
Dialog
Bekräfta en radering: samma Dialog med en destructive-knapp.
New pump
The pump fetches data from the source on a schedule. You can change the settings later.
Sheet
Detaljer bredvid en lista; side är en egenskap (right som standard).
Tooltip
Popover
Tabs
Collapsible
Skeleton
Table
Paging (paging), virtualisering över 200 rader och dragbara kolumner (resizableId) är egenskaper på Table.
Tokens: --foreground, --muted-foreground, --table-head-bg, --table-head-border, --divider
En rad per cell. Två värden = två kolumner.
För långt innehåll klipps med "…" och radbryts aldrig. Hela värdet syns i en tooltip (title) när man hovrar över cellen.
Data i celler är grå; bara rubrikraden är vit.
Breda tabeller scrollar i sidled; scrollbaren syns alltid i fönstret.
Kolumnerna dras bredare eller smalare i rubrikradens kant; dubbelklick återställer.
En tabell visar alltid hur många rader som finns och om fler finns.
| Unit | Merchant |
|---|---|
| HEP | Hepp Design och Inredning Aktiebolag i Göteborg, avdelning Returer och Reklamationer |
| Request | Merchant | Unit | Status | Latency (ms) | Amount (SEK) | Action |
|---|---|---|---|---|---|---|
| REQ-2041 | Sam Sport AB | SAM | active | 42 | 1 234,50 | |
| REQ-2042 | Hepp Design och Inredning Aktiebolag i Göteborg | HEP | pending | — | 89,00 | |
| REQ-2043 | Gesh Shoes AB | GSH | error | 1 204 | 12 840,75 | |
| REQ-2044 | Sam Sport AB | SAM | success | 88 | −310,00 |
Stat
delta ritar ▲/▼ %, data en sparkline; value={null} ritar – och emptyHint säger varför (oaas-api#21938).
Tokens: --surface, --panel-border, --lamp-success, --lamp-danger
Rows today
Visitors
No visitor data from your store yet
EmptyState
No runs yet
Freshness
Shows only when the data is older than staleMs. A green pulsing lamp while it fetches.
Freshness · src/lib/data
13 px, muted. Ticks every 30 s. The row is 32 px with and without text.
import { Freshness, useFwQuery } from "@/lib/data";
const q = useFwQuery({ key: ["stats"], fetcher: mockStats });
<Freshness updatedAt={q.updatedAt} isFetching={q.isFetching} staleMs={60_000} />FwLink
Hover or keyboard focus on a link fetches the page's query; touch does not.
Stats — hover the row, then click: the numbers are already here.
Not opened.
/components — prefetched by the route's loader when a header link to it is hovered.
Rows
Units
Works
Alerts
- No fetch yet.
// a route: the loader prefetches, the page reads the same key
const statsQuery = { key: ["stats"], fetcher: ({ signal }) => getStats(signal) };
export const Route = createFileRoute("/dashboard")({
loader: ({ context }) => prefetchFwQuery(context.queryClient, statsQuery),
});
// TanStack Router: links are FwLink, the router has defaultPreload: "intent"
<ShellMenu renderLink={(l, p) => <FwLink to={l.to} {...p} />} … />
// no TanStack Router: a row's prefetch
{ key: "stats", label: "Stats", link, prefetch: () => prefetchFwQuery(qc, statsQuery) }ChartStack
Det enda diagrammet. variant="stack" (standard, en serie = staplar) eller "line".
Tokens: --primary, --chart-cell, --lamp-success, --lamp-danger
MiniSpark, MiniProgress
16 px höga, ryms i en 32 px tabellrad.
| Pump | Rows, 7 days | Sync |
|---|---|---|
| pump-se-01 | 87 % |
FaviconCube
Appens ikon i applistan och skalets rubrik.
Tokens
Värdet i mörkt och ljust läge, läst ur CSS:en. Skriv alltid tokennamnet, aldrig ett råvärde.
| Färger | Mörkt | Ljust | Roll |
|---|---|---|---|
| --foreground | … | … | rubriker, rubrikrad i tabeller, värden i fokus |
| --secondary-foreground | … | … | sekundär text |
| --muted-foreground | … | … | brödtext, data i tabellceller, etiketter |
| --muted-foreground-2 | … | … | placeholder, hint |
| --primary | … | … | enda accenten: länkar, fokus, primärknapp |
| --primary-bright | … | … | lila text, knapptext |
| --primary-hover-fg | … | … | knapptext vid hover |
| --nav-underline | … | … | aktiv navigeringslänk |
| --success | … | … | grön knapp: kant och ton |
| --success-fg | … | … | grön knapptext |
| --warning | … | … | gul knapp: kant och ton |
| --warning-fg | … | … | gul knapptext |
| --destructive | … | … | röd knapp: kant och ton |
| --destructive-fg | … | … | röd knapptext |
| --disabled | … | … | avstängd: streckad kant |
| --disabled-foreground | … | … | avstängd: text |
| --border | … | … | kant på fält och knappar |
| --table-head-bg | … | … | tabellhuvudets band |
| --table-head-border | … | … | tabellhuvudets ram |
| Lampor | Mörkt | Ljust | Roll |
|---|---|---|---|
| --lamp-success | … | … | grön lampa, --fw-lg: OK, live |
| --lamp-warning | … | … | gul lampa, --fw-ly: varning, stale |
| --lamp-danger | … | … | röd lampa, --fw-lr: fel, offline |
| --btn-tint | … | … | tonen i knappar och lampor (12 %) |
| Typskala | Mörkt | Ljust | Roll |
|---|---|---|---|
| .text-sm | 13px | 13px | brödtext, etiketter, data — systemets standard |
| --leading-body | … | … | radavstånd i brödtext (13 på 18) |
| .text-xl | 26px / 39px | 26px / 39px | sidrubrik |
| --h2-size | … | … | sektionsrubrik |
| .text-btn | 12px | 12px | knapptext, versaler |
| .label-mono | 13px | 13px | etikett, versaler |
| --font-sans | JetBrains Mono 700 | JetBrains Mono 700 | enda typsnittet, en vikt |
| Avstånd och kontrollhöjd | Mörkt | Ljust | Roll |
|---|---|---|---|
| --space-1 | … | … | 8 px — rutnätets steg |
| --space-2 | … | … | 16 px — sidans padding, mellan paneler |
| --space-3 | … | … | 24 px — inne i paneler |
| --space-4 | … | … | 48 px |
| --space-5 | … | … | 64 px |
| --section-gap | … | … | före en sektionsrubrik |
| --control-h | … | … | knapp, fält, sök, select, datum; 44 px under 768 px |
| --radius | … | … | inga rundade hörn |
| Ytor och rutnät | Mörkt | Ljust | Roll |
|---|---|---|---|
| --background | … | … | sidan, under 8 px-rutnätet (alias --page) |
| --surface | … | … | paneler, card, popover, menyn |
| --btn-base | … | … | knappens grund under tonen |
| --panel-border | … | … | panelens kant, 1 px inset (.panel) |
| --divider | … | … | streckad radlinje i tabeller |
| --grid-line | … | … | linjerna i 8 px-rutnätet på body |
| --chart-cell | … | … | rutnätets cell i diagrammen |
| .surfaces-standard | — | — | klass: vanliga ytor i stället för inverterade |