* feat: add shadcn/ui setup and infrastructure
Configuration:
- Add PostCSS config for Tailwind CSS v4
- Add cn utility for className merging (clsx + tailwind-merge)
Dependencies:
- Add @base-ui/react, tailwindcss, @tailwindcss/postcss
- Add shadcn component dependencies (class-variance-authority, clsx, lucide-react, etc.)
- Add shadcn CLI tool for component management
- Update lodash version
Infrastructure:
- Update globals.css with CSS variables and Tailwind imports
- Add use-mobile hook for responsive sidebar behavior
- Update _document.tsx to support dark mode via HTML class
* feat: add shadcn/ui component library
- Add components.json with base-vega style configuration
- Add 48 shadcn/ui components including:
- Core: button, card, input, label, select, textarea
- Layout: sidebar, separator, scroll-area, resizable
- Feedback: alert, alert-dialog, badge, progress, skeleton, spinner, sonner
- Navigation: breadcrumb, navigation-menu, pagination, tabs
- Overlay: dropdown-menu, context-menu, popover, hover-card, tooltip, sheet, drawer
- Form: checkbox, radio-group, switch, slider, combobox, input-otp, native-select, field, input-group
- Data: table, avatar, accordion, collapsible
- Misc: aspect-ratio, empty, kbd, toggle
- Stories: button.stories.tsx, card.stories.tsx, avatar.stories.tsx
* chore: add design system AI skills and update documentation
Add AI skills for Figma design workflow:
- design.figma-to-code: Convert Figma designs to React code
- design.sync-component: Sync components from Figma
- design.sync-variables: Sync CSS variables from Figma
- design.verify: Verify pixel-perfect implementation
- design.prototype: Create Storybook prototypes
Add Figma component mapping documentation and remove autodocs tag
from Storybook examples in AGENTS.md to align with project standards.
* docs: improve JSDoc documentation for UI components
- Add comprehensive JSDoc comments to all UI components
- Include usage examples and key props documentation
- Verify and update examples against shadcn/ui Base UI documentation
- Improve examples for checkbox, collapsible, slider, alert, progress, select, tabs, accordion, switch, and radio-group components
* fix: rewrite story files to use Base UI patterns instead of Radix
- Replace asChild prop with render prop pattern (Base UI)
- Fix unused imports and unescaped entities
- Add required args property for stories with render functions
- All story files now work correctly with Base UI components
* chore: update skills
* refactor: move stories to stories dir
* fix(web): use bare imports for CSS files so they are inlined in production build
@import url(./vars.css) and @import url(./onboard.css) were silently
dropped during next build because @tailwindcss/postcss only resolves
bare @import specifiers, not url() imports. In dev mode the dev server
resolved them at request time, causing a visual mismatch between dev
and production builds.
* fix(web): preserve DM Sans font over Tailwind default
The @theme inline block had --font-sans: var(--font-sans), a circular
self-reference that resolved to Tailwind's default sans-serif stack
instead of the legacy DM Sans font.
* fix(web): inline DM Sans font-face imports in globals CSS
* chore: add scoped Tailwind preflight and ShadcnProvider for MUI coexistence
Since we can't import tailwindcss/preflight.css globally (it would break
MUI), scope the relevant subset of Tailwind's preflight resets to
.shadcn-scope. This ensures shadcn components get proper CSS resets
(button backgrounds, heading weights, form elements, etc.) without
affecting MUI components outside the scope.
Adds ShadcnProvider component to wrap shadcn content with the scope
class and optional dark mode support.
* fix: portal components render inside ShadcnProvider scope
Portal-based shadcn components (HoverCard, Popover, Tooltip, etc.)
were rendering to <body> via base-ui Portal, losing CSS variable
inheritance from .shadcn-scope. This caused transparent backgrounds
and missing styles on all portaled content.
- ShadcnProvider now provides a portal container ref via React context
- All 11 portal components pass container={usePortalContainer()} so
portals render inside .shadcn-scope and inherit CSS variables
- Context uses Symbol.for() singleton to survive bundler module
duplication (e.g. Storybook resolving same file via alias + relative)
- Returns RefObject (not .current) so base-ui reads it lazily, avoiding
timing issues when portal renders in same commit as ShadcnProvider
- Vaul Drawer uses usePortalContainerElement() since it only accepts
Element, not RefObject
* fix: use callback ref in ShadcnProvider for reliable portal container
The previous ref-based approach returned null for Vaul's container prop
because ref.current wasn't yet set when the context value was read.
Switch to a callback ref + useState so the context value updates
reactively when the DOM node mounts, guaranteeing portal components
(especially Vaul Drawer) render inside .shadcn-scope.
Also fix duplicate Tailwind classes on the drawer handle bar.
* chore: exclude Storybook sources from production Tailwind scan
Move @source for stories to a Storybook-only CSS file so utility
classes used only in demo wrappers don't bloat the shipped stylesheet.
* fix: override Tailwind default font with Safe app font
Tailwind theme.css sets --font-sans to a system font stack. Override it
with DM Sans in @theme inline so shadcn components use the app font.
Remove the duplicate override from globals.css.
* fix: remove Tailwind directives from globals.css to restore font loading
The @theme inline and @layer base directives added by shadcn caused
Tailwind's PostCSS plugin to process globals.css, which dropped the
@import url(/fonts/fonts.css) declaration. These directives are already
in shadcn.css where they belong.
---------
Co-authored-by: Hanzo Dev <[email protected]>
3.5 KiB
name, description, argument-hint, allowed-tools
| name | description | argument-hint | allowed-tools | ||||||
|---|---|---|---|---|---|---|---|---|---|
| design.sync-component | Sync a UI component from Figma to code using the component sync workflow. Use when updating components to match Figma designs. | [component-name] |
|
Sync Component from Figma
Sync the $ARGUMENTS component from Figma to code.
Source Files
- Figma File:
trBVcpjZslO63zxiNUI9io(Obra shadcn-ui safe) - Component Mapping:
apps/web/src/components/ui/docs/figma-code-connect.md - Target:
apps/web/src/components/ui/<component>.tsx
Process
1. Find Node ID
Look up the component in figma-code-connect.md to get the Figma node ID.
2. Fetch Design Context
mcp__figma-remote-mcp__get_design_context(
fileKey: "trBVcpjZslO63zxiNUI9io",
nodeId: "<node-id>",
disableCodeConnect: true
)
Also get a screenshot for visual reference:
mcp__figma-remote-mcp__get_screenshot(fileKey, nodeId)
Check for changelog comments: Look for comments on the Figma component page that document changes (e.g., "removed shadow and border", "updated spacing", "changed variant names"). These comments indicate intentional design changes that should be synced to code.
3. Compare & Document
First, check Figma comments for changelog - Look for documented changes in component comments that describe what was modified (e.g., "removed shadow", "updated border radius", "changed color scheme").
Then compare:
| Check | What to Compare |
|---|---|
| Sizes | Verify px values match (size-6=24px, size-8=32px, size-10=40px) |
| Colors | Fill colors → bg-, text- classes |
| Border | border-, rounded- classes |
| Shadow | shadow-* classes (Figma often has none) |
| Variants | CVA variants object keys |
Prioritize changelog items - If changelog comments exist, sync those changes first before doing a full comparison.
4. Update Code
Only sync when Figma actually changed. Don't remove code defaults that improve DX.
Add/update component header comment:
/**
* ComponentName
*
* Figma: https://www.figma.com/design/trBVcpjZslO63zxiNUI9io/?node-id=XX:XXXX
*
* Intentional differences from Figma:
* - property: reason for difference
*
* Changelog (from Figma comments):
* - YYYY-MM-DD: Description of changes from Figma changelog comment
* - YYYY-MM-DD: Additional sync changes made
*/
Note: The changelog should reflect changes documented in Figma component comments. If Figma has a changelog comment, include those changes in the code changelog.
5. Verify
Run type-check:
yarn workspace @safe-global/web type-check
Rules
- Check Figma changelog first - Always look for changelog comments on the Figma component page that document design changes
- Document the delta - Note intentional differences, only sync breaking changes
- Preserve code patterns - Keep CVA structure, only update classes/variants
- Keep existing functionality - Don't remove event handlers, refs, or accessibility
- Verify sizes match - Check actual pixel values, not just naming conventions
- Sync changelog items - If Figma comments document changes (e.g., "removed shadow", "updated border"), ensure those changes are reflected in code