Skills
Chapter 7 of 9
Pick the right library for a given frontend task from a curated, opinionated list — numbers, OTP inputs, charts, command menus, virtualization, drag and drop, toasts, state…
2 minutes · 477 words · 9 sections
A lookup skill. When invoked with a task (“I need toasts”, “what should I use for drag and drop?”), match the task to the curated list below and recommend the library. These are deliberate, taste-driven picks — don’t substitute alternatives outside this list unless the user asks for one or the task genuinely isn’t covered.
package.json first. If the project already uses a listed library, use it. If it uses a competitor (e.g. react-window instead of Virtuoso), flag the recommendation but don’t churn the dependency without being asked.| Task | Library |
|---|---|
| Unstyled, accessible UI components (dialogs, popovers, menus, selects…) | base-ui (opens in a new tab) |
| Command menus (⌘K palettes) | cmdk (opens in a new tab) |
| Toasts / notifications | Sonner (opens in a new tab) |
| One-time password / verification code inputs | input-otp (opens in a new tab) |
| Customizable GUIs / control panels | Leva (opens in a new tab) — dialkit (opens in a new tab) is an alternative |
| Task | Library |
|---|---|
| General-purpose animation (springs, layout animations, enter/exit) | motion (opens in a new tab) (Framer Motion) |
| Animating numbers (counters, prices, stats) | NumberFlow (opens in a new tab) |
| Animated text components | torph (opens in a new tab) |
| 3D globes | Cobe (opens in a new tab) |
| Dynamic OG images (HTML/CSS → SVG/PNG) | Satori (opens in a new tab) |
| Syntax highlighting | shiki (opens in a new tab) |
Reach for motion when you need springs, layout animations, exit animations, or gesture-driven values. A simple hover or fade doesn’t need it — plain CSS transitions are the right tool there.
| Task | Library |
|---|---|
| Real-time / streaming charts | Liveline (opens in a new tab) |
| General charts (static or interactive dashboards) | recharts (opens in a new tab) |
The split: if data points arrive live and the chart scrolls with time, use Liveline. Everything else is recharts.
| Task | Library |
|---|---|
| Drag and drop | dnd kit (opens in a new tab) |
| Virtualization (long lists, large tables) | Virtuoso (opens in a new tab) |
| Task | Library |
|---|---|
| State management | zustand (opens in a new tab) |
Constructing className strings conditionally | clsx (opens in a new tab) |
| Type-safe, variant-driven styling for Tailwind | cva (opens in a new tab) |
| Theme switching / dark mode (no flash on load) | next-themes (opens in a new tab) |
The styling split: clsx for ad-hoc conditional classes; cva when a component has real variants (size, intent, state) that deserve a typed API. They compose — cva uses clsx-style inputs internally.
<div>-based dropdown/dialog with manual focus handling → base-ui, which handles accessibility, focus trapping, and dismissal.useState-per-component web of props for shared state → zustand.Install this repository
npx skills add emilkowalski/skillsSkills install per repository, not per chapter — the CLI has no documented per-skill form, so we do not print one.
Pick the right library for a given frontend task from a curated, opinionated list — numbers, OTP inputs, charts, command menus, virtualization, drag and drop, toasts, state, styling, and more. Only runs when explicitly invoked; it does not trigger on its own.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
main, last pushed 9 August 2026.SKILL.md, not by matching a directory convention. One layout observed: skills/*/SKILL.md.h1 and no skipped levels:/emilkowalski/skills.md, and each chapter at its own .md URL.