Components
Every component in @9klabs/design, grouped by what it is for. Each page has live demos, the API read from the component's source, and a prompt for agents.
Layout & surfaces
- ContainerThe page column: a centred, width-capped wrapper that sets only width and centring, so a section, a main or a bar of chrome all share one measure. I9kNavigation, I9kFooter and I9kPageContainer already sit in it.
- GridCSS grid layout wrapper with a fixed 1/2/3-column or auto-filling track and a size-driven gap. Collapses to one column on narrow viewports.
- PageContainerCentered, width-capped page wrapper with a size-driven horizontal gutter and a minimum height, in the shared page column. Use it once per page as the outermost content wrapper; for a section of a page use I9kContainer.
- ClusterFlex-wrap row that keeps items center-aligned and evenly gapped, wrapping onto new lines instead of overflowing. Use it for groups of buttons, badges, or other inline controls.
- PanelOpaque, bordered surface for grouping content. Use it as the standard card/surface wrapper wherever content needs visual separation from the page background.
Content
- TextText primitive for body copy and intros. Use it for any paragraph-level content that should follow the design system type scale rather than reaching for a bare <p>.
- SectionHeadingHeading with an optional description for introducing a section of a page. Use it above any grouped block of content — a card grid, a list, a feature set.
- PageHeaderLarge hero-style heading for the top of a page, with optional subtitle, description, actions, and avatar. Use it once per page, at the top.
- ArticleHeaderWide banner image for the top of an article, with a generated watermark fallback when there is no image. Use it once, at the top of an article body.
- BadgeSmall inline label for status, category, or tag content. Use it next to a heading or inside a card to mark a short piece of metadata.
- StatValue/label/source stack for a single statistic. Use it in a grid of a few key numbers, such as metrics on an about page or a pricing comparison.
- LevelMeterA short row of rising steps with some filled, for a level out of a few, such as a course level. It is a named meter, the level can be shown in words beside it, and a description can explain it in a tooltip.
- StickerA die-cut sticker with a holographic foil that follows the pointer, for a badge a person has earned. The foil is drawn over the sticker image and clipped to its shape; it stands still for people who prefer reduced motion.
- LinkCardClickable card linking out to an external resource, with a name, description, and optional image/badge/arrow. Use it for a grid of projects, articles, or external links.
- TimelineCardDated entry in a vertical timeline/rail, with a title, body, and optional thumbnail. Use it for a chronological list of talks, posts, or events.
- ProfileCardCard pairing an avatar with a name, bio, and optional action links. Use it for an author byline, a team member card, or a speaker bio.
- AvatarA round picture of a person or account from any image URL, with a fallback slot (such as initials) for when there is no picture.
- BandanaAvatarA large round photo of a person with a bandana that draws itself across the eyes, once when the images load and again when a pointer enters. The bandana never shows for people who prefer reduced motion.
- CollapsibleNative, independently expanding disclosure surface with slots for rich summary and body content.
- SectionTitled page section, named by its heading, whose header carries its own actions and an optional toolbar. It can collapse behind a disclosure button inside the heading, controlled with v-model:open or left to manage itself. The primary variant fills it with the brand green, and fullWidth lets that fill reach the viewport edges as a band.
- FaqListList of collapsible question/answer pairs composed from I9kCollapsible. Use it for plain-text FAQ content without wiring open/close state.
- GithubEmbedCompact card linking to a GitHub repository by "owner/repo" name. Use it to reference a specific repo inline in content, e.g. a blog post or project list.
- IconSVG icon rendered from the library's built-in icon set by name. Use it anywhere a small inline glyph is needed — social links, nav items, buttons.
- AsciiEmojiSmall text-based emoticon (e.g. "^_^") rendered in a monospace face, for a lighter-touch alternative to emoji or icon glyphs.
- NinoNino, the 9k pixel mascot: an inline-SVG character with eight expressions (one of them hide and seek, one dizzy), continuous ambient life (breathing, blinks, an antenna pulse, idle glances), a 300ms face morph on mood changes, one-shot actions (wave, jump, nod, shake, dizzy), a talking state, a logical gaze direction, and motion that switches itself off for reduced-motion visitors.
- NinoMazeA small game for a 404 page: walk Nino through a pixel maze to his house while bugs patrol the corridors. Every seed builds one maze, the same seed always builds the same maze, and every maze is checked to be winnable. Keyboard, d-pad and screen-reader playable, with optional chiptune sound.
- NinoSkyA pixel night sky with Nino drifting through it: twinkling dotted stars, two dotted planets, eyes that follow the pointer, a boop (a new face, a spin and a burst of sparkles) on click, tap, Enter or Space, and a drag: pick Nino up, throw him around the window, and if he comes to rest above the sky he swoops back to it, dizzy. It has no background of its own and follows the page theme. Made for the space under a footer.
- ChatThe shell of a scripted chat: a feature panel with a header (Nino, the bot name and actions), a scrolling live log of bubbles, and a sunken footer tray for the answer controls.
- ChatBubbleOne message in an I9kChat log: a bot bubble on the start side or a user bubble on the end side, with a typing indicator, a wide variant for rich results and an editable variant for revisiting an answer.
Forms
- ChatComposerThe free-text answer of an I9kChat footer: a rounded field with a send button. Enter sends; a multiline composer grows with the text and takes Shift+Enter for a new line.
- FieldField wrapper that renders a label, hint, and error, and provides id/size/validity context to one nested control. It is the provider side of the field composable; I9kInput, I9kTextarea, and I9kSelect are its consumers.
- CheckboxGroupAccessible checkbox fieldset for selecting multiple values with labels, descriptions, validation, and RTL support.
- InputSingle-line text input with an optional label, hint, and error state. Wires its own accessible ids, and inherits size and error state from a wrapping I9kField when there is one.
- TextareaMulti-line text control for longer form input. Wires its own id and ARIA attributes standalone, and inherits id, size, and error state from a wrapping I9kField when there is one.
- SelectNative single-select dropdown that auto-selects the option matching modelValue. Wires its own id and ARIA attributes standalone, and inherits id, size, and error state from a wrapping I9kField when there is one.
- PhoneInputPhone number input with a compact country-code picker: a flag-and-code face over a transparent native select that lists every country by name. Registers the number, not the picker, with a wrapping I9kField.
- RadioGroupFieldset of mutually exclusive radio options, rendered as a stacked list or a card grid. Unlike I9kInput, I9kTextarea, and I9kSelect, it does not participate in the I9kField composable — it owns its own legend, hint, error, and ids entirely.
Actions
- ChatOptionsThe answer row of an I9kChat footer: a named group of reply buttons aligned to the user side, with a focus() handle so the conversation can move focus to the next question.
- ButtonPolymorphic action trigger: renders a native button by default, an anchor when given a destination, or a caller-supplied component. Six variants cover primary actions, filters, and pagination.
- ButtonGroupLayout wrapper that spaces a row or column of buttons with a consistent gap and groups them as one control for assistive tech.
- IconButtonCircular icon-only action trigger: renders a native button by default, or an anchor/caller-supplied component when given a destination. Its own variant set is separate from I9kButton.
- TabsAccessible horizontal tabs (the WAI-ARIA tabs pattern with automatic activation): a named tablist of equal-width tabs over the one panel that belongs to the selected tab.
Feedback
- ToastStyled, accessible message banner for standing status or error text in the page flow. For notifications (saved, failed, sent), use I9kToaster, which renders I9kToast for each one.
- ToasterThe one place notifications appear: a fixed stack at the top of the viewport that shows the toasts raised through a per-app store, announces each through its own live regions, dismisses info and success after five seconds and keeps warnings and errors until the user dismisses them.
- TooltipA short plain-text note above an element, shown on hover, keyboard focus or tap. It also describes the element to assistive technology.
- ModalAccessible modal dialog built on the native <dialog> element, labelled by its title, with a close button, a scrolling body, and an optional footer. The parent owns whether it is open.
Site chrome
- AskAiA heading and a row of pill links that open ChatGPT, Perplexity and Claude in a new tab with a question about the site already typed in.
- AnnouncementBarFull-bleed brand-green bar for one short site-wide message, an optional link and a close button, laid out in the shared page column. Placed above I9kNavigation. Stateless: it emits close and the consumer hides it.
- NavigationSticky site header with a brand slot, a link list, and an actions slot, laid out in the shared page column. Tracks scroll position to add a background on scroll and switch the brand into a compact state. Renders plain anchors, or a caller-supplied router link component.
- NavMenuMobile navigation: a bars toggle that opens a full-screen panel with the brand, the link list, and a footer slot. Owns the modal behavior — teleport, scroll lock, focus trap, Escape, and closing itself when the viewport passes the desktop breakpoint.
- ProfileMenuThe signed-in account's control for a navigation bar: an avatar button that opens a small panel naming the account, its links and the caller's actions, such as signing out.
- BreadcrumbA breadcrumb trail in a named navigation landmark: every step but the last links back, and the last is the current page.
- SidebarLayoutA full-height frame: a slim sticky bar, a sidebar and a main area. Wide screens show the sidebar as a column the reader can hide; narrow screens open it as a modal drawer from the bar.
- SideNavAn app sidebar's section links: a labelled navigation landmark holding a vertical list, with the current section marked, and a footer slot below the list.
- FooterA page's bottom chrome. On its own it is a centred row of social links and a tagline; given link columns or a brand it becomes a multi-column site footer with a bottom bar.
- BrandWordmarkDecorative, self-animating logotype that types itself out and swaps between a full and short form — purely visual, and carries no accessible name of its own.
- SocialLinksRow of pill-shaped social/contact links, each opening in a new tab, with an icon fallback and a customizable accessible label per item.
- ThemeSwitcherControlled light/dark icon button. It renders and emits the toggle only — applying the theme to the page is entirely the caller's job.
- LanguageSwitcherA link to an alternate-language version of the current page, shown as a compact glyph-plus-locale-code button. It is only the link's markup — it does not itself switch the page's language or navigate via JS.
- BlurredCirclesDecorative, non-interactive layer of four slow-drifting blurred circles, meant as an ambient page background sitting behind real content.
- GlowDecorative, non-interactive page background: one large, soft, film-grained glow in the brand green, amber, and orange, half off-screen at an edge or corner, drifting slowly.