Files
f2ee74b50f feat: add shadcn/ui design system with scoped Tailwind preflight (#7227)
* 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]>
2026-02-27 15:51:02 +01:00

4.2 KiB

name, description, argument-hint, allowed-tools
name description argument-hint allowed-tools
design.verify Verify Figma implementation is pixel-perfect. Use after implementing Figma designs to catch and fix discrepancies. [figma-url-or-node-id]
mcp__figma-remote-mcp__get_design_context
mcp__figma-remote-mcp__get_screenshot
Read
Edit
Bash
Grep

Figma-to-Code Verification

Verify the implementation of $ARGUMENTS matches Figma specs.

The 5-Phase Verification Process

Phase 1: Component Inventory

Goal: Create a complete list of all components to verify.

  1. Fetch design context from Figma
  2. Check for changelog comments - Look for documented changes in Figma component comments
  3. Extract all unique node IDs and types
  4. Create a checklist
mcp__figma-remote-mcp__get_design_context(fileKey, nodeId)

Output format:

## Component Checklist

- [ ] Sidebar (node: 1:3236)
  - [ ] Header with workspace switcher
  - [ ] Navigation items
- [ ] Main content area
  - [ ] TotalValueCard (node: 5:1620)
  - [ ] AssetsCard (node: 5:1624)

Phase 2: Visual Comparison

Goal: Compare Figma screenshot vs implementation.

mcp__figma-remote-mcp__get_screenshot(fileKey, nodeId)

Comparison Checklist:

  • Overall layout matches
  • Spacing between elements
  • Component sizes (width/height)
  • Colors and backgrounds
  • Typography (font size, weight, line height)
  • Border radius
  • Shadows and elevation
  • Icons (size, color, alignment) - verify button icons are direct children, not wrapped in divs, ignore visual description and stick to data for icons

Phase 3: Attribute-by-Attribute Verification

For each component, verify:

Layout & Spacing

Attribute Figma Implementation Match?
width
height
padding
gap
layout ratios

Important: Verify layout ratios match Figma (e.g., 2-column grid with 50/50 split, or specific width ratios). Custom Tailwind classes are only allowed for layout, not for styling shadcn components.

Typography

Attribute Figma Implementation Match?
font-size
font-weight
line-height
text-color

Visual Styling

Attribute Figma Implementation Match?
background
border
border-radius
box-shadow

Phase 4: Interactive States

States to verify:

  • Default/resting state
  • Hover state
  • Active/pressed state
  • Focus state
  • Disabled state
  • Selected/active state

Phase 5: Edge Cases

  • Min/max width behavior
  • Long text (truncation/wrapping)
  • Empty states
  • Loading states

Verification Report Template

# Verification Report: [Component Name]

## Figma Reference

- Node ID: [ID]
- Screenshot: [attached]

## Discrepancies Found

### 1. [Issue Title]

- **Location:** [element]
- **Expected:** [Figma value]
- **Actual:** [Implementation value]
- **Fix:** [what to change]

## Summary

- Layout: ✅/❌
- Typography: ✅/❌
- Colors: ✅/❌
- Components: ✅/❌

Quick Commands

# Run Storybook for visual testing
yarn workspace @safe-global/web storybook

# Type-check
yarn workspace @safe-global/web type-check

Project Notes

  • Components Path: apps/web/src/components/ui/
  • Utility Path: apps/web/src/utils/cn.ts
  • Icon Library: lucide-react

Component Usage Rules:

  • Must use existing shadcn components from /ui/ - do not alter or override them
  • Custom styling/Tailwind is only allowed for layout (flex, grid, gap, padding, width/height ratios)
  • Verify layout ratios match Figma exactly (e.g., grid column ratios, flex proportions)