@open-mercato/ui 0.6.7-develop.6646.1.be515f3d49 → 0.6.7-develop.6649.1.e507f22d71
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.
package/dist/primitives/tabs.js
CHANGED
|
@@ -96,10 +96,14 @@ function TabsTrigger({
|
|
|
96
96
|
// Underline trigger — flat, bottom-border accent when active.
|
|
97
97
|
// Negative margin-bottom -1px so the active accent sits on
|
|
98
98
|
// top of the rail's border-bottom (rather than below it).
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
// Hover fills a subtle violet background wash (+ violet text and icon),
|
|
100
|
+
// token-driven so it holds in light and dark. The selected tab still
|
|
101
|
+
// owns the solid accent-indigo underline, so the filled hover never gets
|
|
102
|
+
// confused with the active state.
|
|
103
|
+
orientation === "vertical" ? "group relative inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo" : "group relative -mb-px inline-flex items-center gap-2 rounded-t-md border-b-2 border-transparent px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo",
|
|
104
|
+
"focus-visible:shadow-focus",
|
|
101
105
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
102
|
-
isSelected ? orientation === "vertical" ? "bg-muted/40 text-foreground" : "border-accent-indigo font-semibold text-foreground" : "",
|
|
106
|
+
isSelected ? orientation === "vertical" ? "bg-muted/40 text-foreground hover:bg-muted/40 hover:text-foreground" : "border-accent-indigo font-semibold text-foreground hover:border-accent-indigo hover:bg-transparent hover:text-foreground" : "",
|
|
103
107
|
className
|
|
104
108
|
),
|
|
105
109
|
children: [
|
|
@@ -110,7 +114,7 @@ function TabsTrigger({
|
|
|
110
114
|
"aria-hidden": "true",
|
|
111
115
|
className: cn(
|
|
112
116
|
"inline-flex shrink-0 items-center justify-center",
|
|
113
|
-
isSelected ? "text-accent-indigo" : "text-muted-foreground"
|
|
117
|
+
isSelected ? "text-accent-indigo" : "text-muted-foreground group-hover:text-accent-indigo"
|
|
114
118
|
),
|
|
115
119
|
children: leading
|
|
116
120
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/primitives/tabs.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createContext, useContext } from 'react'\n\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from './button'\n\n/**\n * Tab navigation primitive \u2014 backward compatible with the original\n * pill-style API. Phase B.5 rewrite adds the Figma underline variant\n * (`Tab Menu Horizontal [1.1]` in `553:734`), the vertical orientation\n * (`Tab Menu Vertical [1.1]`), and per-tab `leading` icon + `count`\n * badge slots.\n *\n * Backward compatibility (6 import sites):\n * integrations/[id]/page.tsx\n * scheduler JobLogsModal.tsx\n * checkout LinkTemplateForm.tsx\n * search VectorSearchSection.tsx + FulltextSearchSection.tsx\n * ai-assistant AiPlaygroundPageClient.tsx\n *\n * All six call `<Tabs>` + `<TabsList>` + `<TabsTrigger>` +\n * `<TabsContent>` with the default pill look. The default `variant`\n * stays `pill` so they keep rendering verbatim.\n */\n\ntype TabsContextValue = {\n value: string\n onValueChange: (value: string) => void\n variant: 'pill' | 'underline'\n orientation: 'horizontal' | 'vertical'\n}\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(undefined)\n\nexport function useTabsContext() {\n const context = useContext(TabsContext)\n if (!context) {\n throw new Error('Tabs components must be used within a Tabs provider')\n }\n return context\n}\n\nexport type TabsVariant = 'pill' | 'underline'\nexport type TabsOrientation = 'horizontal' | 'vertical'\n\nexport type TabsProps = {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n /** Visual style. `pill` is the original look (bg-muted container,\n * bg-background selected pill). `underline` matches Figma `Tab Menu\n * Horizontal [1.1]` \u2014 flat strip with a thin border-bottom and an\n * accent-indigo underline on the active tab. */\n variant?: TabsVariant\n /** Tab strip orientation. `horizontal` lays the strip in a row;\n * `vertical` lays it in a column. The default `pill` variant\n * supports both; the underline variant supports only `horizontal`\n * (per Figma \u2014 vertical underline is not a documented pattern). */\n orientation?: TabsOrientation\n children: React.ReactNode\n className?: string\n}\n\nexport function Tabs({\n value: controlledValue,\n defaultValue,\n onValueChange,\n variant = 'pill',\n orientation = 'horizontal',\n children,\n className,\n}: TabsProps) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue ?? '')\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n },\n [isControlled, onValueChange],\n )\n\n const contextValue = React.useMemo<TabsContextValue>(\n () => ({ value, onValueChange: handleValueChange, variant, orientation }),\n [value, handleValueChange, variant, orientation],\n )\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div\n data-slot=\"tabs\"\n data-variant={variant}\n data-orientation={orientation}\n className={cn(orientation === 'vertical' ? 'flex gap-4' : '', className)}\n >\n {children}\n </div>\n </TabsContext.Provider>\n )\n}\n\nexport type TabsListProps = {\n children: React.ReactNode\n className?: string\n /** Accessible name for the `role=\"tablist\"` element. Set it when the\n * surrounding context does not already label the strip (e.g. a bare\n * detail-page section switcher). */\n 'aria-label'?: string\n}\n\nexport function TabsList({ children, className, 'aria-label': ariaLabel }: TabsListProps) {\n const { variant, orientation } = useTabsContext()\n\n const baseClasses =\n variant === 'underline'\n ? // Underline strip \u2014 flat, full-width border-bottom for the rail,\n // selected trigger gets its own border-b-2 accent below.\n orientation === 'vertical'\n ? 'inline-flex flex-col items-stretch gap-1 border-r border-input pr-3'\n : 'inline-flex h-10 items-center justify-start gap-4 border-b border-input text-muted-foreground'\n : // Pill strip (original) \u2014 rounded container, bg-muted shell.\n orientation === 'vertical'\n ? 'inline-flex flex-col items-stretch gap-1 rounded-lg bg-muted p-1 text-muted-foreground'\n : 'inline-flex h-9 items-center justify-start gap-1 rounded-lg bg-muted p-1 text-muted-foreground'\n\n return (\n <div\n data-slot=\"tabs-list\"\n className={cn(baseClasses, className)}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation={orientation}\n >\n {children}\n </div>\n )\n}\n\nexport type TabsTriggerProps = {\n value: string\n children: React.ReactNode\n className?: string\n disabled?: boolean\n /** Optional leading icon slot \u2014 typically a lucide-react icon at\n * `size-4`. Per Figma `Tab Menu Horizontal Items [1.1]`. */\n leading?: React.ReactNode\n /** Optional trailing count badge \u2014 typically a numeric count or\n * \"New\". Rendered as a muted pill that highlights to indigo when\n * the tab is selected. */\n count?: React.ReactNode\n}\n\nexport function TabsTrigger({\n value,\n children,\n className,\n disabled,\n leading,\n count,\n}: TabsTriggerProps) {\n const { value: selectedValue, onValueChange, variant, orientation } = useTabsContext()\n const isSelected = selectedValue === value\n\n if (variant === 'underline') {\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n disabled={disabled}\n onClick={() => onValueChange(value)}\n data-slot=\"tabs-trigger\"\n data-state={isSelected ? 'active' : 'inactive'}\n data-variant=\"underline\"\n className={cn(\n // Underline trigger \u2014 flat, bottom-border accent when active.\n // Negative margin-bottom -1px so the active accent sits on\n // top of the rail's border-bottom (rather than below it).\n orientation === 'vertical'\n ? 'group relative inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors'\n : 'group relative -mb-px inline-flex items-center gap-2 border-b-2 border-transparent px-1 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors',\n 'hover:text-foreground focus-visible:shadow-focus',\n 'disabled:pointer-events-none disabled:opacity-50',\n isSelected\n ? orientation === 'vertical'\n ? 'bg-muted/40 text-foreground'\n : 'border-accent-indigo font-semibold text-foreground'\n : '',\n className,\n )}\n >\n {leading ? (\n <span\n data-slot=\"tabs-trigger-leading\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center',\n isSelected ? 'text-accent-indigo' : 'text-muted-foreground',\n )}\n >\n {leading}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{children}</span>\n {count !== undefined ? (\n <span\n data-slot=\"tabs-trigger-count\"\n className={cn(\n 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 text-xs font-medium',\n isSelected\n ? 'bg-accent-indigo/10 text-accent-indigo'\n : 'bg-muted text-muted-foreground',\n )}\n >\n {count}\n </span>\n ) : null}\n </button>\n )\n }\n\n // Pill variant (original look) \u2014 `<Button variant=\"ghost\" size=\"sm\">`\n // with state classes. Backward compatible.\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n role=\"tab\"\n aria-selected={isSelected}\n disabled={disabled}\n onClick={() => onValueChange(value)}\n data-slot=\"tabs-trigger\"\n data-state={isSelected ? 'active' : 'inactive'}\n data-variant=\"pill\"\n className={cn(\n 'gap-2',\n isSelected\n ? 'bg-background text-foreground shadow'\n : 'hover:bg-background/80 hover:text-foreground',\n className,\n )}\n >\n {leading ? (\n <span\n data-slot=\"tabs-trigger-leading\"\n aria-hidden=\"true\"\n className=\"inline-flex shrink-0 items-center justify-center\"\n >\n {leading}\n </span>\n ) : null}\n <span>{children}</span>\n {count !== undefined ? (\n <span\n data-slot=\"tabs-trigger-count\"\n className={cn(\n 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 text-xs font-medium',\n isSelected\n ? 'bg-accent-indigo/10 text-accent-indigo'\n : 'bg-background/60 text-muted-foreground',\n )}\n >\n {count}\n </span>\n ) : null}\n </Button>\n )\n}\n\nexport type TabsContentProps = {\n value: string\n children: React.ReactNode\n className?: string\n}\n\nexport function TabsContent({ value, children, className }: TabsContentProps) {\n const { value: selectedValue, orientation } = useTabsContext()\n\n if (selectedValue !== value) {\n return null\n }\n\n return (\n <div\n role=\"tabpanel\"\n data-slot=\"tabs-content\"\n className={cn(\n orientation === 'vertical' ? 'flex-1 min-w-0' : 'mt-2',\n 'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className,\n )}\n >\n {children}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": ";AA+FM,cA4EA,YA5EA;AA7FN,YAAY,WAAW;AACvB,SAAS,eAAe,kBAAkB;AAE1C,SAAS,UAAU;AACnB,SAAS,cAAc;AA4BhB,MAAM,cAAc,cAA4C,MAAS;AAEzE,SAAS,iBAAiB;AAC/B,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;AAuBO,SAAS,KAAK;AAAA,EACnB,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAc;AACZ,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAS,gBAAgB,EAAE;AACnF,QAAM,eAAe,oBAAoB;AACzC,QAAM,QAAQ,eAAe,kBAAkB;AAE/C,QAAM,oBAAoB,MAAM;AAAA,IAC9B,CAAC,aAAqB;AACpB,UAAI,CAAC,cAAc;AACjB,6BAAqB,QAAQ;AAAA,MAC/B;AACA,sBAAgB,QAAQ;AAAA,IAC1B;AAAA,IACA,CAAC,cAAc,aAAa;AAAA,EAC9B;AAEA,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,EAAE,OAAO,eAAe,mBAAmB,SAAS,YAAY;AAAA,IACvE,CAAC,OAAO,mBAAmB,SAAS,WAAW;AAAA,EACjD;AAEA,SACE,oBAAC,YAAY,UAAZ,EAAqB,OAAO,cAC3B;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,oBAAkB;AAAA,MAClB,WAAW,GAAG,gBAAgB,aAAa,eAAe,IAAI,SAAS;AAAA,MAEtE;AAAA;AAAA,EACH,GACF;AAEJ;AAWO,SAAS,SAAS,EAAE,UAAU,WAAW,cAAc,UAAU,GAAkB;AACxF,QAAM,EAAE,SAAS,YAAY,IAAI,eAAe;AAEhD,QAAM,cACJ,YAAY;AAAA;AAAA;AAAA,IAGR,gBAAgB,aACZ,wEACA;AAAA;AAAA;AAAA,IAEJ,gBAAgB,aACd,2FACA;AAAA;AAER,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,aAAa,SAAS;AAAA,MACpC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,oBAAkB;AAAA,MAEjB;AAAA;AAAA,EACH;AAEJ;AAgBO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,EAAE,OAAO,eAAe,eAAe,SAAS,YAAY,IAAI,eAAe;AACrF,QAAM,aAAa,kBAAkB;AAErC,MAAI,YAAY,aAAa;AAC3B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,iBAAe;AAAA,QACf;AAAA,QACA,SAAS,MAAM,cAAc,KAAK;AAAA,QAClC,aAAU;AAAA,QACV,cAAY,aAAa,WAAW;AAAA,QACpC,gBAAa;AAAA,QACb,WAAW;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { createContext, useContext } from 'react'\n\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from './button'\n\n/**\n * Tab navigation primitive \u2014 backward compatible with the original\n * pill-style API. Phase B.5 rewrite adds the Figma underline variant\n * (`Tab Menu Horizontal [1.1]` in `553:734`), the vertical orientation\n * (`Tab Menu Vertical [1.1]`), and per-tab `leading` icon + `count`\n * badge slots.\n *\n * Backward compatibility (6 import sites):\n * integrations/[id]/page.tsx\n * scheduler JobLogsModal.tsx\n * checkout LinkTemplateForm.tsx\n * search VectorSearchSection.tsx + FulltextSearchSection.tsx\n * ai-assistant AiPlaygroundPageClient.tsx\n *\n * All six call `<Tabs>` + `<TabsList>` + `<TabsTrigger>` +\n * `<TabsContent>` with the default pill look. The default `variant`\n * stays `pill` so they keep rendering verbatim.\n */\n\ntype TabsContextValue = {\n value: string\n onValueChange: (value: string) => void\n variant: 'pill' | 'underline'\n orientation: 'horizontal' | 'vertical'\n}\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(undefined)\n\nexport function useTabsContext() {\n const context = useContext(TabsContext)\n if (!context) {\n throw new Error('Tabs components must be used within a Tabs provider')\n }\n return context\n}\n\nexport type TabsVariant = 'pill' | 'underline'\nexport type TabsOrientation = 'horizontal' | 'vertical'\n\nexport type TabsProps = {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n /** Visual style. `pill` is the original look (bg-muted container,\n * bg-background selected pill). `underline` matches Figma `Tab Menu\n * Horizontal [1.1]` \u2014 flat strip with a thin border-bottom and an\n * accent-indigo underline on the active tab. */\n variant?: TabsVariant\n /** Tab strip orientation. `horizontal` lays the strip in a row;\n * `vertical` lays it in a column. The default `pill` variant\n * supports both; the underline variant supports only `horizontal`\n * (per Figma \u2014 vertical underline is not a documented pattern). */\n orientation?: TabsOrientation\n children: React.ReactNode\n className?: string\n}\n\nexport function Tabs({\n value: controlledValue,\n defaultValue,\n onValueChange,\n variant = 'pill',\n orientation = 'horizontal',\n children,\n className,\n}: TabsProps) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue ?? '')\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n },\n [isControlled, onValueChange],\n )\n\n const contextValue = React.useMemo<TabsContextValue>(\n () => ({ value, onValueChange: handleValueChange, variant, orientation }),\n [value, handleValueChange, variant, orientation],\n )\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div\n data-slot=\"tabs\"\n data-variant={variant}\n data-orientation={orientation}\n className={cn(orientation === 'vertical' ? 'flex gap-4' : '', className)}\n >\n {children}\n </div>\n </TabsContext.Provider>\n )\n}\n\nexport type TabsListProps = {\n children: React.ReactNode\n className?: string\n /** Accessible name for the `role=\"tablist\"` element. Set it when the\n * surrounding context does not already label the strip (e.g. a bare\n * detail-page section switcher). */\n 'aria-label'?: string\n}\n\nexport function TabsList({ children, className, 'aria-label': ariaLabel }: TabsListProps) {\n const { variant, orientation } = useTabsContext()\n\n const baseClasses =\n variant === 'underline'\n ? // Underline strip \u2014 flat, full-width border-bottom for the rail,\n // selected trigger gets its own border-b-2 accent below.\n orientation === 'vertical'\n ? 'inline-flex flex-col items-stretch gap-1 border-r border-input pr-3'\n : 'inline-flex h-10 items-center justify-start gap-4 border-b border-input text-muted-foreground'\n : // Pill strip (original) \u2014 rounded container, bg-muted shell.\n orientation === 'vertical'\n ? 'inline-flex flex-col items-stretch gap-1 rounded-lg bg-muted p-1 text-muted-foreground'\n : 'inline-flex h-9 items-center justify-start gap-1 rounded-lg bg-muted p-1 text-muted-foreground'\n\n return (\n <div\n data-slot=\"tabs-list\"\n className={cn(baseClasses, className)}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation={orientation}\n >\n {children}\n </div>\n )\n}\n\nexport type TabsTriggerProps = {\n value: string\n children: React.ReactNode\n className?: string\n disabled?: boolean\n /** Optional leading icon slot \u2014 typically a lucide-react icon at\n * `size-4`. Per Figma `Tab Menu Horizontal Items [1.1]`. */\n leading?: React.ReactNode\n /** Optional trailing count badge \u2014 typically a numeric count or\n * \"New\". Rendered as a muted pill that highlights to indigo when\n * the tab is selected. */\n count?: React.ReactNode\n}\n\nexport function TabsTrigger({\n value,\n children,\n className,\n disabled,\n leading,\n count,\n}: TabsTriggerProps) {\n const { value: selectedValue, onValueChange, variant, orientation } = useTabsContext()\n const isSelected = selectedValue === value\n\n if (variant === 'underline') {\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n disabled={disabled}\n onClick={() => onValueChange(value)}\n data-slot=\"tabs-trigger\"\n data-state={isSelected ? 'active' : 'inactive'}\n data-variant=\"underline\"\n className={cn(\n // Underline trigger \u2014 flat, bottom-border accent when active.\n // Negative margin-bottom -1px so the active accent sits on\n // top of the rail's border-bottom (rather than below it).\n // Hover fills a subtle violet background wash (+ violet text and icon),\n // token-driven so it holds in light and dark. The selected tab still\n // owns the solid accent-indigo underline, so the filled hover never gets\n // confused with the active state.\n orientation === 'vertical'\n ? 'group relative inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo'\n : 'group relative -mb-px inline-flex items-center gap-2 rounded-t-md border-b-2 border-transparent px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo',\n 'focus-visible:shadow-focus',\n 'disabled:pointer-events-none disabled:opacity-50',\n isSelected\n ? orientation === 'vertical'\n ? 'bg-muted/40 text-foreground hover:bg-muted/40 hover:text-foreground'\n : 'border-accent-indigo font-semibold text-foreground hover:border-accent-indigo hover:bg-transparent hover:text-foreground'\n : '',\n className,\n )}\n >\n {leading ? (\n <span\n data-slot=\"tabs-trigger-leading\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center',\n isSelected ? 'text-accent-indigo' : 'text-muted-foreground group-hover:text-accent-indigo',\n )}\n >\n {leading}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{children}</span>\n {count !== undefined ? (\n <span\n data-slot=\"tabs-trigger-count\"\n className={cn(\n 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 text-xs font-medium',\n isSelected\n ? 'bg-accent-indigo/10 text-accent-indigo'\n : 'bg-muted text-muted-foreground',\n )}\n >\n {count}\n </span>\n ) : null}\n </button>\n )\n }\n\n // Pill variant (original look) \u2014 `<Button variant=\"ghost\" size=\"sm\">`\n // with state classes. Backward compatible.\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n role=\"tab\"\n aria-selected={isSelected}\n disabled={disabled}\n onClick={() => onValueChange(value)}\n data-slot=\"tabs-trigger\"\n data-state={isSelected ? 'active' : 'inactive'}\n data-variant=\"pill\"\n className={cn(\n 'gap-2',\n isSelected\n ? 'bg-background text-foreground shadow'\n : 'hover:bg-background/80 hover:text-foreground',\n className,\n )}\n >\n {leading ? (\n <span\n data-slot=\"tabs-trigger-leading\"\n aria-hidden=\"true\"\n className=\"inline-flex shrink-0 items-center justify-center\"\n >\n {leading}\n </span>\n ) : null}\n <span>{children}</span>\n {count !== undefined ? (\n <span\n data-slot=\"tabs-trigger-count\"\n className={cn(\n 'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 text-xs font-medium',\n isSelected\n ? 'bg-accent-indigo/10 text-accent-indigo'\n : 'bg-background/60 text-muted-foreground',\n )}\n >\n {count}\n </span>\n ) : null}\n </Button>\n )\n}\n\nexport type TabsContentProps = {\n value: string\n children: React.ReactNode\n className?: string\n}\n\nexport function TabsContent({ value, children, className }: TabsContentProps) {\n const { value: selectedValue, orientation } = useTabsContext()\n\n if (selectedValue !== value) {\n return null\n }\n\n return (\n <div\n role=\"tabpanel\"\n data-slot=\"tabs-content\"\n className={cn(\n orientation === 'vertical' ? 'flex-1 min-w-0' : 'mt-2',\n 'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className,\n )}\n >\n {children}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
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.7-develop.
|
|
3
|
+
"version": "0.6.7-develop.6649.1.e507f22d71",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -155,13 +155,13 @@
|
|
|
155
155
|
"remark-gfm": "^4.0.1"
|
|
156
156
|
},
|
|
157
157
|
"peerDependencies": {
|
|
158
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
158
|
+
"@open-mercato/shared": "0.6.7-develop.6649.1.e507f22d71",
|
|
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
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
164
|
+
"@open-mercato/shared": "0.6.7-develop.6649.1.e507f22d71",
|
|
165
165
|
"@testing-library/dom": "^10.4.1",
|
|
166
166
|
"@testing-library/jest-dom": "^6.9.1",
|
|
167
167
|
"@testing-library/react": "^16.3.1",
|
package/src/primitives/tabs.tsx
CHANGED
|
@@ -182,15 +182,19 @@ export function TabsTrigger({
|
|
|
182
182
|
// Underline trigger — flat, bottom-border accent when active.
|
|
183
183
|
// Negative margin-bottom -1px so the active accent sits on
|
|
184
184
|
// top of the rail's border-bottom (rather than below it).
|
|
185
|
+
// Hover fills a subtle violet background wash (+ violet text and icon),
|
|
186
|
+
// token-driven so it holds in light and dark. The selected tab still
|
|
187
|
+
// owns the solid accent-indigo underline, so the filled hover never gets
|
|
188
|
+
// confused with the active state.
|
|
185
189
|
orientation === 'vertical'
|
|
186
|
-
? 'group relative inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors'
|
|
187
|
-
: 'group relative -mb-px inline-flex items-center gap-2 border-b-2 border-transparent px-
|
|
188
|
-
'
|
|
190
|
+
? 'group relative inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo'
|
|
191
|
+
: 'group relative -mb-px inline-flex items-center gap-2 rounded-t-md border-b-2 border-transparent px-3 py-2 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-accent-indigo/10 hover:text-accent-indigo',
|
|
192
|
+
'focus-visible:shadow-focus',
|
|
189
193
|
'disabled:pointer-events-none disabled:opacity-50',
|
|
190
194
|
isSelected
|
|
191
195
|
? orientation === 'vertical'
|
|
192
|
-
? 'bg-muted/40 text-foreground'
|
|
193
|
-
: 'border-accent-indigo font-semibold text-foreground'
|
|
196
|
+
? 'bg-muted/40 text-foreground hover:bg-muted/40 hover:text-foreground'
|
|
197
|
+
: 'border-accent-indigo font-semibold text-foreground hover:border-accent-indigo hover:bg-transparent hover:text-foreground'
|
|
194
198
|
: '',
|
|
195
199
|
className,
|
|
196
200
|
)}
|
|
@@ -201,7 +205,7 @@ export function TabsTrigger({
|
|
|
201
205
|
aria-hidden="true"
|
|
202
206
|
className={cn(
|
|
203
207
|
'inline-flex shrink-0 items-center justify-center',
|
|
204
|
-
isSelected ? 'text-accent-indigo' : 'text-muted-foreground',
|
|
208
|
+
isSelected ? 'text-accent-indigo' : 'text-muted-foreground group-hover:text-accent-indigo',
|
|
205
209
|
)}
|
|
206
210
|
>
|
|
207
211
|
{leading}
|