Component styling
SkillDev toolsUse when building or styling a component in libs/ui-react or libs/ui-rnative (and their visualization libs) — the cross-platform styling principles, plus routing to the platform mechanics: Tailwind + cva + cn on web, useStyleSheet + themeJS + lx on React Native. Load this before writing component styles.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Component styling skill
What this skill tells your AI
The instructions your AI receives, as published by ledgerhq/lumen in .claude/skills/component-styling/SKILL.md and read by ahel’s review.
Lumen ships the same components on web and React Native. The vocabulary of
design tokens is shared across both (bg-muted ↔ t.colors.bg.muted); the
mechanism is not. This skill states the principles that hold on both platforms,
then routes you to the platform mechanics.
Route by lib
Derive the touched lib from the path (see the Libraries table in AGENTS.md),
then read the matching reference:
| Lib | Read |
|---|---|
libs/ui-react | references/react.md (Tailwind + cva + cn) |
libs/ui-rnative | references/rnative.md (useStyleSheet + themeJS + lx) |
Never apply one platform's mechanics to the other lib. A className on an RN
file or a useStyleSheet call on a web file is always wrong.
Shared principles (both platforms)
These hold regardless of mechanism — the references show how each realises them.
- Design tokens, never raw values. Colours, typography, spacing and sizes
come from the design system, not from raw Tailwind palette classes / arbitrary
sizes (web) or hardcoded literals (RN). The token catalogues live in
references/*. - Props-drill to the top-level element. Behaviour must never be hidden. When
a prop legitimately targets a nested element (a nested
ref,className, orstyle), give it a distinct name (contentClassName,inputStyle) rather than overloading the top-level prop. - Compose variants declaratively. Appearance / size / state maps are declared
once at the top of the styling layer (
cvaon web,Record<Variant, value>insideuseStyleSheeton RN), never assembled ad hoc in the render body. - Never build a style value by concatenation.
text-${color}and its RN equivalents are wrong — use complete token strings and a merge helper (cnon web,StyleSheet.flattenon RN).
Review checks
Rules verifiable from a diff. Lint already covers unknown/invalid Tailwind
classnames, banned imports and formatting — see the "already enforced" list in
pr-review; don't raise those here.
| Check | Applies to | Detect | Skip |
|---|---|---|---|
| Raw Tailwind value instead of a token | react | text-gray-, bg-blue-, font-bold, text-sm, w-[, h-[ | .mdx doc-table markup |
| Dynamic classname built by concatenation | react | className={`...${ ` | — |
Classnames in a bare string variable instead of cn() / cva() | react | const … = 'flex …' outside a cn( / cva( call | strings inlined in className |
cva skipped where variants/many classes exist (or forced for 1–2 classes) | react | inline variant branching in JSX | — |
data-[state=…] on a Base UI primitive (or data-[open] on a Radix one) | react | import source vs attribute form | — |
Hardcoded colour/spacing/size literal instead of a t.* token | rnative | numeric or '#…' inside useStyleSheet | geometry constants under Components/visualization/ |
Large stylesheet inlined in the component body instead of a useXStyles hook | rnative | useStyleSheet call inline in the component | small one-off styles |
Consumer style/lx merged before internal styles (consumer can't win) | rnative | flatten([style, styles.root]) (reversed order) | — |
| Nested override overloads the top-level prop instead of a distinct name | both | one className/style prop feeding an inner element | — |
Signals
- GitHub stars
- 23
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
component-styling-ledgerhq- Source
- github.com/ledgerhq/lumen