@assure-one/design-system 0.8.0 → 0.9.0

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/index.d.ts CHANGED
@@ -151,7 +151,10 @@ declare const BreadcrumbSeparator: React$1.ForwardRefExoticComponent<BreadcrumbS
151
151
  * - accent → bg-accent (cyan CTA)
152
152
  * - dashed → full-bleed "+ Add another" CTA, transparent fill + dashed border
153
153
  *
154
- * Sizes match shadcn convention; default `md` is 8px/14px padding.
154
+ * Control text scale (shared across the button-family control primitives
155
+ * Button / MultiFilterPill / FilterChip): sm = 13px, md = 14px, lg = 16px.
156
+ * `sm` is the dense tier used in toolbars; `md` is the default. (SearchInput
157
+ * keeps its own one-step-denser inputSize scale, 12/13/14.)
155
158
  * Use `asChild` to render as a different element (e.g. an anchor / next/link).
156
159
  */
157
160
  declare const buttonVariants: (props?: ({
@@ -815,8 +818,15 @@ interface MultiFilterPillProps {
815
818
  }[];
816
819
  onToggle: (key: string) => void;
817
820
  onClear: () => void;
821
+ /**
822
+ * Control size shared with Button / FilterChip: sm = h-8 / 13px, md = h-9 /
823
+ * 14px, lg = h-10 / 16px. Defaults to the dense `sm` tier since filter pills
824
+ * are toolbar controls — a pill then sits at the same 32px height and 13px
825
+ * text as a Button sm / FilterChip sm in the same row.
826
+ */
827
+ size?: "sm" | "md" | "lg";
818
828
  }
819
- declare function MultiFilterPill({ label, icon, selected, options, onToggle, onClear, }: MultiFilterPillProps): react_jsx_runtime.JSX.Element;
829
+ declare function MultiFilterPill({ label, icon, selected, options, onToggle, onClear, size, }: MultiFilterPillProps): react_jsx_runtime.JSX.Element;
820
830
  declare namespace MultiFilterPill {
821
831
  var displayName: string;
822
832
  }
@@ -2100,20 +2110,31 @@ declare const NotificationFilter: React$1.ForwardRefExoticComponent<Notification
2100
2110
  type NotificationListProps = React.HTMLAttributes<HTMLDivElement>;
2101
2111
  declare const NotificationList: React$1.ForwardRefExoticComponent<NotificationListProps & React$1.RefAttributes<HTMLDivElement>>;
2102
2112
  interface NotificationItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "title"> {
2113
+ /**
2114
+ * Primary headline — one scannable line (feed the human sentence here, e.g.
2115
+ * "Sara uploaded W-2.pdf", not a generic type label). Clamps to 2 lines,
2116
+ * then ellipsis.
2117
+ */
2103
2118
  title: React.ReactNode;
2119
+ /** Muted secondary line (a message snippet, etc.). Single line, truncates. */
2104
2120
  body?: React.ReactNode;
2105
- /** Small caption, joined with `client` and `time` on the meta line. */
2121
+ /** Quiet caption shown on the meta line only when there is no `body`. */
2106
2122
  typeLabel?: React.ReactNode;
2107
2123
  client?: React.ReactNode;
2108
- /** Preformatted relative time, e.g. "5m". */
2124
+ /** Preformatted relative time, e.g. "5m". Top-right, baseline with `title`. */
2109
2125
  time?: React.ReactNode;
2110
2126
  /** People-driven rows: shows the sender avatar instead of the icon tile. */
2111
2127
  sender?: {
2112
2128
  name: string;
2113
2129
  src?: string | null;
2114
2130
  };
2115
- /** System rows: icon rendered inside a neutral tile. Ignored when `sender` is set. */
2131
+ /** System rows: icon rendered inside a tile. Ignored when `sender` is set. */
2116
2132
  icon?: React.ReactNode;
2133
+ /**
2134
+ * Tint the icon tile per type, e.g. "bg-amber-bg text-amber". The consumer
2135
+ * owns the type-to-colour map. Defaults to a neutral tile.
2136
+ */
2137
+ iconClassName?: string;
2117
2138
  unread?: boolean;
2118
2139
  }
2119
2140
  declare const NotificationItem: React$1.ForwardRefExoticComponent<NotificationItemProps & React$1.RefAttributes<HTMLButtonElement>>;
@@ -2127,6 +2148,7 @@ type ToolbarProps = React.HTMLAttributes<HTMLDivElement>;
2127
2148
  declare const Toolbar: React$1.ForwardRefExoticComponent<ToolbarProps & React$1.RefAttributes<HTMLDivElement>>;
2128
2149
  declare const filterChipVariants: (props?: ({
2129
2150
  active?: boolean | null | undefined;
2151
+ size?: "sm" | "md" | "lg" | null | undefined;
2130
2152
  } & class_variance_authority_types.ClassProp) | undefined) => string;
2131
2153
  interface FilterChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof VariantProps<typeof filterChipVariants>>, VariantProps<typeof filterChipVariants> {
2132
2154
  count?: number;
package/dist/index.js CHANGED
@@ -2695,7 +2695,7 @@ var buttonVariants = cva(
2695
2695
  dashed: "border-2 border-dashed border-rule bg-transparent text-fg-3 hover:border-fg-4 hover:bg-bg-2 hover:text-fg"
2696
2696
  },
2697
2697
  size: {
2698
- sm: "h-8 px-3 text-sm gap-1.5",
2698
+ sm: "h-8 px-3 text-[13px] gap-1.5",
2699
2699
  md: "h-10 px-4 text-sm gap-2",
2700
2700
  lg: "h-12 px-6 text-base gap-2",
2701
2701
  // Icon-only sizes. Hit target ≥ 24px (WCAG 2.5.5 floor).
@@ -3624,20 +3624,27 @@ var ContextMenuSubTrigger = React36.forwardRef(({ className, inset, children, ..
3624
3624
  }
3625
3625
  ));
3626
3626
  ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
3627
- var ContextMenuSubContent = React36.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3628
- ContextMenuPrimitive.SubContent,
3629
- {
3630
- ref,
3631
- className: cn(
3632
- "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
3633
- "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
3634
- "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
3635
- "data-[state=open]:scale-100 data-[state=open]:opacity-100",
3636
- "motion-reduce:transition-none",
3637
- className
3638
- ),
3639
- ...props
3640
- }
3627
+ var ContextMenuSubContent = React36.forwardRef(({ className, ...props }, ref) => (
3628
+ // Portal the sub-content to the body. The parent Content keeps a persistent
3629
+ // `scale-100` transform (its open-state animation), which makes it the
3630
+ // containing block for `position: fixed` descendants — and its
3631
+ // `overflow-hidden` would then clip this Popper-positioned flyout to nothing.
3632
+ // Portaling escapes both the transformed ancestor and the clip.
3633
+ /* @__PURE__ */ jsx(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
3634
+ ContextMenuPrimitive.SubContent,
3635
+ {
3636
+ ref,
3637
+ className: cn(
3638
+ "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
3639
+ "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
3640
+ "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
3641
+ "data-[state=open]:scale-100 data-[state=open]:opacity-100",
3642
+ "motion-reduce:transition-none",
3643
+ className
3644
+ ),
3645
+ ...props
3646
+ }
3647
+ ) })
3641
3648
  ));
3642
3649
  ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
3643
3650
  var ContextMenuContent = React36.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
@@ -4049,20 +4056,27 @@ var DropdownMenuSubTrigger = React36.forwardRef(({ className, inset, children, .
4049
4056
  }
4050
4057
  ));
4051
4058
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
4052
- var DropdownMenuSubContent = React36.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4053
- DropdownMenuPrimitive.SubContent,
4054
- {
4055
- ref,
4056
- className: cn(
4057
- "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
4058
- "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
4059
- "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
4060
- "data-[state=open]:scale-100 data-[state=open]:opacity-100",
4061
- "motion-reduce:transition-none",
4062
- className
4063
- ),
4064
- ...props
4065
- }
4059
+ var DropdownMenuSubContent = React36.forwardRef(({ className, ...props }, ref) => (
4060
+ // Portal the sub-content to the body. The parent Content keeps a persistent
4061
+ // `scale-100` transform (its open-state animation), which makes it the
4062
+ // containing block for `position: fixed` descendants — and its
4063
+ // `overflow-hidden` would then clip this Popper-positioned flyout to nothing.
4064
+ // Portaling escapes both the transformed ancestor and the clip.
4065
+ /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
4066
+ DropdownMenuPrimitive.SubContent,
4067
+ {
4068
+ ref,
4069
+ className: cn(
4070
+ "rounded-card border-rule bg-surface text-fg shadow-pop z-[var(--z-dropdown)] min-w-[8rem] overflow-hidden border p-1",
4071
+ "transition-[opacity,transform] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
4072
+ "data-[state=closed]:scale-95 data-[state=closed]:opacity-0",
4073
+ "data-[state=open]:scale-100 data-[state=open]:opacity-100",
4074
+ "motion-reduce:transition-none",
4075
+ className
4076
+ ),
4077
+ ...props
4078
+ }
4079
+ ) })
4066
4080
  ));
