-
Notifications
You must be signed in to change notification settings - Fork 6
add more claude skills that might be useful #775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
gudnuf
wants to merge
1
commit into
master
Choose a base branch
from
additional-claude-setup
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+815
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| --- | ||
| name: tailwind-design-system | ||
| description: Tailwind CSS design system for this mobile-first wallet app. Covers theme system (USD/BTC/dark), CSS variables, CVA components, shadcn/ui patterns, custom animations, and layout conventions. Use when creating or modifying UI components. | ||
| --- | ||
|
|
||
| # Tailwind Design System — Project Conventions | ||
|
|
||
| **Stack**: Tailwind CSS 4.1 + `@tailwindcss/vite` + shadcn/ui + CVA + tailwind-merge + tw-animate-css + Radix UI + vaul | ||
|
|
||
| **References** (load when needed): | ||
| - [component-patterns.md](references/component-patterns.md) — CVA examples, MoneyDisplay, Dialog/Drawer/Toast animations, view transitions, page layout, available UI components | ||
|
|
||
| ## Quick Reference | ||
|
|
||
| | What | How | | ||
| |------|-----| | ||
| | Class merging | `cn()` from `~/lib/utils` (clsx + tailwind-merge) | | ||
| | Component variants | CVA (`class-variance-authority`) | | ||
| | Semantic colors | CSS variables: `bg-primary`, `text-foreground`, `border-border` | | ||
| | Amount fonts | `font-numeric` (Teko) | | ||
| | Primary font | `font-primary` (Kode Mono) | | ||
| | Full viewport | `h-dvh` (dynamic viewport height) | | ||
| | Mobile container | `mx-auto w-full sm:max-w-sm` | | ||
| | Hide scrollbar | `scrollbar-none` (custom `@utility`) | | ||
| | Dark mode | Class-based (`.dark` on root) | | ||
| | Currency theme | `.usd` or `.btc` class on root | | ||
|
|
||
| ## Configuration | ||
|
|
||
| **Tailwind v4 uses CSS-first configuration** — no `tailwind.config.ts`. All config lives in `app/tailwind.css`. | ||
|
|
||
| | File | Purpose | | ||
| |------|---------| | ||
| | `app/tailwind.css` | All Tailwind config: `@theme`, `@utility`, CSS variables, base styles | | ||
| | `vite.config.ts` | `@tailwindcss/vite` plugin (first in plugins array) | | ||
| | `app/lib/utils.ts` | `cn()` utility (clsx + tailwind-merge) | | ||
| | `app/features/theme/theme-provider.tsx` | Theme context and switching | | ||
| | `app/features/theme/colors.ts` | Theme colors in TypeScript (**must stay in sync with CSS**) | | ||
| | `app/components/ui/` | shadcn/ui base components | | ||
| | `app/components/page.tsx` | Page layout components | | ||
| | `app/components/money-display.tsx` | MoneyDisplay / MoneyInputDisplay | | ||
| | `components.json` | shadcn/ui config (no `config` path — v4 uses CSS) | | ||
|
|
||
| ## v4 CSS-First Config Structure | ||
|
|
||
| The `app/tailwind.css` file structure: | ||
|
|
||
| ```css | ||
| @import "tailwindcss"; | ||
| @plugin "tailwindcss-animate"; | ||
|
|
||
| /* 1. CSS Variables — outside @layer (v4 requirement) */ | ||
| :root { --background: hsl(0 0% 100%); /* ... */ } | ||
| .usd { --background: hsl(178 100% 15%); /* ... */ } | ||
| .btc { --background: hsl(217 68% 35%); /* ... */ } | ||
| .dark { --background: hsl(0 0% 3.9%); /* ... */ } | ||
|
|
||
| /* 2. @theme inline — registers CSS vars as Tailwind color tokens */ | ||
| @theme inline { | ||
| --color-background: var(--background); | ||
| --color-foreground: var(--foreground); | ||
| --color-primary: var(--primary); | ||
| /* ... maps all CSS vars to Tailwind tokens */ | ||
| } | ||
|
|
||
| /* 3. @theme — custom tokens (fonts, sizes, animations) */ | ||
| @theme { | ||
| --font-numeric: "Teko", sans-serif; | ||
| --font-primary: "Kode Mono", monospace; | ||
| --font-size-2xs: 0.625rem; | ||
| --animate-shake: shake 0.2s ease-in-out; | ||
| --animate-slam: slam 0.4s ease-out both; | ||
| --animate-slide-out-up: slide-out-up 300ms ease-out forwards; | ||
| } | ||
|
|
||
| /* 4. @keyframes — top-level, referenced by @theme animations */ | ||
| @keyframes shake { /* ... */ } | ||
|
|
||
| /* 5. @utility — custom utilities (replaces v3 plugins) */ | ||
| @utility scrollbar-none { | ||
| -ms-overflow-style: none; | ||
| scrollbar-width: none; | ||
| &::-webkit-scrollbar { display: none; } | ||
| } | ||
|
|
||
| /* 6. @layer base — global styles */ | ||
| @layer base { | ||
| * { @apply border-border; } | ||
| body { @apply bg-background text-foreground; } | ||
| button:not(:disabled), [role="button"]:not(:disabled) { | ||
| cursor: pointer; /* v4 removed default cursor:pointer */ | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| **Key v4 differences from v3:** | ||
| - `@import "tailwindcss"` replaces three `@tailwind` directives | ||
| - CSS variables use `hsl()` wrapper (v3 used bare values like `0 0% 100%`) | ||
| - `@theme inline` registers CSS vars as Tailwind tokens (replaces `theme.extend.colors` in JS) | ||
| - `@theme` defines custom tokens (replaces `theme.extend.*` in JS config) | ||
| - `@utility` creates custom utilities (replaces `plugin({ addUtilities })`) | ||
| - `@plugin` loads plugins (replaces `require()` in JS config) | ||
| - No `postcss.config.js` needed — `@tailwindcss/vite` handles everything | ||
|
|
||
| ## v4 Class Name Changes | ||
|
|
||
| Use the v4 names. The v3 names no longer exist: | ||
|
|
||
| | v3 (removed) | v4 (use this) | | ||
| |--------------|---------------| | ||
| | `shadow-sm` | `shadow-xs` | | ||
| | `rounded-sm` | `rounded-xs` | | ||
| | `outline-none` | `outline-hidden` | | ||
|
|
||
| Also: default `ring` width changed from `3px` to `1px` (use `ring-3` for old behavior). | ||
|
|
||
| ## Theme System | ||
|
|
||
| Two independent axes, both cookie-persisted for SSR: | ||
| 1. **Currency theme**: `.usd` (teal) or `.btc` (blue) on `<html>` | ||
| 2. **Color mode**: `light` / `dark` / `system` — applies `.dark` class | ||
|
|
||
| Access via `useTheme()` from `app/features/theme/use-theme.tsx`. | ||
|
|
||
| Always use semantic color classes (`bg-primary`, `text-foreground`, `border-border`). Never hardcode colors like `bg-blue-500`. | ||
|
|
||
| **Keep `app/tailwind.css` and `app/features/theme/colors.ts` in sync** — the TypeScript file duplicates CSS variable values for programmatic access. | ||
|
|
||
| ## Layout Conventions | ||
|
|
||
| - **Full viewport**: `h-dvh` (not `h-screen` — handles mobile browser chrome) | ||
| - **Safe viewport**: `h-[90svh]` for drawers/modals | ||
| - **Mobile container**: `w-full sm:max-w-sm` (full on mobile, 448px max on larger) | ||
| - **Centered layout**: `mx-auto sm:items-center` | ||
| - **Scrollable content**: `flex-1 overflow-y-auto scrollbar-none min-h-0` | ||
| - **Numpad**: `sm:hidden` (keyboard input on larger screens) | ||
| - **Mobile-first**: Base styles target mobile; `sm:` adjusts for larger screens | ||
|
|
||
| ## Rules | ||
|
|
||
| | Do | Don't | | ||
| |----|-------| | ||
| | Semantic color classes (`bg-primary`) | Hardcoded colors (`bg-blue-500`) | | ||
| | `font-numeric` for all monetary amounts | Arbitrary font values | | ||
| | `h-dvh` for full-viewport layouts | `h-screen` (broken on mobile) | | ||
| | `cn()` for all className composition | Manual string concatenation | | ||
| | CVA for component variants | Inline conditional classes | | ||
| | Check `app/components/ui/` before creating new components | Duplicate existing shadcn components | | ||
| | Keep CSS vars and `colors.ts` in sync | Change one without the other | | ||
| | Add new keyframes/animations in `@theme`/`@keyframes` in CSS | Create animations outside `app/tailwind.css` | | ||
| | Use cookies for theme persistence | `localStorage` (breaks SSR) | | ||
| | `forwardRef` on components wrapping HTML elements | Skip ref forwarding | | ||
152 changes: 152 additions & 0 deletions
152
.claude/skills/tailwind-design-system/references/component-patterns.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| # Component Patterns | ||
|
|
||
| ## CVA Component Pattern | ||
|
|
||
| All UI components use CVA for type-safe variants with `cn()` for className merging: | ||
|
|
||
| ```typescript | ||
| // app/components/ui/button.tsx | ||
| import { cva, type VariantProps } from 'class-variance-authority'; | ||
| import { cn } from '~/lib/utils'; | ||
|
|
||
| const buttonVariants = cva( | ||
| 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | ||
| { | ||
| variants: { | ||
| variant: { | ||
| default: 'bg-primary text-primary-foreground hover:bg-primary/90', | ||
| destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', | ||
| outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', | ||
| secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', | ||
| ghost: 'hover:bg-accent hover:text-accent-foreground', | ||
| link: 'text-primary underline-offset-4 hover:underline', | ||
| }, | ||
| size: { | ||
| default: 'h-10 px-4 py-2', | ||
| sm: 'h-9 rounded-md px-3', | ||
| lg: 'h-11 rounded-md px-8', | ||
| icon: 'h-10 w-10', | ||
| }, | ||
| }, | ||
| defaultVariants: { variant: 'default', size: 'default' }, | ||
| }, | ||
| ); | ||
| ``` | ||
|
|
||
| **Button features**: `loading` prop with spinner, `asChild` via Radix `Slot`, `forwardRef`, `cn()` for overrides. | ||
|
|
||
| ## MoneyDisplay Component | ||
|
|
||
| **Always use `MoneyDisplay` or `MoneyInputDisplay` for monetary amounts.** | ||
|
|
||
| File: `app/components/money-display.tsx` | ||
|
|
||
| ```typescript | ||
| const valueVariants = cva('font-numeric', { | ||
| variants: { | ||
| size: { | ||
| xs: 'pt-0.5 text-xl', | ||
| sm: 'pt-1 text-2xl', | ||
| md: 'pt-1.5 text-5xl', | ||
| lg: 'pt-2 text-6xl', | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| Usage: | ||
| ```tsx | ||
| <MoneyDisplay money={balance} size="lg" variant="default" /> | ||
| <MoneyInputDisplay inputValue="1.5" currency="USD" unit="usd" /> | ||
| ``` | ||
|
|
||
| ## Available UI Components | ||
|
|
||
| Check `app/components/ui/` before creating new ones: | ||
|
|
||
| Badge, Button, Card (compound), Carousel, Checkbox, Dialog, Drawer (vaul), Dropdown Menu, Hover Card, Input, Label, Radio Group, Scroll Area, Select, Separator, Skeleton, Tabs, Toast, Toaster | ||
|
|
||
| All follow: CVA variants, `forwardRef`, `cn()`, Radix primitives. | ||
|
|
||
| ## Compound Component Pattern (Card) | ||
|
|
||
| ```typescript | ||
| const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>( | ||
| ({ className, ...props }, ref) => ( | ||
| <div | ||
| ref={ref} | ||
| className={cn('rounded-lg border bg-card text-card-foreground shadow-xs', className)} | ||
| {...props} | ||
| /> | ||
| ), | ||
| ); | ||
| // Plus: CardHeader, CardTitle, CardDescription, CardContent, CardFooter | ||
| ``` | ||
|
|
||
| ## Dialog/Drawer/Toast Animations | ||
|
|
||
| **Dialog** uses `tailwindcss-animate` data-attribute animations: | ||
| ```tsx | ||
| // Overlay | ||
| 'data-[state=open]:animate-in data-[state=closed]:animate-out' | ||
| 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0' | ||
|
|
||
| // Content | ||
| 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95' | ||
| 'data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]' | ||
| 'data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]' | ||
| ``` | ||
|
|
||
| **Drawer** (vaul): | ||
| ```tsx | ||
| className="bg-gradient-to-b from-transparent via-black/70 to-black/80" // overlay | ||
| className="fixed inset-x-0 bottom-0 rounded-t-[10px]" // content | ||
| className="h-[90svh] font-primary sm:h-[75vh]" // responsive height | ||
| ``` | ||
|
|
||
| **Toast** exit uses custom animation: | ||
| ```tsx | ||
| 'data-[state=closed]:animate-slide-out-up' | ||
| ``` | ||
|
|
||
| ## View Transitions | ||
|
|
||
| File: `app/lib/transitions/view-transition.tsx` + `transitions.css` | ||
|
|
||
| ```tsx | ||
| <LinkWithViewTransition to="/page" transition="slideLeft" applyTo="oldView"> | ||
| Go Forward | ||
| </LinkWithViewTransition> | ||
|
|
||
| const navigate = useNavigateWithViewTransition(); | ||
| navigate('/page', { transition: 'slideRight', applyTo: 'bothViews' }); | ||
| ``` | ||
|
|
||
| Types: `slideLeft`, `slideRight`, `slideUp`, `slideDown`, `fade` | ||
| Duration: 180ms (synced between CSS and TS — keep in sync!) | ||
| Apply modes: `newView`, `oldView`, `bothViews` | ||
|
|
||
| ## Page Layout Components | ||
|
|
||
| File: `app/components/page.tsx` | ||
|
|
||
| ```tsx | ||
| // Main page wrapper | ||
| <div className="mx-auto flex h-dvh w-full flex-col p-4 font-primary sm:items-center sm:px-6 lg:px-8"> | ||
|
|
||
| // Content area | ||
| <div className="flex flex-grow flex-col gap-2 p-2 sm:w-full sm:max-w-sm"> | ||
|
|
||
| // Footer | ||
| <div className="flex w-full flex-col items-center gap-2 p-2 sm:max-w-sm"> | ||
|
|
||
| // Header — centered title with absolute positioning | ||
| <div className="-translate-x-1/2 absolute left-1/2 transform"> | ||
| ``` | ||
|
|
||
| ## Icons | ||
|
|
||
| Using **Lucide React**: | ||
| - Standard: `size-4` or `size-5` | ||
| - Large: `size-6` | ||
| - In buttons: `[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to merge tailwind upgrade pr for this to be true