@neasg/design-system 0.4.30 → 0.4.31

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/README.md CHANGED
@@ -325,16 +325,9 @@ Release flow:
325
325
  > git push origin main --follow-tags
326
326
  > ```
327
327
 
328
- ## Storybook Deployment
328
+ ## Storybook Validation
329
329
 
330
- Storybook is published to Chromatic from GitHub Actions. CI builds Storybook
331
- with `npm run build-storybook`, then uploads `storybook-static` with
332
- `npm run chromatic`.
333
-
334
- One-time setup:
335
-
336
- 1. Create or connect the Chromatic project for this repo.
337
- 2. Add a GitHub Actions secret named `CHROMATIC_PROJECT_TOKEN`.
338
-
339
- After that, pull requests and pushes to `main` publish a Chromatic build. The
340
- GitHub Actions log includes the published Storybook URL.
330
+ GitHub Actions builds Storybook with `npm run build-storybook` to verify that
331
+ the stories compile. The Chromatic publishing step is temporarily commented
332
+ out in `.github/workflows/ci.yml` and can be uncommented when snapshot
333
+ publishing is needed again.
package/dist/card.js CHANGED
@@ -106,7 +106,7 @@ const Card = React.forwardRef(({ title, description, variant = "default", size =
106
106
  };
107
107
  const renderedTitle = React.isValidElement(title) ? (title) : (_jsx(Typography, { as: "p", variant: hasStat ? "caption" : "body", color: variant === "gradient" ? "inherit" : hasStat ? "muted" : "foreground", className: cn(hasStat && "font-medium", !hasStat && "font-semibold", variant === "gradient" && "opacity-80"), children: title }));
108
108
  const renderedDescription = description == null ? null : React.isValidElement(description) ? (description) : (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-70" : undefined, children: description }));
109
- return (_jsxs("div", { ref: ref, onClick: onClick, onKeyDown: handleKeyDown, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, role: role !== null && role !== void 0 ? role : (interactive ? "button" : undefined), tabIndex: tabIndex !== null && tabIndex !== void 0 ? tabIndex : (interactive ? 0 : undefined), "aria-pressed": ariaPressed !== null && ariaPressed !== void 0 ? ariaPressed : (interactive && active !== undefined ? Boolean(active) : undefined), className: cn("group/card rounded-surface border border-[hsl(var(--card-border))] text-card-foreground", variant === "default" && "bg-card", variant === "elevated" && "bg-card shadow-sm", variant === "gradient" &&
109
+ return (_jsxs("div", { ref: ref, onClick: onClick, onKeyDown: handleKeyDown, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, role: role !== null && role !== void 0 ? role : (interactive ? "button" : props["aria-label"] || props["aria-labelledby"] ? "region" : undefined), tabIndex: tabIndex !== null && tabIndex !== void 0 ? tabIndex : (interactive ? 0 : undefined), "aria-pressed": ariaPressed !== null && ariaPressed !== void 0 ? ariaPressed : (interactive && active !== undefined ? Boolean(active) : undefined), className: cn("group/card rounded-surface border border-[hsl(var(--card-border))] text-card-foreground", variant === "default" && "bg-card", variant === "elevated" && "bg-card shadow-sm", variant === "gradient" &&
110
110
  "border-[hsl(var(--card-gradient-border))]/30 bg-gradient-to-br from-[hsl(var(--card-gradient-from))] to-[hsl(var(--card-gradient-to))] text-[hsl(var(--card-gradient-foreground))]", active && "border-primary bg-primary/[0.04] ring-1 ring-primary/20", accent === "primary" &&
111
111
  "border-[hsl(var(--card-border))] shadow-[inset_4px_0_0_0_hsl(var(--primary))]", interactive &&
112
112
  "cursor-pointer transition-[border-color,background-color,box-shadow,transform] duration-150 ease-out hover:border-primary/50 hover:bg-primary/5 hover:shadow-md motion-safe:hover:-translate-y-0.5 motion-safe:active:translate-y-0 motion-safe:active:scale-[0.99] focus-visible:border-primary/50 focus-visible:bg-primary/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", className), ...props, children: [_jsxs("div", { className: cn("relative flex flex-col gap-2", size === "default" && "p-4", size === "compact" && "p-3", showIcon && size === "default" && "pr-12", showIcon && size === "compact" && "pr-10"), children: [showIcon ? (_jsx("span", { "aria-hidden": "true", "data-slot": "card-icon", className: cn("pointer-events-none absolute right-3 top-3 inline-flex size-7 items-center justify-center rounded-control border border-[hsl(var(--card-border))] bg-background/80 text-muted-foreground shadow-sm transition-[background-color,color,transform] duration-150 ease-out group-hover/card:scale-105 group-hover/card:bg-highlight group-hover/card:text-highlight-foreground group-focus-visible/card:bg-highlight group-focus-visible/card:text-highlight-foreground motion-reduce:transition-colors [&_svg]:size-3.5", size === "compact" && "right-2.5 top-2.5 size-6 [&_svg]:size-3", active &&
package/dist/styles.css CHANGED
@@ -240,7 +240,7 @@
240
240
  0 3px 14px -10px rgb(15 23 42 / 0.14);
241
241
  --tab-list-background: var(--layout-chrome-background);
242
242
  --tab-list-border: var(--component-border);
243
- --tab-trigger-foreground: var(--nea-neutral-500);
243
+ --tab-trigger-foreground: 215 16% 40%;
244
244
  --tab-trigger-hover-background: var(--nea-neutral-200);
245
245
  --tab-trigger-active-background: var(--nea-neutral-0);
246
246
  --tab-trigger-active-foreground: var(--nea-neutral-900);
package/dist/table.js CHANGED
@@ -301,7 +301,7 @@ function DraggableColumnHead({ columnKey, disabled, hasResizeHandle, prevHasResi
301
301
  !isFirst &&
302
302
  "before:pointer-events-none before:absolute before:left-0 before:top-1/2 before:z-[1] before:h-6 before:-translate-y-1/2 before:w-px before:rounded-full before:bg-transparent before:transition-colors hover:before:bg-[hsl(var(--table-border))]", isDragging && "z-10 opacity-90 shadow-lg"),
303
303
  gripIcon: disabled ? null : DragGripIcon,
304
- dragHandleProps: disabled ? {} : { ...attributes, ...listeners },
304
+ dragHandleProps: disabled ? {} : { ...attributes, ...listeners, role: undefined, tabIndex: undefined },
305
305
  });
306
306
  }
307
307
  const TableColumnResizeHandle = React.forwardRef(function TableColumnResizeHandle({ column, nextColumn, currentWidth, minWidth, maxWidth, onResizeStart, onResizeByKeyboard, className, onClick, ...props }, ref) {
package/dist/tabs.d.ts CHANGED
@@ -14,6 +14,8 @@ declare const TabsRoot: React.ForwardRefExoticComponent<TabsRootProps & React.Re
14
14
  declare const TabsList: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
15
15
  interface TabsTriggerProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> {
16
16
  value: string;
17
+ /** Suppress the aria-controls attribute (use when tab panels are not rendered). */
18
+ suppressAriaControls?: boolean;
17
19
  }
18
20
  declare const TabsTrigger: React.ForwardRefExoticComponent<TabsTriggerProps & React.RefAttributes<HTMLButtonElement>>;
19
21
  interface TabsContentProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> {
package/dist/tabs.js CHANGED
@@ -34,14 +34,14 @@ const TabsRoot = React.forwardRef(({ defaultValue = "", value: valueProp, onValu
34
34
  TabsRoot.displayName = TabsPrimitive.Root.displayName;
35
35
  const TabsList = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.List, { ref: ref, className: cn("inline-flex h-fit items-stretch justify-center overflow-hidden rounded-control border border-[hsl(var(--tab-list-border))] bg-[hsl(var(--tab-list-background))] p-1 text-[hsl(var(--tab-trigger-foreground))]", className), ...props })));
36
36
  TabsList.displayName = TabsPrimitive.List.displayName;
37
- const TabsTrigger = React.forwardRef(({ className, value, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, value: value, className: cn("inline-flex min-h-8 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-sm bg-[hsl(var(--tab-list-background))] px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--tab-list-background))] disabled:pointer-events-none disabled:opacity-50 data-[state=inactive]:hover:bg-[hsl(var(--tab-trigger-hover-background))] data-[state=inactive]:hover:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:bg-[hsl(var(--tab-trigger-active-background))] data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:shadow-[0_1px_3px_rgb(15_23_42_/_0.12)]", className), ...props })));
37
+ const TabsTrigger = React.forwardRef(({ className, value, suppressAriaControls, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, value: value, "aria-controls": suppressAriaControls ? undefined : props["aria-controls"], className: cn("inline-flex min-h-8 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-sm bg-[hsl(var(--tab-list-background))] px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--tab-list-background))] disabled:pointer-events-none disabled:opacity-50 data-[state=inactive]:hover:bg-[hsl(var(--tab-trigger-hover-background))] data-[state=inactive]:hover:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:bg-[hsl(var(--tab-trigger-active-background))] data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:shadow-[0_1px_3px_rgb(15_23_42_/_0.12)]", className), ...props })));
38
38
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
39
39
  const TabsContent = React.forwardRef(({ className, value, ...props }, ref) => (_jsx(TabsPrimitive.Content, { ref: ref, value: value, className: cn("focus-visible:outline-none data-[state=inactive]:hidden", className), ...props })));
40
40
  TabsContent.displayName = TabsPrimitive.Content.displayName;
41
41
  function renderTabsItemLabel(label, active) {
42
42
  return typeof label === "function" ? label({ active }) : label;
43
43
  }
44
- function TabTriggerWithDropdown({ item, triggerClassName, contentClassName, }) {
44
+ function TabTriggerWithDropdown({ item, triggerClassName, contentClassName, suppressAriaControls, }) {
45
45
  var _a, _b, _c, _d, _e;
46
46
  const [open, setOpen] = React.useState(false);
47
47
  const sections = (_a = item.sections) !== null && _a !== void 0 ? _a : [];
@@ -82,7 +82,7 @@ function TabTriggerWithDropdown({ item, triggerClassName, contentClassName, }) {
82
82
  setInternalActiveSection((_b = (_a = sections[0]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null);
83
83
  }
84
84
  }, [isTabSelected, item.activeSection, sections]);
85
- return (_jsx(Popover, { open: open, onOpenChange: setOpen, surface: "menu", align: "start", contentClassName: cn("min-w-[12rem]", contentClassName), trigger: _jsxs(TabsTrigger, { value: item.value, disabled: item.disabled, "data-state": isTabSelected ? "active" : "inactive", "data-tab-value": item.value, className: cn("flex items-center gap-1", triggerClassName), children: [renderTabsItemLabel(item.label, isTabSelected), _jsx(ChevronDownIcon, { size: 12, className: cn("transition-transform duration-200", open && "rotate-180") })] }), children: _jsx(PopoverMenuSection, { className: "space-y-1", children: sections.map((section) => (_jsxs("button", { type: "button", "data-slot": "popover-menu-item", className: cn("flex min-h-fit w-full cursor-pointer items-start gap-2 px-3 py-2 text-left text-sm font-normal leading-5 text-popover-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground", popoverMenuItemFocusClassName, isTabSelected &&
85
+ return (_jsx(Popover, { open: open, onOpenChange: setOpen, surface: "menu", align: "start", contentClassName: cn("min-w-[12rem]", contentClassName), trigger: _jsxs(TabsTrigger, { value: item.value, disabled: item.disabled, suppressAriaControls: suppressAriaControls, "data-state": isTabSelected ? "active" : "inactive", "data-tab-value": item.value, className: cn("flex items-center gap-1", triggerClassName), children: [renderTabsItemLabel(item.label, isTabSelected), _jsx(ChevronDownIcon, { size: 12, className: cn("transition-transform duration-200", open && "rotate-180") })] }), children: _jsx(PopoverMenuSection, { className: "space-y-1", children: sections.map((section) => (_jsxs("button", { type: "button", "data-slot": "popover-menu-item", className: cn("flex min-h-fit w-full cursor-pointer items-start gap-2 px-3 py-2 text-left text-sm font-normal leading-5 text-popover-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground", popoverMenuItemFocusClassName, isTabSelected &&
86
86
  activeSection === section.id &&
87
87
  "bg-accent text-accent-foreground hover:bg-accent hover:text-accent-foreground"), onClick: () => handleSectionClick(section.id), children: [_jsx("span", { className: "block min-w-0 flex-1 whitespace-normal break-words leading-5", children: section.label }), isTabSelected && activeSection === section.id ? (_jsx(Check, { "aria-hidden": "true", className: "mt-0.5 h-4 w-4 shrink-0" })) : null] }, section.id))) }) }));
88
88
  }
@@ -98,15 +98,15 @@ function TabWithDropdown({ value, label, sections, disabled, scrollOffset, onSec
98
98
  activeSection,
99
99
  }, triggerClassName: className, contentClassName: contentClassName }));
100
100
  }
101
- function TabTriggerItem({ item, triggerClassName }) {
101
+ function TabTriggerItem({ item, triggerClassName, suppressAriaControls }) {
102
102
  var _a;
103
103
  const tabsContext = useTabsContext();
104
104
  const isSelected = tabsContext ? tabsContext.value === item.value : false;
105
105
  const label = renderTabsItemLabel(item.label, isSelected);
106
106
  if (!item.onClose) {
107
- return (_jsx(TabsTrigger, { value: item.value, disabled: item.disabled, "data-tab-value": item.value, className: triggerClassName, children: label }));
107
+ return (_jsx(TabsTrigger, { value: item.value, disabled: item.disabled, "data-tab-value": item.value, className: triggerClassName, suppressAriaControls: suppressAriaControls, children: label }));
108
108
  }
109
- return (_jsxs("div", { className: "inline-flex min-w-max shrink-0 items-stretch whitespace-nowrap", "data-tab-value": item.value, children: [_jsx(TabsTrigger, { value: item.value, disabled: item.disabled, className: cn("shrink-0 rounded-r-none pr-1 data-[state=active]:shadow-none", triggerClassName), children: label }), _jsx("button", { type: "button", "aria-label": (_a = item.closeLabel) !== null && _a !== void 0 ? _a : "Close tab", "data-state": isSelected ? "active" : "inactive", className: cn("inline-flex min-h-8 cursor-pointer items-center justify-center rounded-r-sm bg-[hsl(var(--tab-list-background))] px-2 text-muted-foreground transition-all hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--tab-list-background))] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[hsl(var(--tab-trigger-active-background))] data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))]", item.disabled && "cursor-not-allowed opacity-50"), disabled: item.disabled, onClick: (event) => {
109
+ return (_jsxs("div", { className: "inline-flex min-w-max shrink-0 items-stretch whitespace-nowrap", "data-tab-value": item.value, children: [_jsx(TabsTrigger, { value: item.value, disabled: item.disabled, suppressAriaControls: suppressAriaControls, className: cn("shrink-0 rounded-r-none pr-1 data-[state=active]:shadow-none", triggerClassName), children: label }), _jsx("button", { type: "button", "aria-label": (_a = item.closeLabel) !== null && _a !== void 0 ? _a : "Close tab", "data-state": isSelected ? "active" : "inactive", className: cn("inline-flex min-h-8 cursor-pointer items-center justify-center rounded-r-sm bg-[hsl(var(--tab-list-background))] px-2 text-muted-foreground transition-all hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--tab-list-background))] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[hsl(var(--tab-trigger-active-background))] data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))]", item.disabled && "cursor-not-allowed opacity-50"), disabled: item.disabled, onClick: (event) => {
110
110
  var _a;
111
111
  event.stopPropagation();
112
112
  (_a = item.onClose) === null || _a === void 0 ? void 0 : _a.call(item);
@@ -144,8 +144,8 @@ function Tabs({ items, defaultValue, value, onValueChange, size = "default", ren
144
144
  if (!items.length) {
145
145
  return null;
146
146
  }
147
- return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, triggerClassName: cn(size === "compact" &&
148
- "min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", triggerClassName) }, item.value)) : (_jsx(TabTriggerItem, { item: item, triggerClassName: cn(size === "compact" &&
147
+ return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
148
+ "min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", triggerClassName) }, item.value)) : (_jsx(TabTriggerItem, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
149
149
  "min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", triggerClassName) }, item.value))) }) }), renderPanels
150
150
  ? items.map((item) => (_jsx(TabsContent, { value: item.value, className: cn("pt-4", panelClassName), children: item.content }, item.value)))
151
151
  : null] }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neasg/design-system",
3
- "version": "0.4.30",
3
+ "version": "0.4.31",
4
4
  "description": "NEA shared design system primitives, theme tokens, and Storybook docs.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",