Picking The Right Library
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.
How to use it
Claude Code
- Run the line below. It pulls the whole folder into
~/.claude/skills/pick-ui-library, including the files SKILL.md points to. - Describe your job in plain words. Claude Code follows the skill from there.
npx degit emilkowalski/skills/skills/pick-ui-library#main ~/.claude/skills/pick-ui-libraryFor one project only, change the path to .claude/skills/pick-ui-library. This skill also uses package.json — copying SKILL.md alone won't be enough. See the folder on GitHub.
Claude (web or desktop app)
- On this page open ⋯ → Download .md.
- Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
- Pick the file and Save. Claude shows the name and description and runs a security scan.
- Check the skill is switched on.
- Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
- ChatGPT: make a Project and paste it into Instructions.
- Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
- Check which app you pasted it into — the steps above name the right one.
- Some skills need the paid tier of Claude or ChatGPT.
Paste into Claude, ChatGPT or Cursor.
Source of Picking The Right Library
Show the full text86 lines
| name | description | disable-model-invocation |
|---|---|---|
| pick-ui-library | 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. | true |
Picking The Right Library
Initial Response
When this skill is first invoked without a specific question, respond only with:
I'm ready to pick the right library for your task, my picks come from Emil Kowalski's curated list.
Do not provide any other information until the user asks a question.
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.
How to use this
- Identify the task, not the library the user named. "I need to show a dropdown" is a UI-primitives task (base-ui), even if they asked about something else.
- Check what's already installed. Look at
package.jsonfirst. 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. - Recommend one library, state what it's for in one sentence, and install/wire it up if that's part of the request. Don't present a menu of options when the list has a clear answer.
- If the task isn't covered by the list, say so explicitly and recommend from your own knowledge — but be clear you've left the curated list.
The list
UI components & primitives
| Task | Library |
|---|---|
| Unstyled, accessible UI components (dialogs, popovers, menus, selects…) | base-ui |
| Command menus (⌘K palettes) | cmdk |
| Toasts / notifications | Sonner |
| One-time password / verification code inputs | input-otp |
| Customizable GUIs / control panels | Leva — dialkit is an alternative |
Motion & visuals
| Task | Library |
|---|---|
| General-purpose animation (springs, layout animations, enter/exit) | motion (Framer Motion) |
| Animating numbers (counters, prices, stats) | NumberFlow |
| Animated text components | torph |
| 3D globes | Cobe |
| Dynamic OG images (HTML/CSS → SVG/PNG) | Satori |
| Syntax highlighting | shiki |
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.
Charts
| Task | Library |
|---|---|
| Real-time / streaming charts | Liveline |
| General charts (static or interactive dashboards) | recharts |
The split: if data points arrive live and the chart scrolls with time, use Liveline. Everything else is recharts.
Interaction & performance
| Task | Library |
|---|---|
| Drag and drop | dnd kit |
| Virtualization (long lists, large tables) | Virtuoso |
State & styling
| Task | Library |
|---|---|
| State management | zustand |
Constructing className strings conditionally |
clsx |
| Type-safe, variant-driven styling for Tailwind | cva |
| Theme switching / dark mode (no flash on load) | next-themes |
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.
Common mismatches to catch
- Toasts built by hand or with a modal library → Sonner exists for exactly this.
- A
<div>-based dropdown/dialog with manual focus handling → base-ui, which handles accessibility, focus trapping, and dismissal. - Animating a number by re-rendering text → NumberFlow handles digit transitions properly.
- Rendering a 1,000+ row list directly → Virtuoso before reaching for pagination hacks.
- A
useState-per-component web of props for shared state → zustand. - Template-literal className ternaries three conditions deep → clsx (or cva if it's variant-shaped).
| 1 | |
| 2 | name pick-ui-library |
| 3 | description 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. |
| 4 | disable-model-invocation true |
| 5 | |
| 6 | |
| 7 | # Picking The Right Library |
| 8 | |
| 9 | ## Initial Response |
| 10 | |
| 11 | When this skill is first invoked without a specific question, respond only with: |
| 12 | |
| 13 | > I'm ready to pick the right library for your task, my picks come from Emil Kowalski's curated list. |
| 14 | |
| 15 | Do not provide any other information until the user asks a question. |
| 16 | |
| 17 | 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. |
| 18 | |
| 19 | ## How to use this |
| 20 | |
| 21 | **Identify the task**, not the library the user named. "I need to show a dropdown" is a UI-primitives task (base-ui), even if they asked about something else. |
| 22 | **Check what's already installed.** Look at `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. |
| 23 | **Recommend one library**, state what it's for in one sentence, and install/wire it up if that's part of the request. Don't present a menu of options when the list has a clear answer. |
| 24 | If the task isn't covered by the list, say so explicitly and recommend from your own knowledge — but be clear you've left the curated list. |
| 25 | |
| 26 | ## The list |
| 27 | |
| 28 | ### UI components & primitives |
| 29 | |
| 30 | | Task | Library | |
| 31 | | --- | --- | |
| 32 | | Unstyled, accessible UI components (dialogs, popovers, menus, selects…) | [base-ui] | |
| 33 | | Command menus (⌘K palettes) | [cmdk] | |
| 34 | | Toasts / notifications | [Sonner] | |
| 35 | | One-time password / verification code inputs | [input-otp] | |
| 36 | | Customizable GUIs / control panels | [Leva] — [dialkit] is an alternative | |
| 37 | |
| 38 | ### Motion & visuals |
| 39 | |
| 40 | | Task | Library | |
| 41 | | --- | --- | |
| 42 | | General-purpose animation (springs, layout animations, enter/exit) | [motion] (Framer Motion) | |
| 43 | | Animating numbers (counters, prices, stats) | [NumberFlow] | |
| 44 | | Animated text components | [torph] | |
| 45 | | 3D globes | [Cobe] | |
| 46 | | Dynamic OG images (HTML/CSS → SVG/PNG) | [Satori] | |
| 47 | | Syntax highlighting | [shiki] | |
| 48 | |
| 49 | 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. |
| 50 | |
| 51 | ### Charts |
| 52 | |
| 53 | | Task | Library | |
| 54 | | --- | --- | |
| 55 | | Real-time / streaming charts | [Liveline] | |
| 56 | | General charts (static or interactive dashboards) | [recharts] | |
| 57 | |
| 58 | The split: if data points arrive live and the chart scrolls with time, use Liveline. Everything else is recharts. |
| 59 | |
| 60 | ### Interaction & performance |
| 61 | |
| 62 | | Task | Library | |
| 63 | | --- | --- | |
| 64 | | Drag and drop | [dnd kit] | |
| 65 | | Virtualization (long lists, large tables) | [Virtuoso] | |
| 66 | |
| 67 | ### State & styling |
| 68 | |
| 69 | | Task | Library | |
| 70 | | --- | --- | |
| 71 | | State management | [zustand] | |
| 72 | | Constructing `className` strings conditionally | [clsx] | |
| 73 | | Type-safe, variant-driven styling for Tailwind | [cva] | |
| 74 | | Theme switching / dark mode (no flash on load) | [next-themes] | |
| 75 | |
| 76 | 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. |
| 77 | |
| 78 | ## Common mismatches to catch |
| 79 | |
| 80 | **Toasts built by hand or with a modal library** → Sonner exists for exactly this. |
| 81 | **A `<div>`-based dropdown/dialog with manual focus handling** → base-ui, which handles accessibility, focus trapping, and dismissal. |
| 82 | **Animating a number by re-rendering text** → NumberFlow handles digit transitions properly. |
| 83 | **Rendering a 1,000+ row list directly** → Virtuoso before reaching for pagination hacks. |
| 84 | **A `useState`-per-component web of props for shared state** → zustand. |
| 85 | **Template-literal className ternaries three conditions deep** → clsx (or cva if it's variant-shaped). |
| 86 |
Discussion
Browse more free Claude skills.