Delacour UI · Native
React Native components that compose.
Built on Uniwind, Reanimated and the Gesture API. Nineteen components, 148 typed surfaces, and a reason written down for every decision.
bun add @delacour/native-uiThe icon names nothing
No size, no color. The button wraps its subtree in an icon-defaults provider carrying its own size class and its variant's foreground token, so a bare glyph comes out right with nothing said at the call site.
Set either explicitly and yours wins. That is the whole precedence rule, and it is the same one every component here follows.
How composition worksimport { Button } from "@delacour/native-ui/button";import { Icon } from "@delacour/native-ui/icon";import { IconArrowRight } from "@delacour/native-ui/icons/central";<Button haptic="selection" onPress={next}> <Button.Label>Continue</Button.Label> <Icon icon={IconArrowRight} /></Button>;Why it is built this way
Compose, don't configure
Icons are children, never props. A button publishes its size and its variant's foreground to the subtree, so a bare <Icon> comes out matching the label beside it.
Loading that costs no layout
The spinner takes the place of the icon it replaces rather than joining it. Both are drawn at the same token, so nothing shifts when work begins — or when it ends.
One scale, indexed
Icon and Spinner resolve md to the same edge length. A checkbox's square reads that scale two steps up rather than minting its own three numbers.
Themed by CSS variables
Components name bg-background and text-muted-foreground — never a raw palette colour, never a dark: prefix. Swap the variables and the theme follows.
Decisions you can unit-test
Every pure resolver lives in a *.variants.ts free of React Native imports, so the whole variant matrix is reachable from bun test rather than only from a simulator.
Peers, not dependencies
Every native module is a peer, and granular export subpaths make the optional ones genuinely optional. Import /button and nothing keyboard-related resolves.