4067
4081
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
4068
4082
  var DropdownMenuContent = React36.forwardRef(({ className, sideOffset = 6, align = "start", ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
@@ -4730,13 +4744,19 @@ function Logo({
4730
4744
  }
4731
4745
  );
4732
4746
  }
4747
+ var TRIGGER_SIZE = {
4748
+ sm: "h-8 gap-1.5 px-2.5 text-[13px]",
4749
+ md: "h-9 gap-2 px-3 text-sm",
4750
+ lg: "h-10 gap-2 px-3.5 text-base"
4751
+ };
4733
4752
  function MultiFilterPill({
4734
4753
  label,
4735
4754
  icon,
4736
4755
  selected,
4737
4756
  options,
4738
4757
  onToggle,
4739
- onClear
4758
+ onClear,
4759
+ size = "sm"
4740
4760
  }) {
4741
4761
  const active = selected.size > 0;
4742
4762
  const displayLabel = active ? selected.size === 1 ? options.find((o) => o.key === [...selected][0])?.label ?? label : `${label} \xB7 ${selected.size}` : label;
@@ -4745,7 +4765,8 @@ function MultiFilterPill({
4745
4765
  PopoverTrigger,
4746
4766
  {
4747
4767
  className: cn(
4748
- "rounded-pill font-body inline-flex items-center gap-1.5 border px-2.5 py-1 text-xs font-medium",
4768
+ "rounded-pill font-body inline-flex items-center border font-medium",
4769
+ TRIGGER_SIZE[size],
4749
4770
  "transition-[color,background-color,border-color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
4750
4771
  "motion-reduce:transition-none",
4751
4772
  "focus-visible:[box-shadow:var(--shadow-focus-ring)] focus-visible:outline-none",
@@ -5460,7 +5481,10 @@ var searchInputVariants = cva(
5460
5481
  {
5461
5482
  variants: {
5462
5483
  inputSize: {
5463
- sm: "h-8 pl-8 pr-8 text-xs",
5484
+ // `sm` is the dense control tier: h-8 + 13px, so a search box lines up
5485
+ // pixel-for-pixel (height AND text) with Button / MultiFilterPill /
5486
+ // FilterChip at their `sm` tier in a toolbar row.
5487
+ sm: "h-8 pl-8 pr-8 text-[13px]",
5464
5488
  md: "h-9 pl-9 pr-9 text-[13px]",
5465
5489
  lg: "h-11 pl-10 pr-10 text-sm"
5466
5490
  }
@@ -8757,16 +8781,16 @@ var NotificationFilter = forwardRef(
8757
8781
  ),
8758
8782
  ...props,
8759
8783
  children: [
8760
- /* @__PURE__ */ jsx("div", { className: "bg-bg-2 inline-flex rounded-md p-0.5 text-xs font-medium", children: FILTER_OPTIONS.map((option) => /* @__PURE__ */ jsx(
8784
+ /* @__PURE__ */ jsx("div", { className: "bg-bg-2 inline-flex rounded-lg p-0.5 text-xs font-medium", children: FILTER_OPTIONS.map((option) => /* @__PURE__ */ jsx(
8761
8785
  "button",
8762
8786
  {
8763
8787
  type: "button",
8764
8788
  onClick: () => onValueChange(option),
8765
8789
  "aria-pressed": value === option,
8766
8790
  className: cn(
8767
- "rounded-[6px] px-2.5 py-1 capitalize transition-colors",
8791
+ "rounded-md px-2.5 py-1 capitalize transition-colors",
8768
8792
  "focus-visible:ring-accent outline-none focus-visible:ring-2",
8769
- value === option ? "bg-surface text-fg shadow-quiet" : "text-fg-3 hover:text-fg"
8793
+ value === option ? "bg-surface text-fg shadow-quiet ring-rule-soft ring-1" : "text-fg-3 hover:text-fg"
8770
8794
  ),
8771
8795
  children: option
8772
8796
  },
@@ -8794,45 +8818,51 @@ var NotificationList = forwardRef(
8794
8818
  );
8795
8819
  NotificationList.displayName = "NotificationList";
8796
8820
  var NotificationItem = forwardRef(
8797
- function NotificationItem2({ title, body, typeLabel, client, time, sender, icon, unread, className, ...props }, ref) {
8798
- const meta = [typeLabel, client, time].filter(Boolean);
8821
+ function NotificationItem2({ title, body, typeLabel, client, time, sender, icon, iconClassName, unread, className, ...props }, ref) {
8822
+ const meta = body ? [] : [typeLabel, client].filter(Boolean);
8799
8823
  return /* @__PURE__ */ jsxs(
8800
8824
  "button",
8801
8825
  {
8802
8826
  ref,
8803
8827
  type: "button",
8804
8828
  className: cn(
8805
- "flex w-full gap-3 px-4 py-3 text-left outline-none",
8829
+ "flex w-full gap-3 px-4 py-2.5 text-left outline-none",
8806
8830
  "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)] motion-reduce:transition-none",
8807
- "hover:bg-bg-2/60 focus-visible:bg-bg-2/60",
8808
- unread && "bg-accent/[0.06]",
8831
+ unread ? "bg-pro-bg hover:bg-pro-bg-hover focus-visible:bg-pro-bg-hover" : "hover:bg-bg-2/60 focus-visible:bg-bg-2/60",
8809
8832
  className
8810
8833
  ),
8811
8834
  ...props,
8812
8835
  children: [
8836
+ /* @__PURE__ */ jsx("span", { className: "flex w-1.5 shrink-0 justify-center", "aria-hidden": "true", children: unread && /* @__PURE__ */ jsx("span", { className: "bg-pro-fg mt-[13px] size-1.5 rounded-full" }) }),
8813
8837
  sender ? /* @__PURE__ */ jsx(Avatar, { size: "sm", name: sender.name, src: sender.src, className: "mt-0.5" }) : /* @__PURE__ */ jsx(
8814
8838
  "div",
8815
8839
  {
8816
8840
  "aria-hidden": "true",
8817
- className: "bg-bg-2 text-fg-3 mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full [&_svg]:size-3.5",
8841
+ className: cn(
8842
+ "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-lg [&_svg]:size-3.5",
8843
+ iconClassName ?? "bg-bg-2 text-fg-3"
8844
+ ),
8818
8845
  children: icon
8819
8846
  }
8820
8847
  ),
8821
8848
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
8822
8849
  unread && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Unread. " }),
8823
- /* @__PURE__ */ jsx("p", { className: cn("text-fg text-sm leading-snug", unread ? "font-semibold" : "font-medium"), children: title }),
8824
- body && /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 truncate text-xs", children: body }),
8825
- meta.length > 0 && /* @__PURE__ */ jsx("div", { className: "text-fg-4 mt-1 flex flex-wrap items-center gap-1.5 text-[11px]", children: meta.map((part, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
8826
- i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
8850
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
8827
8851
  /* @__PURE__ */ jsx(
8828
- "span",
8852
+ "p",
8829
8853
  {
8830
8854
  className: cn(
8831
- i === 0 && typeLabel ? "font-medium tracking-wide uppercase" : "tabular-nums"
8855
+ "line-clamp-2 min-w-0 flex-1 text-[13.5px] leading-snug font-medium",
8856
+ unread ? "text-fg" : "text-fg-2"
8832
8857
  ),
8833
- children: part
8858
+ children: title
8834
8859
  }
8835
- )
8860
+ ),
8861
+ time && /* @__PURE__ */ jsx("span", { className: "text-fg-4 shrink-0 text-xs whitespace-nowrap tabular-nums", children: time })
8862
+ ] }),
8863
+ body ? /* @__PURE__ */ jsx("p", { className: "text-fg-3 mt-0.5 truncate text-xs", children: body }) : meta.length > 0 && /* @__PURE__ */ jsx("p", { className: "text-fg-4 mt-0.5 truncate text-[11.5px]", children: meta.map((part, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
8864
+ i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " \xB7 " }),
8865
+ part
8836
8866
  ] }, i)) })
8837
8867
  ] })
8838
8868
  ]
@@ -8847,7 +8877,7 @@ var Toolbar = forwardRef(function Toolbar2({ className, children, ...props }, re
8847
8877
  Toolbar.displayName = "Toolbar";
8848
8878
  var filterChipVariants = cva(
8849
8879
  cn(
8850
- "inline-flex items-center gap-1.5 h-8 px-3 rounded-pill text-xs font-medium border",
8880
+ "inline-flex items-center gap-1.5 rounded-pill font-medium border",
8851
8881
  "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out-quart)]",
8852
8882
  "motion-reduce:transition-none",
8853
8883
  "focus-visible:outline-none focus-visible:[box-shadow:var(--shadow-focus-ring)]",
@@ -8858,21 +8888,29 @@ var filterChipVariants = cva(
8858
8888
  active: {
8859
8889
  true: "bg-pro-bg text-pro-fg border-pro-fg/30 hover:bg-pro-bg-hover",
8860
8890
  false: "bg-bg-2 text-fg-2 border-rule hover:bg-bg-3"
8891
+ },
8892
+ // Control text scale shared with Button / MultiFilterPill: sm = 13px,
8893
+ // md = 14px, lg = 16px. Defaults to the dense `sm` tier (toolbar control).
8894
+ size: {
8895
+ sm: "h-8 px-3 text-[13px]",
8896
+ md: "h-9 px-3.5 text-sm",
8897
+ lg: "h-10 px-4 text-base"
8861
8898
  }
8862
8899
  },
8863
8900
  defaultVariants: {
8864
- active: false
8901
+ active: false,
8902
+ size: "sm"
8865
8903
  }
8866
8904
  }
8867
8905
  );
8868
- var FilterChip = forwardRef(function FilterChip2({ active = false, count, className, children, type, ...props }, ref) {
8906
+ var FilterChip = forwardRef(function FilterChip2({ active = false, size, count, className, children, type, ...props }, ref) {
8869
8907
  return /* @__PURE__ */ jsxs(
8870
8908
  "button",
8871
8909
  {
8872
8910
  ref,
8873
8911
  type: type ?? "button",
8874
8912
  "aria-pressed": active ?? false,
8875
- className: cn(filterChipVariants({ active }), className),
8913
+ className: cn(filterChipVariants({ active, size }), className),
8876
8914
  ...props,
8877
8915
  children: [
8878
8916
  children,