System
The conventions that make Nordstar components compose cleanly. This page documents the shared idioms — they're not enforced by the type system, but following them keeps your app's surface area small and predictable.
Polymorphism via as
Most Nordstar components accept an as prop to render as a different element while keeping their styling and behavior. This is the system's way of saying "I know what this should look like; you tell me what it should be in the document."
<Heading as="h2" level="h1">Welcome</Heading>
<Label as={Link} href="/docs">Docs</Label>
<Button as="a" href="/signup">Sign up</Button>
The visual treatment comes from the component's role; the rendered element comes from as. Use this when the visual hierarchy and the document outline diverge — the most common case is rendering a heading-styled element at a different <h*> level.
Color tokens
Every component that takes color exposes the same union: 'default' | 'primary' | 'secondary' | 'foreground'. Pick by intent, not by hue:
default— the component's own neutral state. No emphasis.primary— your primary brand action. The default for "do this thing."secondary— a complementary accent for less-emphasized actions or marketing-flavored callouts.foreground— maximum contrast against whatever surface the component sits on. Use for solid surfaces inside dark cards, or for accent text that needs to scream.
Components consume the token; the token's actual color comes from Theme.
Composition rhythm
The system has a small set of layout containers — View, Card, Header — and they're meant to nest in a predictable way:
- A page route's outermost element is a
View. - The first child of
Viewis typically aHeader. - The page body is whatever you want, often containing one or more
Cards. - A
Cardmay containCard.HeaderandCard.Divider, plus arbitrary content.
<View>
<Header>
<Header.Logo>App</Header.Logo>
<Header.Menu>…</Header.Menu>
</Header>
<main>
<Card>
<Card.Header>Settings</Card.Header>
<Card.Divider />
<p>Body content.</p>
</Card>
</main>
</View>
Variants
outline and solid are the two visual variants used across surfaces (Button, Card, Input):
outline— bordered, transparent fill. Default. Works on any background.solid— filled, the strongest emphasis. Use sparingly.
If a component takes a color and you set variant="solid", the result is the most visually loud combination available. Reserve it for the call to action.
Spacing
Spacing tokens come from Tailwind v4's defaults — p-3, gap-4, mt-6, etc. — applied consistently inside components. When composing, keep the rhythm: prefer gap-3, gap-4, or gap-6 over arbitrary values; prefer p-3 for cards and p-6 for hero sections.
Working with Tailwind classes
Every Nordstar component accepts className and merges it sensibly via tailwind-merge. You can always escalate:
<Card className="p-6 md:p-8">
<Card.Header>Spacious card</Card.Header>
</Card>
The default p-3 is overridden by your p-6 md:p-8 because tailwind-merge recognizes both as padding rules. This is the right way to fine-tune spacing — don't fight the component, just override the class.
Related
- Theme — token reference and override mechanisms.
- Components — every component honors these idioms.