Skip to content

Guidelines

Composition

How to compose Stance components: compound parts, the asChild prop for router links, controlled and uncontrolled state, and extending styles safely.

Stance favours small parts that compose over large components with many props.

Compound components

Complex components are families of parts: Dialog, DialogTrigger, DialogContent, DialogTitle… The parent holds state and the parts render markup. You can reorder, omit or wrap parts without new props.

tsx
<Tabs defaultValue="templates">
  <TabsList aria-label="Signature workspace">
    <TabsTrigger value="templates">Templates</TabsTrigger>
    <TabsTrigger value="users">Organisation users</TabsTrigger>
  </TabsList>
  <TabsContent value="templates">…</TabsContent>
  <TabsContent value="users">…</TabsContent>
</Tabs>

asChild

Triggers and actions accept asChild to render your element, such as a router link, with Stance behaviour and styling merged onto it. Props, handlers, refs and class names merge.

tsx
<Button asChild variant="outline">
  <Link href="/dashboard/templates">View templates</Link>
</Button>

Controlled and uncontrolled

Stateful components work both ways. Pass defaultValue/defaultOpen and let Stance manage state, or pass value/open with an on…Change handler to own it.

Extending

  • Every component forwards its ref and spreads native attributes onto its root element.
  • className merges with Stance classes. Style with tokens: var(--st-…).
  • Variants and state are data-* attributes, so they are stable selectors for product-specific CSS.
  • Build product patterns by composing Stance parts inside your app; promote them to Stance when a second product needs them.