@open-mercato/ui 0.6.8-develop.7015.1.af90a2ddc7 → 0.6.8-develop.7016.1.4ed7b1e49d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ import {
6
6
  AlertTriangle,
7
7
  Apple,
8
8
  Archive,
9
+ AtSign,
9
10
  Award,
10
11
  BadgeCheck,
11
12
  Ban,
@@ -167,6 +168,7 @@ const LUCIDE_ICON_REGISTRY = {
167
168
  "alert-triangle": AlertTriangle,
168
169
  "apple": Apple,
169
170
  "archive": Archive,
171
+ "at-sign": AtSign,
170
172
  "award": Award,
171
173
  "badge-check": BadgeCheck,
172
174
  "ban": Ban,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/icons/lucideRegistry.generated.tsx"],
4
- "sourcesContent": ["/* eslint-disable */\n// AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.\n// Generated from discovered icon string usages across the repo.\n\nimport type { LucideIcon } from 'lucide-react';\nimport {\n Activity,\n AlarmClock,\n AlertCircle,\n AlertOctagon,\n AlertTriangle,\n Apple,\n Archive,\n Award,\n BadgeCheck,\n Ban,\n Banknote,\n BarChart2,\n BarChart3,\n Bell,\n Bolt,\n Book,\n Bookmark,\n Box,\n Boxes,\n Briefcase,\n BriefcaseBusiness,\n Building,\n Building2,\n Calendar,\n CalendarCheck,\n CalendarClock,\n CalendarCog,\n CalendarMinus,\n CalendarOff,\n CalendarX,\n Check,\n CheckCircle,\n CheckCircle2,\n CheckSquare,\n Circle,\n ClipboardCheck,\n ClipboardList,\n Clock,\n Clock3,\n Coins,\n Copy,\n CopyX,\n CreditCard,\n Crown,\n Database,\n DollarSign,\n Download,\n ExternalLink,\n Eye,\n FileCheck,\n FileMinus,\n FilePenLine,\n Files,\n FileSpreadsheet,\n FileText,\n FilterX,\n Flag,\n Flame,\n FolderTree,\n Gauge,\n GitBranch,\n GitCompareArrows,\n GitPullRequestArrow,\n Globe,\n GraduationCap,\n Hammer,\n Hand,\n Handshake,\n Headphones,\n Heart,\n HelpCircle,\n Hourglass,\n Inbox,\n Key,\n KeyRound,\n Layers,\n Leaf,\n Lightbulb,\n LineChart,\n Link,\n List,\n ListX,\n Loader,\n Loader2,\n Lock,\n Mail,\n MailOpen,\n Map,\n MapPin,\n MapPinned,\n Megaphone,\n MessageCircle,\n MessageSquareReply,\n MinusCircle,\n Notebook,\n Package,\n PackageCheck,\n PackagePlus,\n PackageSearch,\n PackageX,\n PauseCircle,\n Percent,\n Phone,\n PhoneCall,\n PieChart,\n PlusSquare,\n Receipt,\n ReceiptText,\n RefreshCcw,\n RefreshCw,\n Repeat2,\n Reply,\n RotateCcw,\n Ruler,\n Send,\n Settings,\n Shapes,\n Share2,\n Shield,\n ShieldAlert,\n ShieldCheck,\n ShoppingBag,\n ShoppingCart,\n Shuffle,\n Sliders,\n Smartphone,\n Snowflake,\n Sparkles,\n Star,\n StickyNote,\n Store,\n Tag,\n Target,\n ThumbsUp,\n Ticket,\n Timer,\n Trash2,\n TrendingUp,\n TriangleAlert,\n Trophy,\n Truck,\n Undo,\n Undo2,\n Unlock,\n User,\n UserCheck,\n UserMinus,\n UserPlus,\n UserRound,\n Users,\n UserX,\n Wallet,\n Warehouse,\n Webhook,\n Workflow,\n Wrench,\n X,\n XCircle,\n ZapOff,\n} from 'lucide-react';\n\nexport const LUCIDE_ICON_REGISTRY: Record<string, LucideIcon> = {\n 'activity': Activity,\n 'alarm-clock': AlarmClock,\n 'alert-circle': AlertCircle,\n 'alert-octagon': AlertOctagon,\n 'alert-triangle': AlertTriangle,\n 'apple': Apple,\n 'archive': Archive,\n 'award': Award,\n 'badge-check': BadgeCheck,\n 'ban': Ban,\n 'banknote': Banknote,\n 'bar-chart-2': BarChart2,\n 'bar-chart-3': BarChart3,\n 'bell': Bell,\n 'bolt': Bolt,\n 'book': Book,\n 'bookmark': Bookmark,\n 'box': Box,\n 'boxes': Boxes,\n 'briefcase': Briefcase,\n 'briefcase-business': BriefcaseBusiness,\n 'building': Building,\n 'building2': Building2,\n 'calendar': Calendar,\n 'calendar-check': CalendarCheck,\n 'calendar-clock': CalendarClock,\n 'calendar-cog': CalendarCog,\n 'calendar-minus': CalendarMinus,\n 'calendar-off': CalendarOff,\n 'calendar-x': CalendarX,\n 'check': Check,\n 'check-circle': CheckCircle,\n 'check-circle-2': CheckCircle2,\n 'check-square': CheckSquare,\n 'circle': Circle,\n 'clipboard-check': ClipboardCheck,\n 'clipboard-list': ClipboardList,\n 'clock': Clock,\n 'clock-3': Clock3,\n 'coins': Coins,\n 'copy': Copy,\n 'copy-x': CopyX,\n 'credit-card': CreditCard,\n 'crown': Crown,\n 'database': Database,\n 'dollar-sign': DollarSign,\n 'download': Download,\n 'external-link': ExternalLink,\n 'eye': Eye,\n 'file-check': FileCheck,\n 'file-minus': FileMinus,\n 'file-pen-line': FilePenLine,\n 'file-spreadsheet': FileSpreadsheet,\n 'file-text': FileText,\n 'files': Files,\n 'filter-x': FilterX,\n 'flag': Flag,\n 'flame': Flame,\n 'folder-tree': FolderTree,\n 'gauge': Gauge,\n 'git-branch': GitBranch,\n 'git-compare-arrows': GitCompareArrows,\n 'git-pull-request-arrow': GitPullRequestArrow,\n 'globe': Globe,\n 'graduation-cap': GraduationCap,\n 'hammer': Hammer,\n 'hand': Hand,\n 'handshake': Handshake,\n 'headphones': Headphones,\n 'heart': Heart,\n 'help-circle': HelpCircle,\n 'hourglass': Hourglass,\n 'inbox': Inbox,\n 'key': Key,\n 'key-round': KeyRound,\n 'layers': Layers,\n 'leaf': Leaf,\n 'lightbulb': Lightbulb,\n 'line-chart': LineChart,\n 'link': Link,\n 'list': List,\n 'list-x': ListX,\n 'loader': Loader,\n 'loader-2': Loader2,\n 'lock': Lock,\n 'mail': Mail,\n 'mail-open': MailOpen,\n 'map': Map,\n 'map-pin': MapPin,\n 'map-pinned': MapPinned,\n 'megaphone': Megaphone,\n 'message-circle': MessageCircle,\n 'message-square-reply': MessageSquareReply,\n 'minus-circle': MinusCircle,\n 'notebook': Notebook,\n 'package': Package,\n 'package-check': PackageCheck,\n 'package-plus': PackagePlus,\n 'package-search': PackageSearch,\n 'package-x': PackageX,\n 'pause-circle': PauseCircle,\n 'percent': Percent,\n 'phone': Phone,\n 'phone-call': PhoneCall,\n 'pie-chart': PieChart,\n 'plus-square': PlusSquare,\n 'receipt': Receipt,\n 'receipt-text': ReceiptText,\n 'refresh-ccw': RefreshCcw,\n 'refresh-cw': RefreshCw,\n 'repeat-2': Repeat2,\n 'reply': Reply,\n 'rotate-ccw': RotateCcw,\n 'ruler': Ruler,\n 'send': Send,\n 'settings': Settings,\n 'shapes': Shapes,\n 'share-2': Share2,\n 'shield': Shield,\n 'shield-alert': ShieldAlert,\n 'shield-check': ShieldCheck,\n 'shopping-bag': ShoppingBag,\n 'shopping-cart': ShoppingCart,\n 'shuffle': Shuffle,\n 'sliders': Sliders,\n 'smartphone': Smartphone,\n 'snowflake': Snowflake,\n 'sparkles': Sparkles,\n 'star': Star,\n 'sticky-note': StickyNote,\n 'store': Store,\n 'tag': Tag,\n 'target': Target,\n 'thumbs-up': ThumbsUp,\n 'ticket': Ticket,\n 'timer': Timer,\n 'trash-2': Trash2,\n 'trending-up': TrendingUp,\n 'triangle-alert': TriangleAlert,\n 'trophy': Trophy,\n 'truck': Truck,\n 'undo': Undo,\n 'undo-2': Undo2,\n 'unlock': Unlock,\n 'user': User,\n 'user-check': UserCheck,\n 'user-minus': UserMinus,\n 'user-plus': UserPlus,\n 'user-round': UserRound,\n 'user-x': UserX,\n 'users': Users,\n 'wallet': Wallet,\n 'warehouse': Warehouse,\n 'webhook': Webhook,\n 'workflow': Workflow,\n 'wrench': Wrench,\n 'x': X,\n 'x-circle': XCircle,\n 'zap-off': ZapOff,\n};\n"],
5
- "mappings": "AAKA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,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",
4
+ "sourcesContent": ["/* eslint-disable */\n// AUTO-GENERATED by @open-mercato/ui build. Do not edit by hand.\n// Generated from discovered icon string usages across the repo.\n\nimport type { LucideIcon } from 'lucide-react';\nimport {\n Activity,\n AlarmClock,\n AlertCircle,\n AlertOctagon,\n AlertTriangle,\n Apple,\n Archive,\n AtSign,\n Award,\n BadgeCheck,\n Ban,\n Banknote,\n BarChart2,\n BarChart3,\n Bell,\n Bolt,\n Book,\n Bookmark,\n Box,\n Boxes,\n Briefcase,\n BriefcaseBusiness,\n Building,\n Building2,\n Calendar,\n CalendarCheck,\n CalendarClock,\n CalendarCog,\n CalendarMinus,\n CalendarOff,\n CalendarX,\n Check,\n CheckCircle,\n CheckCircle2,\n CheckSquare,\n Circle,\n ClipboardCheck,\n ClipboardList,\n Clock,\n Clock3,\n Coins,\n Copy,\n CopyX,\n CreditCard,\n Crown,\n Database,\n DollarSign,\n Download,\n ExternalLink,\n Eye,\n FileCheck,\n FileMinus,\n FilePenLine,\n Files,\n FileSpreadsheet,\n FileText,\n FilterX,\n Flag,\n Flame,\n FolderTree,\n Gauge,\n GitBranch,\n GitCompareArrows,\n GitPullRequestArrow,\n Globe,\n GraduationCap,\n Hammer,\n Hand,\n Handshake,\n Headphones,\n Heart,\n HelpCircle,\n Hourglass,\n Inbox,\n Key,\n KeyRound,\n Layers,\n Leaf,\n Lightbulb,\n LineChart,\n Link,\n List,\n ListX,\n Loader,\n Loader2,\n Lock,\n Mail,\n MailOpen,\n Map,\n MapPin,\n MapPinned,\n Megaphone,\n MessageCircle,\n MessageSquareReply,\n MinusCircle,\n Notebook,\n Package,\n PackageCheck,\n PackagePlus,\n PackageSearch,\n PackageX,\n PauseCircle,\n Percent,\n Phone,\n PhoneCall,\n PieChart,\n PlusSquare,\n Receipt,\n ReceiptText,\n RefreshCcw,\n RefreshCw,\n Repeat2,\n Reply,\n RotateCcw,\n Ruler,\n Send,\n Settings,\n Shapes,\n Share2,\n Shield,\n ShieldAlert,\n ShieldCheck,\n ShoppingBag,\n ShoppingCart,\n Shuffle,\n Sliders,\n Smartphone,\n Snowflake,\n Sparkles,\n Star,\n StickyNote,\n Store,\n Tag,\n Target,\n ThumbsUp,\n Ticket,\n Timer,\n Trash2,\n TrendingUp,\n TriangleAlert,\n Trophy,\n Truck,\n Undo,\n Undo2,\n Unlock,\n User,\n UserCheck,\n UserMinus,\n UserPlus,\n UserRound,\n Users,\n UserX,\n Wallet,\n Warehouse,\n Webhook,\n Workflow,\n Wrench,\n X,\n XCircle,\n ZapOff,\n} from 'lucide-react';\n\nexport const LUCIDE_ICON_REGISTRY: Record<string, LucideIcon> = {\n 'activity': Activity,\n 'alarm-clock': AlarmClock,\n 'alert-circle': AlertCircle,\n 'alert-octagon': AlertOctagon,\n 'alert-triangle': AlertTriangle,\n 'apple': Apple,\n 'archive': Archive,\n 'at-sign': AtSign,\n 'award': Award,\n 'badge-check': BadgeCheck,\n 'ban': Ban,\n 'banknote': Banknote,\n 'bar-chart-2': BarChart2,\n 'bar-chart-3': BarChart3,\n 'bell': Bell,\n 'bolt': Bolt,\n 'book': Book,\n 'bookmark': Bookmark,\n 'box': Box,\n 'boxes': Boxes,\n 'briefcase': Briefcase,\n 'briefcase-business': BriefcaseBusiness,\n 'building': Building,\n 'building2': Building2,\n 'calendar': Calendar,\n 'calendar-check': CalendarCheck,\n 'calendar-clock': CalendarClock,\n 'calendar-cog': CalendarCog,\n 'calendar-minus': CalendarMinus,\n 'calendar-off': CalendarOff,\n 'calendar-x': CalendarX,\n 'check': Check,\n 'check-circle': CheckCircle,\n 'check-circle-2': CheckCircle2,\n 'check-square': CheckSquare,\n 'circle': Circle,\n 'clipboard-check': ClipboardCheck,\n 'clipboard-list': ClipboardList,\n 'clock': Clock,\n 'clock-3': Clock3,\n 'coins': Coins,\n 'copy': Copy,\n 'copy-x': CopyX,\n 'credit-card': CreditCard,\n 'crown': Crown,\n 'database': Database,\n 'dollar-sign': DollarSign,\n 'download': Download,\n 'external-link': ExternalLink,\n 'eye': Eye,\n 'file-check': FileCheck,\n 'file-minus': FileMinus,\n 'file-pen-line': FilePenLine,\n 'file-spreadsheet': FileSpreadsheet,\n 'file-text': FileText,\n 'files': Files,\n 'filter-x': FilterX,\n 'flag': Flag,\n 'flame': Flame,\n 'folder-tree': FolderTree,\n 'gauge': Gauge,\n 'git-branch': GitBranch,\n 'git-compare-arrows': GitCompareArrows,\n 'git-pull-request-arrow': GitPullRequestArrow,\n 'globe': Globe,\n 'graduation-cap': GraduationCap,\n 'hammer': Hammer,\n 'hand': Hand,\n 'handshake': Handshake,\n 'headphones': Headphones,\n 'heart': Heart,\n 'help-circle': HelpCircle,\n 'hourglass': Hourglass,\n 'inbox': Inbox,\n 'key': Key,\n 'key-round': KeyRound,\n 'layers': Layers,\n 'leaf': Leaf,\n 'lightbulb': Lightbulb,\n 'line-chart': LineChart,\n 'link': Link,\n 'list': List,\n 'list-x': ListX,\n 'loader': Loader,\n 'loader-2': Loader2,\n 'lock': Lock,\n 'mail': Mail,\n 'mail-open': MailOpen,\n 'map': Map,\n 'map-pin': MapPin,\n 'map-pinned': MapPinned,\n 'megaphone': Megaphone,\n 'message-circle': MessageCircle,\n 'message-square-reply': MessageSquareReply,\n 'minus-circle': MinusCircle,\n 'notebook': Notebook,\n 'package': Package,\n 'package-check': PackageCheck,\n 'package-plus': PackagePlus,\n 'package-search': PackageSearch,\n 'package-x': PackageX,\n 'pause-circle': PauseCircle,\n 'percent': Percent,\n 'phone': Phone,\n 'phone-call': PhoneCall,\n 'pie-chart': PieChart,\n 'plus-square': PlusSquare,\n 'receipt': Receipt,\n 'receipt-text': ReceiptText,\n 'refresh-ccw': RefreshCcw,\n 'refresh-cw': RefreshCw,\n 'repeat-2': Repeat2,\n 'reply': Reply,\n 'rotate-ccw': RotateCcw,\n 'ruler': Ruler,\n 'send': Send,\n 'settings': Settings,\n 'shapes': Shapes,\n 'share-2': Share2,\n 'shield': Shield,\n 'shield-alert': ShieldAlert,\n 'shield-check': ShieldCheck,\n 'shopping-bag': ShoppingBag,\n 'shopping-cart': ShoppingCart,\n 'shuffle': Shuffle,\n 'sliders': Sliders,\n 'smartphone': Smartphone,\n 'snowflake': Snowflake,\n 'sparkles': Sparkles,\n 'star': Star,\n 'sticky-note': StickyNote,\n 'store': Store,\n 'tag': Tag,\n 'target': Target,\n 'thumbs-up': ThumbsUp,\n 'ticket': Ticket,\n 'timer': Timer,\n 'trash-2': Trash2,\n 'trending-up': TrendingUp,\n 'triangle-alert': TriangleAlert,\n 'trophy': Trophy,\n 'truck': Truck,\n 'undo': Undo,\n 'undo-2': Undo2,\n 'unlock': Unlock,\n 'user': User,\n 'user-check': UserCheck,\n 'user-minus': UserMinus,\n 'user-plus': UserPlus,\n 'user-round': UserRound,\n 'user-x': UserX,\n 'users': Users,\n 'wallet': Wallet,\n 'warehouse': Warehouse,\n 'webhook': Webhook,\n 'workflow': Workflow,\n 'wrench': Wrench,\n 'x': X,\n 'x-circle': XCircle,\n 'zap-off': ZapOff,\n};\n"],
5
+ "mappings": "AAKA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,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",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,26 @@ import { Slot } from "@radix-ui/react-slot";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { cn } from "@open-mercato/shared/lib/utils";
5
5
  const iconButtonVariants = cva(
6
- "inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus aria-pressed:bg-primary aria-pressed:text-primary-foreground aria-pressed:hover:bg-primary-hover",
6
+ // The pressed surface is repeated under `dark:` on purpose: the outline and
7
+ // ghost variants ship `dark:bg-input/30` / `dark:hover:bg-accent/50`, which
8
+ // otherwise outrank the un-prefixed `aria-pressed:` background while the
9
+ // `aria-pressed:text-primary-foreground` still applies — leaving a dark icon
10
+ // on a dark surface (invisible pressed star/bell buttons on the dark theme).
11
+ //
12
+ // Every pressed rule is additionally gated on `not-disabled:` because a toggle
13
+ // can be pressed AND disabled at the same time (an active editor tool while the
14
+ // document is read-only). Without the gate the pressed rules outrank the
15
+ // `disabled:` surface — `dark:aria-pressed:bg-primary` is more specific than
16
+ // `disabled:bg-bg-disabled` — and a control the user cannot operate renders
17
+ // as a primary, actionable button.
18
+ //
19
+ // The gate MUST stay `not-disabled:` (`&:not(:disabled)`) and not `enabled:`
20
+ // (`&:enabled`): the CSS `:enabled` pseudo-class only matches form elements,
21
+ // so on an `asChild` host — this primitive is routinely rendered onto a link —
22
+ // no pressed rule could ever match and the pressed state would not paint at
23
+ // all. `:not(:disabled)` gates the same way on a real `<button>` while leaving
24
+ // a non-form host styled.
25
+ "inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus not-disabled:aria-pressed:bg-primary not-disabled:aria-pressed:text-primary-foreground not-disabled:aria-pressed:hover:bg-primary-hover dark:not-disabled:aria-pressed:bg-primary dark:not-disabled:aria-pressed:hover:bg-primary-hover",
7
26
  {
8
27
  variants: {
9
28
  variant: {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/primitives/icon-button.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst iconButtonVariants = cva(\n \"inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus aria-pressed:bg-primary aria-pressed:text-primary-foreground aria-pressed:hover:bg-primary-hover\",\n {\n variants: {\n variant: {\n primary:\n 'bg-primary text-primary-foreground shadow-xs hover:bg-primary-hover',\n destructive:\n 'bg-destructive text-white shadow-xs hover:bg-destructive/90',\n outline:\n 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n white:\n 'bg-background text-muted-foreground shadow-xs hover:bg-accent hover:text-accent-foreground',\n modifiable:\n 'bg-transparent text-current hover:bg-foreground/10',\n },\n size: {\n xs: 'size-6',\n sm: 'size-7',\n default: 'size-8',\n lg: 'size-9',\n },\n fullRadius: {\n true: 'rounded-full',\n false: 'rounded-md',\n },\n },\n defaultVariants: {\n variant: 'outline',\n size: 'default',\n fullRadius: false,\n },\n }\n)\n\nexport function IconButton({\n className,\n variant,\n size,\n fullRadius,\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof iconButtonVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n data-slot=\"icon-button\"\n type={asChild ? undefined : 'button'}\n className={cn(iconButtonVariants({ variant, size, fullRadius, className }))}\n {...props}\n />\n )\n}\n\nexport { iconButtonVariants }\n"],
5
- "mappings": "AAoDI;AAnDJ,SAAS,YAAY;AACrB,SAAS,WAA8B;AACvC,SAAS,UAAU;AAEnB,MAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,OAAO;AAAA,QACP,OACE;AAAA,QACF,YACE;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,MACA,YAAY;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,MACN,YAAY;AAAA,IACd;AAAA,EACF;AACF;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GACmE;AACjE,QAAM,OAAO,UAAU,OAAO;AAC9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,MAAM,UAAU,SAAY;AAAA,MAC5B,WAAW,GAAG,mBAAmB,EAAE,SAAS,MAAM,YAAY,UAAU,CAAC,CAAC;AAAA,MACzE,GAAG;AAAA;AAAA,EACN;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst iconButtonVariants = cva(\n // The pressed surface is repeated under `dark:` on purpose: the outline and\n // ghost variants ship `dark:bg-input/30` / `dark:hover:bg-accent/50`, which\n // otherwise outrank the un-prefixed `aria-pressed:` background while the\n // `aria-pressed:text-primary-foreground` still applies \u2014 leaving a dark icon\n // on a dark surface (invisible pressed star/bell buttons on the dark theme).\n //\n // Every pressed rule is additionally gated on `not-disabled:` because a toggle\n // can be pressed AND disabled at the same time (an active editor tool while the\n // document is read-only). Without the gate the pressed rules outrank the\n // `disabled:` surface \u2014 `dark:aria-pressed:bg-primary` is more specific than\n // `disabled:bg-bg-disabled` \u2014 and a control the user cannot operate renders\n // as a primary, actionable button.\n //\n // The gate MUST stay `not-disabled:` (`&:not(:disabled)`) and not `enabled:`\n // (`&:enabled`): the CSS `:enabled` pseudo-class only matches form elements,\n // so on an `asChild` host \u2014 this primitive is routinely rendered onto a link \u2014\n // no pressed rule could ever match and the pressed state would not paint at\n // all. `:not(:disabled)` gates the same way on a real `<button>` while leaving\n // a non-form host styled.\n \"inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus not-disabled:aria-pressed:bg-primary not-disabled:aria-pressed:text-primary-foreground not-disabled:aria-pressed:hover:bg-primary-hover dark:not-disabled:aria-pressed:bg-primary dark:not-disabled:aria-pressed:hover:bg-primary-hover\",\n {\n variants: {\n variant: {\n primary:\n 'bg-primary text-primary-foreground shadow-xs hover:bg-primary-hover',\n destructive:\n 'bg-destructive text-white shadow-xs hover:bg-destructive/90',\n outline:\n 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n white:\n 'bg-background text-muted-foreground shadow-xs hover:bg-accent hover:text-accent-foreground',\n modifiable:\n 'bg-transparent text-current hover:bg-foreground/10',\n },\n size: {\n xs: 'size-6',\n sm: 'size-7',\n default: 'size-8',\n lg: 'size-9',\n },\n fullRadius: {\n true: 'rounded-full',\n false: 'rounded-md',\n },\n },\n defaultVariants: {\n variant: 'outline',\n size: 'default',\n fullRadius: false,\n },\n }\n)\n\nexport function IconButton({\n className,\n variant,\n size,\n fullRadius,\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof iconButtonVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n data-slot=\"icon-button\"\n type={asChild ? undefined : 'button'}\n className={cn(iconButtonVariants({ variant, size, fullRadius, className }))}\n {...props}\n />\n )\n}\n\nexport { iconButtonVariants }\n"],
5
+ "mappings": "AAuEI;AAtEJ,SAAS,YAAY;AACrB,SAAS,WAA8B;AACvC,SAAS,UAAU;AAEnB,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBzB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,OAAO;AAAA,QACP,OACE;AAAA,QACF,YACE;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,MACA,YAAY;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,MACN,YAAY;AAAA,IACd;AAAA,EACF;AACF;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GACmE;AACjE,QAAM,OAAO,UAAU,OAAO;AAC9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,MAAM,UAAU,SAAY;AAAA,MAC5B,WAAW,GAAG,mBAAmB,EAAE,SAAS,MAAM,YAAY,UAAU,CAAC,CAAC;AAAA,MACzE,GAAG;AAAA;AAAA,EACN;AAEJ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/ui",
3
- "version": "0.6.8-develop.7015.1.af90a2ddc7",
3
+ "version": "0.6.8-develop.7016.1.4ed7b1e49d",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -155,14 +155,14 @@
155
155
  "remark-gfm": "^4.0.1"
156
156
  },
157
157
  "peerDependencies": {
158
- "@open-mercato/shared": "0.6.8-develop.7015.1.af90a2ddc7",
158
+ "@open-mercato/shared": "0.6.8-develop.7016.1.4ed7b1e49d",
159
159
  "react": ">=18.0.0",
160
160
  "react-dom": ">=18.0.0",
161
161
  "react-is": ">=18.0.0"
162
162
  },
163
163
  "devDependencies": {
164
164
  "@figma/code-connect": "^1.3.4",
165
- "@open-mercato/shared": "0.6.8-develop.7015.1.af90a2ddc7",
165
+ "@open-mercato/shared": "0.6.8-develop.7016.1.4ed7b1e49d",
166
166
  "@testing-library/dom": "^10.4.1",
167
167
  "@testing-library/jest-dom": "^7.0.0",
168
168
  "@testing-library/react": "^16.3.1",
@@ -772,17 +772,9 @@ function AppShellBody({ productName, logo, email, canManageUpgradeActions = fals
772
772
  setOpenGroups((prev) => (prev[key] === false ? { ...prev, [key]: true } : prev))
773
773
  // eslint-disable-next-line react-hooks/exhaustive-deps
774
774
  }, [pathname, navGroups])
775
- // Keep header state in sync with props (server-side updates)
776
- React.useEffect(() => {
777
- setHeaderTitle(currentTitle)
778
- setHeaderBreadcrumb(breadcrumb)
779
- }, [currentTitle, breadcrumb])
780
- // Clear breadcrumb on client-side navigation so stale state doesn't persist;
781
- // the new page's ApplyBreadcrumb (if any) will set the correct values.
782
- // Must be a layout effect: when a prefetched navigation commits the new
783
- // pathname and the new page together, child passive effects (ApplyBreadcrumb)
784
- // run before parent ones, so a passive clear here would wipe the value the
785
- // incoming page just set.
775
+ // Reset stale header state before applying server props and before the new
776
+ // page's passive ApplyBreadcrumb effect. The ordering matters for layouts
777
+ // that persist across client-side navigation.
786
778
  const prevPathname = React.useRef(pathname)
787
779
  useIsomorphicLayoutEffect(() => {
788
780
  if (pathname !== prevPathname.current) {
@@ -791,6 +783,12 @@ function AppShellBody({ productName, logo, email, canManageUpgradeActions = fals
791
783
  setHeaderBreadcrumb(undefined)
792
784
  }
793
785
  }, [pathname])
786
+ // Keep header state in sync with props (server-side updates). A child page's
787
+ // ApplyBreadcrumb effect runs afterward and may refine this static trail.
788
+ useIsomorphicLayoutEffect(() => {
789
+ setHeaderTitle(currentTitle)
790
+ setHeaderBreadcrumb(breadcrumb)
791
+ }, [currentTitle, breadcrumb])
794
792
 
795
793
  // Keep navGroups in sync when server-provided groups change
796
794
  React.useEffect(() => {
@@ -3193,7 +3193,10 @@ export function DataTable<T extends RowData>({
3193
3193
  const shouldRenderHeader = hasTitle || renderToolbarInline || shouldRenderActionsWrapper || shouldRenderToolbarBelow
3194
3194
  const containerClassName = embedded ? '' : 'rounded-lg border bg-card mx-1 sm:mx-2'
3195
3195
  const headerWrapperClassName = embedded ? 'pb-3' : 'px-4 py-3 border-b'
3196
- const headerContentClassName = 'flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between'
3196
+ // The header row wraps once the actions no longer fit beside the title (the
3197
+ // title keeps a 12rem floor); before, the title collapsed to a sliver and
3198
+ // the wrapped action buttons rendered over it on narrow layouts.
3199
+ const headerContentClassName = 'flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between'
3197
3200
  const toolbarWrapperClassName = embedded ? 'mt-2' : 'mt-3 pt-3 border-t'
3198
3201
  const tableScrollWrapperClassName = embedded ? '' : 'overflow-auto'
3199
3202
 
@@ -3249,11 +3252,11 @@ export function DataTable<T extends RowData>({
3249
3252
  <div className={headerWrapperClassName}>
3250
3253
  {(hasTitle || shouldRenderActionsWrapper || renderToolbarInline) && (
3251
3254
  <div className={headerContentClassName}>
3252
- <div className="flex-1 min-w-0">
3255
+ <div className="flex-1 min-w-0 sm:basis-48">
3253
3256
  {renderToolbarInline ? builtToolbar : titleContent}
3254
3257
  </div>
3255
3258
  {shouldRenderActionsWrapper ? (
3256
- <div className="flex flex-wrap items-center gap-2 min-h-[2.25rem]">
3259
+ <div className="flex flex-wrap items-center gap-2 min-h-[2.25rem] sm:ml-auto sm:justify-end">
3257
3260
  {refreshButtonConfig ? (
3258
3261
  <Button
3259
3262
  type="button"
@@ -471,6 +471,52 @@ describe('AppShell', () => {
471
471
  })
472
472
  })
473
473
 
474
+ it('keeps the new page breadcrumb after client-side navigation', async () => {
475
+ mockPathname = '/backend/documents'
476
+
477
+ const { rerender } = renderWithProviders(
478
+ <AppShell
479
+ email="demo@example.com"
480
+ groups={groups}
481
+ currentTitle="Documents"
482
+ breadcrumb={[{ label: 'Documents' }]}
483
+ >
484
+ <ApplyBreadcrumb title="Documents" breadcrumb={[{ label: 'Documents' }]} />
485
+ <div>Documents list</div>
486
+ </AppShell>,
487
+ { dict },
488
+ )
489
+
490
+ await waitFor(() => {
491
+ expect(within(screen.getByRole('navigation', { name: 'Breadcrumb' })).getByText('Documents')).toBeInTheDocument()
492
+ })
493
+
494
+ mockPathname = '/backend/documents/document-id'
495
+ rerender(
496
+ <AppShell
497
+ email="demo@example.com"
498
+ groups={groups}
499
+ currentTitle="Documents"
500
+ breadcrumb={[{ label: 'Documents' }]}
501
+ >
502
+ <ApplyBreadcrumb
503
+ title="Document"
504
+ breadcrumb={[
505
+ { label: 'Documents', href: '/backend/documents' },
506
+ { label: 'Document' },
507
+ ]}
508
+ />
509
+ <div>Document detail</div>
510
+ </AppShell>,
511
+ )
512
+
513
+ await waitFor(() => {
514
+ const breadcrumb = screen.getByRole('navigation', { name: 'Breadcrumb' })
515
+ expect(within(breadcrumb).getByRole('link', { name: 'Documents' })).toHaveAttribute('href', '/backend/documents')
516
+ expect(within(breadcrumb).getByText('Document')).toHaveAttribute('aria-current', 'page')
517
+ })
518
+ })
519
+
474
520
  it('keeps settings parent item active on descendant routes outside explicit child list', async () => {
475
521
  mockPathname = '/backend/entities/user/example%3Acalendar_entity'
476
522
 
@@ -0,0 +1,111 @@
1
+ /** @jest-environment jsdom */
2
+ import * as React from 'react'
3
+ import { DataTable } from '../DataTable'
4
+ import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'
5
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
6
+ import { I18nProvider } from '@open-mercato/shared/lib/i18n/context'
7
+ import { render } from '@testing-library/react'
8
+
9
+ jest.mock('next/navigation', () => ({
10
+ useRouter: () => ({ push: jest.fn(), replace: jest.fn(), prefetch: jest.fn() }),
11
+ }))
12
+
13
+ jest.mock('../injection/useInjectionDataWidgets', () => ({
14
+ useInjectionDataWidgets: () => ({ widgets: [], isLoading: false }),
15
+ }))
16
+
17
+ type Row = { id: string; title: string }
18
+
19
+ const tokensOf = (el: Element | null): string[] =>
20
+ (el?.getAttribute('class') ?? '').split(/\s+/).filter(Boolean)
21
+
22
+ // The header used to be a single non-wrapping `sm:flex-row` line. A title
23
+ // sitting next to a long action group (Create + Export + Refresh + injected
24
+ // toolbar buttons) had nothing but `min-w-0` holding it, so it collapsed to a
25
+ // sliver while the action buttons — which wrap on their own — spilled onto a
26
+ // second line and rendered over it. The row now wraps as a unit, the title
27
+ // keeps a 12rem floor, and the actions stay right-aligned in either layout.
28
+ describe('DataTable header row wrapping', () => {
29
+ function renderHeaderTable() {
30
+ const columns: ColumnDef<Row>[] = [{ accessorKey: 'title', header: 'Title' }]
31
+ const queryClient = new QueryClient({ defaultOptions: { queries: { gcTime: 0 } } })
32
+ const result = render(
33
+ <QueryClientProvider client={queryClient}>
34
+ <I18nProvider locale="en" dict={{}}>
35
+ <DataTable
36
+ title="Documents"
37
+ actions={<button type="button">Create document</button>}
38
+ columns={columns}
39
+ data={[{ id: '1', title: 'Solar rollout' }]}
40
+ />
41
+ </I18nProvider>
42
+ </QueryClientProvider>,
43
+ )
44
+ return { ...result, queryClient }
45
+ }
46
+
47
+ function headerParts(container: HTMLElement) {
48
+ const headerContent = Array.from(container.querySelectorAll('div')).find((el) =>
49
+ tokensOf(el).includes('sm:flex-row'),
50
+ ) ?? null
51
+ return {
52
+ headerContent,
53
+ titleSlot: headerContent?.firstElementChild ?? null,
54
+ actionsSlot: headerContent?.lastElementChild ?? null,
55
+ }
56
+ }
57
+
58
+ it('lets the header row wrap instead of crushing the title', () => {
59
+ const { container, queryClient } = renderHeaderTable()
60
+ try {
61
+ const { headerContent } = headerParts(container)
62
+ expect(headerContent).not.toBeNull()
63
+ expect(tokensOf(headerContent)).toEqual(
64
+ expect.arrayContaining([
65
+ 'flex',
66
+ 'flex-col',
67
+ 'gap-2',
68
+ 'sm:flex-row',
69
+ 'sm:flex-wrap',
70
+ 'sm:items-center',
71
+ 'sm:justify-between',
72
+ ]),
73
+ )
74
+ } finally {
75
+ queryClient.clear()
76
+ }
77
+ })
78
+
79
+ it('gives the title a wrap threshold instead of an unbounded shrink', () => {
80
+ const { container, queryClient } = renderHeaderTable()
81
+ try {
82
+ const { titleSlot } = headerParts(container)
83
+ expect(titleSlot?.textContent).toContain('Documents')
84
+ expect(tokensOf(titleSlot)).toEqual(
85
+ expect.arrayContaining(['flex-1', 'min-w-0', 'sm:basis-48']),
86
+ )
87
+ } finally {
88
+ queryClient.clear()
89
+ }
90
+ })
91
+
92
+ it('keeps the actions right-aligned once the row has wrapped', () => {
93
+ const { container, queryClient } = renderHeaderTable()
94
+ try {
95
+ const { actionsSlot } = headerParts(container)
96
+ expect(actionsSlot?.textContent).toContain('Create document')
97
+ expect(tokensOf(actionsSlot)).toEqual(
98
+ expect.arrayContaining([
99
+ 'flex',
100
+ 'flex-wrap',
101
+ 'items-center',
102
+ 'gap-2',
103
+ 'sm:ml-auto',
104
+ 'sm:justify-end',
105
+ ]),
106
+ )
107
+ } finally {
108
+ queryClient.clear()
109
+ }
110
+ })
111
+ })
@@ -11,6 +11,7 @@ import {
11
11
  AlertTriangle,
12
12
  Apple,
13
13
  Archive,
14
+ AtSign,
14
15
  Award,
15
16
  BadgeCheck,
16
17
  Ban,
@@ -173,6 +174,7 @@ export const LUCIDE_ICON_REGISTRY: Record<string, LucideIcon> = {
173
174
  'alert-triangle': AlertTriangle,
174
175
  'apple': Apple,
175
176
  'archive': Archive,
177
+ 'at-sign': AtSign,
176
178
  'award': Award,
177
179
  'badge-check': BadgeCheck,
178
180
  'ban': Ban,
@@ -38,3 +38,73 @@ describe('IconButton solid variants', () => {
38
38
  expect(className).not.toContain('dark:bg-input')
39
39
  })
40
40
  })
41
+
42
+ describe('IconButton pressed state', () => {
43
+ // The pressed surface must be restated under `dark:` for the same reason:
44
+ // `variant="outline"` (`dark:bg-input/30`) and `variant="ghost"`
45
+ // (`dark:hover:bg-accent/50`) otherwise outrank `aria-pressed:bg-primary`
46
+ // while `aria-pressed:text-primary-foreground` still applies, leaving a
47
+ // dark icon on a dark surface (invisible favorite/watch toggles).
48
+ it.each(['outline', 'ghost'] as const)('keeps the primary fill on a pressed %s button in dark mode', (variant) => {
49
+ const classes = iconButtonVariants({ variant })
50
+ expect(classes).toContain('not-disabled:aria-pressed:bg-primary')
51
+ expect(classes).toContain('dark:not-disabled:aria-pressed:bg-primary')
52
+ expect(classes).toContain('dark:not-disabled:aria-pressed:hover:bg-primary-hover')
53
+ })
54
+
55
+ // A toggle can be pressed and disabled at once — an active editor tool on a
56
+ // read-only document. The pressed rules are more specific than the
57
+ // `disabled:` surface, so without a not-disabled gate the disabled control
58
+ // renders as a primary, actionable button in both themes.
59
+ it.each(['outline', 'ghost'] as const)(
60
+ 'never lets the pressed surface outrank the disabled surface on a %s button',
61
+ (variant) => {
62
+ const classes = iconButtonVariants({ variant })
63
+ expect(classes).toContain('disabled:bg-bg-disabled')
64
+ expect(classes).toContain('disabled:text-text-disabled')
65
+ for (const pressed of classes.split(' ').filter((cls) => cls.includes('aria-pressed:'))) {
66
+ expect(pressed).toContain('not-disabled:aria-pressed:')
67
+ }
68
+ },
69
+ )
70
+
71
+ it('renders a pressed disabled toggle with only not-disabled-gated pressed rules', () => {
72
+ const { getByRole } = render(
73
+ <IconButton variant="outline" aria-label="Highlight" aria-pressed disabled>
74
+ <svg />
75
+ </IconButton>,
76
+ )
77
+ const classes = getByRole('button').className.split(' ')
78
+ expect(classes).toContain('disabled:bg-bg-disabled')
79
+ expect(classes).not.toContain('aria-pressed:bg-primary')
80
+ expect(classes).not.toContain('dark:aria-pressed:bg-primary')
81
+ expect(classes).toContain('not-disabled:aria-pressed:bg-primary')
82
+ })
83
+
84
+ // `enabled:` compiles to `&:enabled`, which the CSS spec restricts to form
85
+ // elements. `IconButton` supports `asChild` and is rendered onto links across
86
+ // the app (MessagesIcon, RoleAssignmentRow, DealsSection), so an `enabled:`
87
+ // gate would silently drop the pressed state on every one of those hosts.
88
+ // `not-disabled:` (`&:not(:disabled)`) matches a non-form host just fine.
89
+ it('keeps the pressed surface on an asChild anchor host', () => {
90
+ const { getByRole } = render(
91
+ <IconButton variant="ghost" asChild aria-pressed>
92
+ <a href="/inbox" aria-label="Messages">
93
+ <svg />
94
+ </a>
95
+ </IconButton>,
96
+ )
97
+ const anchor = getByRole('link')
98
+ const classes = anchor.className.split(' ')
99
+ expect(anchor.tagName).toBe('A')
100
+ expect(classes).toContain('not-disabled:aria-pressed:bg-primary')
101
+ expect(classes).toContain('not-disabled:aria-pressed:text-primary-foreground')
102
+ expect(classes).toContain('dark:not-disabled:aria-pressed:bg-primary')
103
+ // The whole point of the fix: no pressed rule may be gated on `:enabled`,
104
+ // which can never match an anchor.
105
+ for (const pressed of classes.filter((cls) => cls.includes('aria-pressed:'))) {
106
+ expect(pressed).not.toContain('enabled:aria-pressed:')
107
+ expect(pressed).toContain('not-disabled:aria-pressed:')
108
+ }
109
+ })
110
+ })
@@ -4,7 +4,26 @@ import { cva, type VariantProps } from 'class-variance-authority'
4
4
  import { cn } from '@open-mercato/shared/lib/utils'
5
5
 
6
6
  const iconButtonVariants = cva(
7
- "inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus aria-pressed:bg-primary aria-pressed:text-primary-foreground aria-pressed:hover:bg-primary-hover",
7
+ // The pressed surface is repeated under `dark:` on purpose: the outline and
8
+ // ghost variants ship `dark:bg-input/30` / `dark:hover:bg-accent/50`, which
9
+ // otherwise outrank the un-prefixed `aria-pressed:` background while the
10
+ // `aria-pressed:text-primary-foreground` still applies — leaving a dark icon
11
+ // on a dark surface (invisible pressed star/bell buttons on the dark theme).
12
+ //
13
+ // Every pressed rule is additionally gated on `not-disabled:` because a toggle
14
+ // can be pressed AND disabled at the same time (an active editor tool while the
15
+ // document is read-only). Without the gate the pressed rules outrank the
16
+ // `disabled:` surface — `dark:aria-pressed:bg-primary` is more specific than
17
+ // `disabled:bg-bg-disabled` — and a control the user cannot operate renders
18
+ // as a primary, actionable button.
19
+ //
20
+ // The gate MUST stay `not-disabled:` (`&:not(:disabled)`) and not `enabled:`
21
+ // (`&:enabled`): the CSS `:enabled` pseudo-class only matches form elements,
22
+ // so on an `asChild` host — this primitive is routinely rendered onto a link —
23
+ // no pressed rule could ever match and the pressed state would not paint at
24
+ // all. `:not(:disabled)` gates the same way on a real `<button>` while leaving
25
+ // a non-form host styled.
26
+ "inline-flex items-center justify-center cursor-pointer transition-all outline-none disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-disabled disabled:shadow-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:outline-none focus-visible:shadow-focus not-disabled:aria-pressed:bg-primary not-disabled:aria-pressed:text-primary-foreground not-disabled:aria-pressed:hover:bg-primary-hover dark:not-disabled:aria-pressed:bg-primary dark:not-disabled:aria-pressed:hover:bg-primary-hover",
8
27
  {
9
28
  variants: {
10
29
  variant: {