styled()
When slots and props are not enough, extend the frame:
import { styled } from "@knitui/core";
import { Box } from "@knitui/components";
export const Panel = styled(Box, {
name: "Panel",
padding: "$lg",
borderRadius: "$md",
backgroundColor: "$color2",
borderWidth: 1,
borderColor: "$borderColor",
variants: {
tone: {
quiet: { backgroundColor: "$color1" },
loud: { backgroundColor: "$color3", borderColor: "$color7" },
},
raised: {
true: { shadow: "md" },
},
} as const,
});<Panel tone="loud" raised p="$xl" />as const on variants is load-bearing — it is what makes tone a union instead
of string in the resulting props.
Import it from @knitui/core
The kit's styled is Tamagui's factory with .styleable() output memoized. It is
the only styled on the kit's surface — @knitui/core deliberately stops
re-exporting Tamagui's raw one, so you cannot accidentally get a frame that skips
the memoization.
What you can extend
Any component whose frame is exported. Most components expose theirs
(Button.Frame, ActionIcon.Frame, UnstyledButton exposes
UnstyledButtonFrame), and every layout primitive is a plain styled(Box). Start
from the closest frame rather than from Box — you inherit the variant ladders.
Variants that read tokens
variants: {
size: {
"...size": (token) => ({ height: token, paddingHorizontal: token }),
},
} as constThe spread-variant form maps a whole token scale in one go. Note the kit's own
components do not use it for size — they read
controlMetrics instead, because height, font, padding
and radius need to move independently rather than all following one token.
Extraction and .styleable()
Your own styled() components made from plain Box can flatten, so a
performance-critical leaf is a reasonable place to avoid .styleable().
When not to reach for it
- Restyling one part of a component → use
styles. - A one-off tweak → just pass props; they win over variants.
- A different colour →
theme, not astyledoverride, or you lose hover, press and focus coherence.