Components
@memoturn/ui is the shared component library used by the Memoturn dashboard and this docs site. It’s built on shadcn/ui new-york-v4, Radix UI primitives, Tailwind CSS v4, and a brand color overlay defined in tokens.css.
The library is workspace-internal today ("private": true). There’s no npm release.
Foundation
Section titled “Foundation”The 57 component primitives are sourced verbatim from shadcn/ui’s new-york-v4 registry. Brand identity comes through three vectors:
--primary: brand teal (lagoon-deeplight /lagoondark) appears on every button, focus ring, accent, and active state.- Display typography: Inter Tight headings and Manrope body give the surface its voice without painting it.
- Atmospheric decoration:
.atoll-bandtopographic texture appears on hero/CTA/empty surfaces; brand gradients (--gradient-lagoon,--gradient-atoll) on hero badges and the user avatar.
Structural surfaces (--background, --card, --popover, --border, --muted, --accent) use shadcn’s neutral oklch tokens: pure white in light, pure dark in dark mode, soft gray borders. The docs landing (HeroCard, LinkChip, FeatureCard, CTA) uses --docs-panel-bg (sand-tinted page-white in light, card-tinted in dark) with hairline --docs-line borders; the closing-band CTA lights up the brand --gradient-atoll as the page’s single brand moment.
Tokens
Section titled “Tokens”Defined in packages/ui/src/styles/tokens.css. Composed via Tailwind v4 @theme inline so every token is addressable as a Tailwind utility (bg-card, text-primary, border-input, etc.).
Brand palette (always addressable)
Section titled “Brand palette (always addressable)”| Token | Light | Dark | Use |
|---|---|---|---|
--lagoon | #4fb8b2 | #60d7cf | Bright accent (bg-lagoon) |
--lagoon-deep | #328f97 | #8de5db | Deep accent (text-lagoon-deep) |
--palm | #2f6a4a | #6ec89a | Secondary accent / success |
--sand / --foam | warm pales | dark scaled | Atmospheric tints |
--accent-warm | #e89456 | #f5b169 | Warm accent (warnings, CTA highlights) |
These exist for hero/CTA decoration. Don’t reach for them in primitives. Primitives consume the semantic tokens below, which already route through --primary etc.
Semantic tokens (shadcn surface)
Section titled “Semantic tokens (shadcn surface)”| Family | Tokens |
|---|---|
| Surfaces | --background, --card, --popover, --surface (muted panels), --sidebar |
| Text | --foreground, --card-foreground, --muted-foreground, --popover-foreground |
| Action | --primary (brand teal), --secondary, --accent, --destructive, --success, --warning |
| Form | --border, --input, --ring (also brand teal) |
| Code | --code, --code-foreground, --code-highlight, --code-number |
| Chart | --chart-1 through --chart-5 (brand-sequenced) |
| Selection | --selection, --selection-foreground |
| Overlay | --overlay, --overlay-strong, --overlay-subtle (three-tier) |
Every token has a dark counterpart that flips on :root[data-theme="dark"], .dark class, or @media (prefers-color-scheme: dark).
Radius
Section titled “Radius”--radius defaults to 0.375rem (~6px). Derived scale: --radius-sm through --radius-4xl via calc(var(--radius) * N). Use Tailwind utilities: rounded-sm, rounded-md, rounded-lg, rounded-xl.
Shadow
Section titled “Shadow”Tailwind’s shadow-xs / shadow-sm / shadow-md / shadow-lg are overridden with brand green-tinted shadows in light mode, neutral darkness in dark mode. Every primitive that uses these utilities picks up the brand atmosphere automatically.
Typography
Section titled “Typography”- Body / UI: Manrope,
--font-sans/font-sans - Display / heading: Inter Tight,
--font-heading/font-heading - Code: system mono stack,
--font-mono/font-mono
Manrope provides humanist warmth in body copy. Inter Tight (used by Linear, Vercel, Anthropic) provides modern display character without the cartoony ball terminals of Fraunces.
Two utility classes give you the brand voice:
.kicker: small uppercase tracked label (KICKER LIKE THIS). Composes with margin/color modifiers:class="kicker mb-2 text-primary"..display-title: Inter Tight semibold, tight tracking,1.05line-height. Use for hero/section/card titles.
Page-shell utilities
Section titled “Page-shell utilities”These define the dashboard’s visual rhythm without touching component primitives:
.page-wrap: fluid full-width container, soft cap at 1800px, padding scalesclamp(1rem, 3vw, 3rem)..atoll-band: topographic concentric-arc texture at 6% opacity with a radial mask; compose on cards or sections for ambient depth..rise-in: entrance animation; respectsprefers-reduced-motion..shimmer: left-to-right brand-tinted gradient sweep; powers theSkeletonprimitive..nav-link: underline indicator that grows from left on hover/active; brand-teal stroke.
Primitives
Section titled “Primitives”All 57 shadcn new-york-v4 components are exported from @memoturn/ui. Categories below highlight the most-used; the full list is in packages/ui/src/index.ts.
Form controls
Section titled “Form controls”Button, Input, Textarea, Select, NativeSelect, Checkbox, RadioGroup, Switch, Slider, Label, Form (react-hook-form integration), Field, FieldGroup, InputGroup, InputOTP, Combobox, Toggle, ToggleGroup, ButtonGroup.
Every form control shares one focus language: ring-2 ring-ring/30 on focus, hover:border-ring/40 preview, brand-teal ring (because --ring resolves to --primary).
Overlays
Section titled “Overlays”Dialog, AlertDialog, Sheet, Drawer, Popover, HoverCard, Tooltip, DropdownMenu, ContextMenu, Menubar, Command (CommandDialog for ⌘K palettes).
All use bg-popover for content and the brand-tinted overlay scrim. data-slot attributes on every element for inspect-and-style.
Layout
Section titled “Layout”Card (+ CardHeader/CardTitle/CardDescription/CardContent/CardFooter/CardAction), Sidebar, Resizable panels, ScrollArea, Separator, AspectRatio, Tabs.
CardTitle / DialogTitle / SheetTitle / DrawerTitle / EmptyTitle use font-heading (Inter Tight). Every modal display moment is in the brand voice.
Data display
Section titled “Data display”Table, Badge, Avatar (+ AvatarFallback / AvatarBadge / AvatarGroup), Item (data row primitive), Empty (EmptyTitle/EmptyDescription/EmptyMedia), Pagination, Breadcrumb, Accordion, Collapsible, Calendar, Carousel, Chart (recharts wrapper), Progress, Skeleton, Spinner, Kbd.
Badge extends shadcn defaults with three brand variants (dense primary tint, lexical palm tint, hot warm tint) used for search-leg color coding. Skeleton uses .shimmer for brand-tinted loading.
Toasts
Section titled “Toasts”Toaster (Sonner-backed) + the toast helper. Mount once at the app root:
import { Toaster } from "@memoturn/ui";
export function RootLayout() { return ( <> {/* …app… */} <Toaster /> </> );}Then fire from anywhere:
import { toast } from "@memoturn/ui";
await revokeKey(id);toast.success(`Revoked "${name}"`);
// or with a descriptiontoast.error({ title: "Revoke failed", description: err.message });The helper exposes success, error, info, and dismiss. Each type gets a left-border color stripe (success → palm, info → primary, warning → accent-warm, error → destructive) and a brand-tinted icon.
Composites
Section titled “Composites”Higher-level building blocks specific to the Memoturn brand voice. They compose primitives plus brand decoration (atoll-band, gradients, kicker labels).
| Component | Source | Use |
|---|---|---|
Hero | Hero.tsx | Landing / section hero with kicker, title, description, action slots. |
FeatureCard | FeatureCard.tsx | Icon + kicker + title + description + footer; lifts on hover. |
CTA | CTA.tsx | Brand-gradient call-to-action panel with primary + secondary actions. |
EmptyState | EmptyState.tsx | Centered empty state with BrandMark, title, description, action. |
CodeBlock | CodeBlock.tsx | Snippet block with copy-to-clipboard button. |
Logo | Logo.tsx | 4 variants: full, mark, wordmark, chip. |
BrandMark | BrandMark.tsx | Standalone SVG mark. |
ThemeToggle | ThemeToggle.tsx | Light / dark / auto switcher; persists to localStorage. |
Adding a shadcn component
Section titled “Adding a shadcn component”The dashboard wires apps/app/components.json so the shadcn CLI installs into packages/ui/src/components/:
pnpm exec shadcn add <component>After install, normalize the imports to relative paths (@/lib/utils → ../lib/utils, @/components/ui/... → ./...) and re-export from packages/ui/src/index.ts.
Theming consumers
Section titled “Theming consumers”Both the Memoturn dashboard (TanStack Start on Workers) and this docs site (Astro + Starlight) consume tokens.css directly. The dashboard mounts via Tailwind v4’s @theme inline directive; the docs site @imports and adds back-compat aliases for older brand-tinted decoration.
To embed @memoturn/ui in a third app, import the tokens once at the top of your global stylesheet, then add the Tailwind layer:
@import "tailwindcss";@import "tw-animate-css";@import "@memoturn/ui/styles/tokens.css";@import "@memoturn/ui/styles/base.css";
@source "../node_modules/@memoturn/ui/src/components/**/*.{ts,tsx}";
@custom-variant dark (&:is([data-theme="dark"] *, .dark *));Accessibility
Section titled “Accessibility”- Every interactive primitive has a visible
focus-visiblering driven by--ring(brand teal). - Radix-backed components inherit Radix’s keyboard and screen-reader support.
- Form inputs respect
aria-invalid(destructive ring + border) and pair with<Label htmlFor>. Emptyand error boundaries use semantic headings; modal titles use properDialog.Title.- Reduced motion:
.rise-inand.shimmerhonorprefers-reduced-motion: reduce.
If you find a component that fails an axe-core check, please email support@memoturn.ai. Accessibility regressions are bugs, not enhancements.