component library · work in progress
Bigface UI
This page is the library the site itself is built from: every colour, font and component below is the production one, rendered live.
01 — colour
Colour tokens
The 20 palette colours, each with where it comes from and the contrast its ink reaches. The 16 ANSI slots are aliases of those, never new colours.
Terminal (ANSI) aliases
Semantic tokens
What shadcn's components paint with, read from tailwind.css. Each one is a palette variable and nothing else.
| Token | Palette |
|---|---|
| --background | bf-bg |
| --foreground | bf-fg |
| --card | bf-cursor-line |
| --card-foreground | bf-fg |
| --popover | bf-cursor-line |
| --popover-foreground | bf-fg |
| --primary | bf-blue |
| --primary-foreground | ink-on-bright |
| --secondary | bf-border-muted |
| --secondary-foreground | bf-fg |
| --muted | bf-border-muted |
| --muted-foreground | bf-fg-dim |
| --accent | bf-border-muted |
| --accent-foreground | bf-fg |
| --destructive | bf-burnt-orange |
| --border | bf-border |
| --input | bf-border |
| --ring | bf-blue |
| --chart-1 | bf-blue |
| --chart-2 | bf-lime |
| --chart-3 | bf-yellow |
| --chart-4 | bf-burnt-orange |
| --chart-5 | bf-purple |
| --sidebar | bf-cursor-line |
| --sidebar-foreground | bf-fg |
| --sidebar-primary | bf-blue |
| --sidebar-primary-foreground | ink-on-bright |
| --sidebar-accent | bf-border-muted |
| --sidebar-accent-foreground | bf-fg |
| --sidebar-border | bf-border |
| --sidebar-ring | bf-blue |
02 — type
Type
One family, Recursive, loaded once. The display and sans stacks differ only in fallbacks; the mono face is the same file with the MONO axis on.
font-displayBigface 2018 { } 0123
"Recursive", "Helvetica Neue", system-ui, sans-serif
headings, the brand, stats
font-sansBigface 2018 { } 0123
"Recursive", system-ui, -apple-system, "Segoe UI", sans-serif
body copy and controls
font-codeBigface 2018 { } 0123
"Recursive", ui-monospace, "SF Mono", Menlo, monospace + "MONO" 1 axis
code, commands, kickers, chips
Scale in use
Every font-size class used under site/src/, smallest first, each line set in its own size. Headings without a class use the element defaults: h1clamp(2.6rem, 6vw, 4rem), h2 clamp(1.7rem, 3.2vw, 2.4rem),h3 1.1rem.
text-[0.6rem]text-[0.625rem]text-[0.64rem]text-[0.66rem]text-[0.68rem]text-[0.7rem]text-[0.72rem]text-[0.75rem]text-xstext-[0.78rem]text-[0.79rem]text-[0.8rem]text-[0.82rem]text-[0.84rem]text-[0.85rem]text-[0.87rem]text-smtext-[0.88rem]text-[0.9rem]text-[0.94rem]text-[0.95rem]text-[1rem]text-basetext-[1.1rem]text-[1.22rem]text-[1.9rem]text-[clamp(1.35rem,2.4vw,1.8rem)]text-[clamp(2.3rem,5.2vw,3.6rem)]text-[clamp(2.6rem,6vw,4.4rem)]text-[clamp(3.4rem,8.5vw,6.2rem)]03 — native
Native components
Everything in components/ui/, exactly as the shadcn CLI wrote it — all
63 components the registry ships. The four below are documented in depth;
the rest follow with their exports and the variant keys read from their own source.
Button
native · shadcnimport { Button } from "@/components/ui/button";Every variant × size. Icon sizes carry an icon instead of a label.
| default | xs | sm | lg | icon | icon-xs | icon-sm | icon-lg | |
|---|---|---|---|---|---|---|---|---|
| default | ||||||||
| outline | ||||||||
| secondary | ||||||||
| ghost | ||||||||
| destructive | ||||||||
| link |
States per variant. Hover and focus are live: point at or tab to any button above.
| default | disabled | aria-invalid | |
|---|---|---|---|
| default | |||
| outline | |||
| secondary | |||
| ghost | |||
| destructive | |||
| link |
Badge
native · shadcnimport { Badge } from "@/components/ui/badge";Every variant; Badge has no size. Not interactive, so no hover or disabled state.
Card
native · shadcnimport {
Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,
} from "@/components/ui/card";Both sizes with every slot filled. Static, so no states.
Tabs
native · shadcnimport { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";Every list variant × orientation, live (one island each). The third trigger is disabled; focus and arrow keys work.
variant=default · horizontal
variant=default · vertical
variant=line · horizontal
variant=line · vertical
The full set — 63 components
native · shadcnEvery component the CLI ships, installed and upgrade-clean (ui:drift). The four above are documented in depth; the rest are registered with how many parts each exports and the variant keys its own source declares.
accordion
4 exportsalert
4 exportsvariant: default · destructive
alert-dialog
12 exportsaspect-ratio
1 exportsattachment
9 exportsvariant: icon · image
size: default · sm · xs
avatar
6 exportsbreadcrumb
7 exportsbubble
4 exportsvariant: default · secondary · muted · tinted · outline · ghost · destructive
button-group
4 exportscalendar
2 exportscarousel
7 exportschart
6 exportscheckbox
1 exportscode-block
8 exportsvariant: default · destructive
collapsible
3 exportscombobox
16 exportscommand
9 exportscontext-menu
15 exportsdialog
10 exportsdirection
2 exportsdrawer
10 exportsdropdown-menu
15 exportsempty
6 exportsvariant: default · icon
field
10 exportshover-card
3 exportsinput
1 exportsinput-group
6 exportssize: xs · sm · icon-xs · icon-sm
input-otp
4 exportsitem
10 exportsvariant: default · outline · muted
size: default · sm · xs
kbd
2 exportslabel
1 exportsmarker
4 exportsvariant: default · separator · border
menubar
16 exportsmessage
6 exportsmessage-scroller
9 exportsnative-select
3 exportsnavigation-menu
9 exportspagination
7 exportspopover
7 exportsprogress
1 exportsquestionnaire
15 exportsradio-group
2 exportsresizable
3 exportsscroll-area
2 exportsselect
10 exportsseparator
1 exportssheet
8 exportssidebar
24 exportsvariant: default · outline
size: default · sm · lg
skeleton
1 exportsslider
1 exportssonner
1 exportsspinner
1 exportsswitch
1 exportstable
8 exportstextarea
1 exportstoggle
2 exportsvariant: default · outline
size: default · sm · lg
toggle-group
2 exportstooltip
4 exportstrace
8 exports04 — bg
BG components
Everything in components/bg/: the Bigface layer. Wrappers add variants over a
native component without touching it; composite blocks are built from utilities and other BG
parts. Props are shown straight from each file.
31 entries · 4 wrappers · 8 with props not finalised.
BGButton
wrapper · over ButtonBigface tones (glow, ghost, copy, nav, chip) layered on the shadcn Button; href renders a link.
export type BGButtonProps = Omit<ButtonProps, "asChild"> &
VariantProps<typeof bgButtonVariants> & {
/** Render as a link (shadcn's asChild + <a>), so .astro pages can pass plain text children. */
href?: string;BGBadge
wrapper · over BadgeMono uppercase pill, tinted by how far a theme was checked.
export type BGBadgeProps = React.ComponentProps<typeof Badge> &
VariantProps<typeof bgBadgeVariants>;BGCard
wrapper · over CardThe deep translucent plate with a hairline border; glow adds the blue→lime rim.
export type BGCardProps = React.ComponentProps<typeof Card> & VariantProps<typeof bgCardVariants>;BGInstallTabs
wrapper · over Tabsprops not finalisedInstall / uninstall command switcher: shadcn Tabs in one island, panels force-mounted.
Not final: item shape (bar, command, note) is ad hoc to the install section.
curl -fsSL https://bigface.qqntt.com/install.sh | sh -s -- picurl -fsSL https://bigface.qqntt.com/install.sh | sh -s -- --uninstall piexport interface BGInstallTab {
id: string;
label: string;
/** Title in the fake terminal bar, e.g. "sh — install". Omit for no bar. */
bar?: string;
command: string;
note: string;
}
BGInstallTabs({ items }: { items: BGInstallTab[] })BGEyebrow
composite blockSmall mono kicker above a heading, with the blue dot.
a kicker
interface Props {
class?: string;
}BGSectionHead
composite blockNumbered section heading: kicker, title, lead.
00 — demo
A section heading
The lead paragraph sits under it.
interface Props {
eyebrow: string;
title: string;
}BGDivider
composite blockSection break: a hairline fading out at both ends.
(no props)BGCopyButton
composite blockprops not finalisedThe small copy pill wired to the page's copy handler (data-copy).
Not final: aria-label is passed as a raw string prop.
interface Props {
value: string;
label?: string;
swap?: "on" | "off";
"aria-label"?: string;
class?: string;
}BGCommandLine
composite blockPill-shaped one-line command with a prompt sigil and a copy button.
interface Props {
command: string;
copyLabel?: string;
}BGStat
composite blockBig gradient number over a short label.
interface Props {
value: string | number;
label: string;
}BGSwatchChip
composite blockOne colour of the home strip: grows on hover, copies its hex.
interface Props {
name: string;
hex: string;
}BGSwatch
composite blockPalette card: colour plate with its contrast ratio, name and source.
interface Props {
name: string;
color: Color;
}BGMarquee
composite blockEndless strip of names, pauses on hover.
interface Props {
items: string[];
}BGSyntaxPreview
composite blockFake editor window painted with the syntax roles, optional terminal strip.
// main.ts — colours, not a screenshot.import { greet } from "./hello"; type User = { id: number; name: string }; const ENDPOINT = "https://api.example.com/users"; export async function main(ids: number[]): Promise<void> { const res = await fetch(ENDPOINT); if (!res.ok) throw new Error(`users: ${res.status}`); const all: User[] = await res.json(); const picked = all.filter((u) => ids.includes(u.id)); picked.forEach((u) => greet(u.name));}interface Props {
terminal?: boolean;
}BGContrastTable
composite blockEvery palette colour's contrast on the background, with its WCAG band.
| Colour | Hex | Ratio on background | WCAG |
|---|---|---|---|
| fg | #d9d9d4 | 10.4 : 1 | AAA |
| comment | #75715e | 3.0 : 1 | large text |
| fgDim | #6e6b68 | 2.8 : 1 | below 3 |
| blue | #00b0ff | 6.1 : 1 | AA |
| lightBlue | #40c4ff | 7.4 : 1 | AAA |
| paleBlue | #b3e5fc | 10.9 : 1 | AAA |
| cyan | #66d9ef | 9.0 : 1 | AAA |
| green | #00c853 | 6.6 : 1 | AA |
| lime | #c6ff00 | 12.4 : 1 | AAA |
| yellow | #e5e500 | 10.9 : 1 | AAA |
| brightYellow | #ffeb3b | 12.1 : 1 | AAA |
| burntOrange | #fc5d23 | 4.7 : 1 | AA |
| purple | #ae81ff | 5.2 : 1 | AA |
| ansi.black | #494848 | 1.6 : 1 | below 3 |
| ansi.red | #fc5d23 | 4.7 : 1 | AA |
| ansi.green | #00c853 | 6.6 : 1 | AA |
| ansi.yellow | #e5e500 | 10.9 : 1 | AAA |
| ansi.blue | #00b0ff | 6.1 : 1 | AA |
| ansi.magenta | #ae81ff | 5.2 : 1 | AA |
| ansi.cyan | #66d9ef | 9.0 : 1 | AAA |
| ansi.white | #d9d9d4 | 10.4 : 1 | AAA |
| ansi.brightBlack | #6e6b68 | 2.8 : 1 | below 3 |
| ansi.brightRed | #fc5d23 | 4.7 : 1 | AA |
| ansi.brightGreen | #c6ff00 | 12.4 : 1 | AAA |
| ansi.brightYellow | #ffeb3b | 12.1 : 1 | AAA |
| ansi.brightBlue | #40c4ff | 7.4 : 1 | AAA |
| ansi.brightMagenta | #ae81ff | 5.2 : 1 | AA |
| ansi.brightCyan | #b3e5fc | 10.9 : 1 | AAA |
| ansi.brightWhite | #f8f8f0 | 13.8 : 1 | AAA |
(no props)BGPaletteGroup
composite blockA palette-page section: heading with a count, then its content.
A palette group 3
Its content goes here.
interface Props {
id: string;
title: string;
count?: number;
}BGFilterChips
composite blockApp grid filter: chips that hide cards by data-card-kind.
Filters the BGAppCard grid in the next entry.
interface Props {
kinds: string[];
}BGAppCard
composite blockprops not finalisedOne app in the home grid, with its check level and the pointer glow.
Not final: takes the raw Target record from data/targets.ts.
interface Props {
target: Target;
index: number;
base: string;
}BGSplit
composite blockMedia beside its instructions from 1024px, stacked below; the media stays first in the DOM.
Instructions
The aside: at least 340px wide, or the layout stacks.
interface Props {
split?: boolean;
class?: string;
}BGBreadcrumbs
composite blockBigface / Apps / name trail.
interface Props {
base: string;
name: string;
}BGMarketCard
composite blockprops not finalised“Published” strip for targets listed in their app's own gallery.
Not final: label / url / name mirror the Target.market fields one by one.
published
JetBrains MarketplaceJetBrains IDEs installs and updates it from its own gallery.interface Props {
label: string;
url: string;
name: string;
}BGDownloadCard
composite blockA download link styled as a small card.
interface Props {
href: string;
label: string;
detail: string;
class?: string;
}BGManualSteps
composite block“Do it by hand” fold with numbered steps.
Or do it by hand
- Copy
bigface.jsonto~/.pi/agent/themes/. - Run
pi --use-theme bigfacefor one session, or pick it under/settings→ Theme.
interface Props {
steps: string[];
}BGCodeCard
composite blockA block of code with its path and a copy button.
const palette = "bigface";interface Props {
path: string;
code: string;
truncated: boolean;
}BGNextCard
composite blockLink card to the next page in a sequence.
interface Props {
href: string;
name: string;
}BGHero
composite blockprops not finalisedHome hero: pitch, actions, install line and the parallax stage.
Not final: page-specific props (base, repo, ports, command).
Page-level block, shown live in place on /.
interface Props {
base: string;
repo: string;
ports: number;
command: string;
}BGAppHero
composite blockprops not finalisedApp page header: kind, port number, name, tagline, check level.
Not final: takes the raw Target plus a pre-computed label string.
Page-level block, shown live in place on /apps/pi/.
interface Props {
target: Target;
index: number;
total: number;
levelLabel: string;
}BGSiteHeader
composite blockprops not finalisedSticky site header: skip link, brand, main nav.
Not final: base / repo are passed as plain strings on every page.
Rendered once per page by Base.astro: the live one is this page's own.
interface Props {
base: string;
repo: string;
}BGSiteFooter
composite blockprops not finalisedSite footer: the mark, a one-line pitch, the footer nav.
Not final: base / repo / ports are passed as plain strings.
Rendered once per page by Base.astro: the live one is this page's own.
interface Props {
base: string;
repo: string;
ports: number;
}BGToast
composite blockThe copy confirmation (one per page, #toast).
Rendered once per page by Base.astro: the live one is this page's own.
(no props)bgTextClass
helper · not a componentLiteral text-bf-* class per palette colour, so Tailwind's scanner sees every one.
bgfgfgDimborderborderMutedselectioncursorLinebraceMatchbluelightBluepaleBluecyangreenlimeyellowbrightYellowburntOrangepurplecommentcaret
// Literal Tailwind class names per palette colour. They are spelled out (not built from strings) so
// Tailwind's scanner sees every one; anything that colours text by palette name goes through here.
export const bgTextClass: Record<string, string> = {
bg: "text-bf-bg",
fg: "text-bf-fg",
fgDim: "text-bf-fg-dim",
border: "text-bf-border",
borderMuted: "text-bf-border-muted",
selection: "text-bf-selection",
cursorLine: "text-bf-cursor-line",
braceMatch: "text-bf-brace-match",
blue: "text-bf-blue",
lightBlue: "text-bf-light-blue",
paleBlue: "text-bf-pale-blue",
cyan: "text-bf-cyan",
green: "text-bf-green",
lime: "text-bf-lime",
yellow: "text-bf-yellow",
brightYellow: "text-bf-bright-yellow",
burntOrange: "text-bf-burnt-orange",
purple: "text-bf-purple",
comment: "text-bf-comment",
caret: "text-bf-caret",
};05 — not yet
Not covered yet
This is a working catalogue, not a finished design system. Deliberately missing for now:
- Live demos for the rest of the native set. All 63 components the CLI ships are installed and upgrade-clean, and every one is registered above with its exports and variant keys; the ones outside the four deep entries have no live demo yet, and say nothing rather than pretending.
- Two system colours the registry paints with. Overlay scrims ask for
bg-black/10and the slider thumb forbg-white. Tailwind's default colour scale is cleared here (bigface is palette-only), so both classes generate no CSS and the scrim stays invisible; fixing that means adding a colour to the palette, which is a design decision, not a component one. - Pinned hover and focus states. They are live (point or tab) rather than frozen side by side: forcing them would mean editing the shadcn classes.
- Final props for 8 BG components: BGInstallTabs, BGCopyButton, BGAppCard, BGMarketCard, BGHero, BGAppHero, BGSiteHeader, BGSiteFooter. They take page data (a raw
Target, base and repo strings) instead of design types. - A light theme. Bigface is dark only, by design.
- Usage guidance. No do/don't notes or spacing rules yet; this page shows what exists, not how to compose it.