@lessly/ui 1.1.0 → 1.2.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
@@ -2437,15 +2437,17 @@ declare function SidebarNav({ items, collapsed, basePath, LinkComponent, isItemA
2437
2437
  interface AppSidebarProps {
2438
2438
  items: NavItem[];
2439
2439
  /** Expanded-slot mark/wordmark, rendered when `header` is absent. Also the collapsed-rail
2440
- * fallback when `logoCollapsed` isn't given see `logoCollapsed`. */
2440
+ * fallback when `logoCollapsed` isn't given, on a rail that isn't `collapsible` — see
2441
+ * `logoCollapsed`. */
2441
2442
  logo?: React$1.ReactNode;
2442
- /** Collapsed-rail identity — a small mark, shown overlaid by the pin on hover/focus when
2443
- * `collapsible`. A collapsible rail should supply this (or `logo`): `header` is expanded-only
2444
- * and is never read while collapsed, so without a mark the collapsed rail shows just the pin. */
2443
+ /** Collapsed-rail identity — a small mark, for a rail that cannot be expanded from inside it.
2444
+ * A `collapsible` rail shows the pin here instead and never reads this: the 52px rail holds
2445
+ * one box, and the way back to expanded is what it holds. */
2445
2446
  logoCollapsed?: React$1.ReactNode;
2446
2447
  /** Identity slot above the rail — e.g. an <OrgProductSwitcher/> (#266). Falls back to `logo`.
2447
2448
  * Expanded-only: rendering it in the 52px collapsed rail would overflow, so the collapsed
2448
- * branch never reads it supply `logoCollapsed` (or `logo`) for that state instead. */
2449
+ * branch never reads it. What stands in depends on `collapsible` the pin when it is set,
2450
+ * `logoCollapsed ?? logo` when it is not. */
2449
2451
  header?: React$1.ReactNode;
2450
2452
  /** Account slot below the rail — e.g. a <UserMenu/>. Its divider renders only with it. */
2451
2453
  footer?: React$1.ReactNode;
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ var twMerge = extendTailwindMerge((config) => {
12
12
  { [group.replace("border-w", "border")]: TOKEN_BORDER_WIDTHS }
13
13
  ];
14
14
  }
15
+ config.conflictingClassGroups["font-size"] = [];
15
16
  return config;
16
17
  });
17
18
  function cn(...inputs) {
@@ -592,13 +593,14 @@ Label2.displayName = LabelPrimitive.Root.displayName;
592
593
  // src/components/option-card.tsx
593
594
  import * as React9 from "react";
594
595
  import { cva as cva3 } from "class-variance-authority";
596
+ import { Check as Check2 } from "lucide-react";
595
597
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
596
598
  var optionCardVariants = cva3(
597
599
  "flex w-full items-center gap-3 rounded-lg border border-border-default p-3 text-left transition-colors hover:bg-bg-elevated focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-border-focus",
598
600
  {
599
601
  variants: {
600
602
  selected: {
601
- true: "ring-2 ring-border-strong",
603
+ true: "border-border-strong",
602
604
  false: ""
603
605
  }
604
606
  },
@@ -619,7 +621,8 @@ var OptionCard = React9.forwardRef(
619
621
  /* @__PURE__ */ jsxs6("span", { className: "flex min-w-0 flex-col", children: [
620
622
  /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-text-primary", children: title }),
621
623
  description && /* @__PURE__ */ jsx9("span", { className: "truncate text-xs text-text-tertiary", children: description })
622
- ] })
624
+ ] }),
625
+ selected !== void 0 && /* @__PURE__ */ jsx9(Check2, { className: cn("ml-auto size-3.5 shrink-0 text-text-primary", !selected && "invisible") })
623
626
  ]
624
627
  }
625
628
  )
@@ -816,7 +819,7 @@ var SettingRow = React11.forwardRef(function SettingRow2({ icon: Icon, label, de
816
819
  SettingRow.displayName = "SettingRow";
817
820
 
818
821
  // src/components/switch.tsx
819
- import { Check as Check2 } from "lucide-react";
822
+ import { Check as Check3 } from "lucide-react";
820
823
  import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
821
824
  function Switch({
822
825
  checked,
@@ -850,7 +853,7 @@ function Switch({
850
853
  "span",
851
854
  {
852
855
  className: `pointer-events-none absolute inset-y-0 left-0 flex w-6 items-center justify-center transition-opacity ${checked ? "opacity-100" : "opacity-0"}`,
853
- children: /* @__PURE__ */ jsx15(Check2, { className: "size-3 text-white" })
856
+ children: /* @__PURE__ */ jsx15(Check3, { className: "size-3 text-white" })
854
857
  }
855
858
  ),
856
859
  /* @__PURE__ */ jsx15(
@@ -868,7 +871,7 @@ function Switch({
868
871
  // src/components/checkbox.tsx
869
872
  import * as React12 from "react";
870
873
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
871
- import { Check as Check3 } from "lucide-react";
874
+ import { Check as Check4 } from "lucide-react";
872
875
  import { jsx as jsx16 } from "react/jsx-runtime";
873
876
  var Checkbox = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
874
877
  CheckboxPrimitive.Root,
@@ -882,7 +885,7 @@ var Checkbox = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__
882
885
  className
883
886
  ),
884
887
  ...props,
885
- children: /* @__PURE__ */ jsx16(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: /* @__PURE__ */ jsx16(Check3, { className: "h-4 w-4" }) })
888
+ children: /* @__PURE__ */ jsx16(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: /* @__PURE__ */ jsx16(Check4, { className: "h-4 w-4" }) })
886
889
  }
887
890
  ));
888
891
  Checkbox.displayName = CheckboxPrimitive.Root.displayName;
@@ -1488,7 +1491,7 @@ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
1488
1491
  // src/components/context-menu.tsx
1489
1492
  import * as React25 from "react";
1490
1493
  import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
1491
- import { Check as Check4, ChevronRight as ChevronRight2, Circle as Circle3 } from "lucide-react";
1494
+ import { Check as Check5, ChevronRight as ChevronRight2, Circle as Circle3 } from "lucide-react";
1492
1495
  import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
1493
1496
  var ContextMenu = ContextMenuPrimitive.Root;
1494
1497
  var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
@@ -1561,7 +1564,7 @@ var ContextMenuCheckboxItem = React25.forwardRef(({ className, children, checked
1561
1564
  checked,
1562
1565
  ...props,
1563
1566
  children: [
1564
- /* @__PURE__ */ jsx29("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx29(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx29(Check4, { className: "h-4 w-4" }) }) }),
1567
+ /* @__PURE__ */ jsx29("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx29(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx29(Check5, { className: "h-4 w-4" }) }) }),
1565
1568
  children
1566
1569
  ]
1567
1570
  }
@@ -1609,7 +1612,7 @@ ContextMenuShortcut.displayName = "ContextMenuShortcut";
1609
1612
  // src/components/menubar.tsx
1610
1613
  import * as React26 from "react";
1611
1614
  import * as MenubarPrimitive from "@radix-ui/react-menubar";
1612
- import { Check as Check5, ChevronRight as ChevronRight3, Circle as Circle4 } from "lucide-react";
1615
+ import { Check as Check6, ChevronRight as ChevronRight3, Circle as Circle4 } from "lucide-react";
1613
1616
  import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
1614
1617
  var MenubarMenu = (props) => /* @__PURE__ */ jsx30(MenubarPrimitive.Menu, { ...props });
1615
1618
  MenubarMenu.displayName = "MenubarMenu";
@@ -1709,7 +1712,7 @@ var MenubarCheckboxItem = React26.forwardRef(({ className, children, checked, ..
1709
1712
  checked,
1710
1713
  ...props,
1711
1714
  children: [
1712
- /* @__PURE__ */ jsx30("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx30(MenubarPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx30(Check5, { className: "h-4 w-4" }) }) }),
1715
+ /* @__PURE__ */ jsx30("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx30(MenubarPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx30(Check6, { className: "h-4 w-4" }) }) }),
1713
1716
  children
1714
1717
  ]
1715
1718
  }
@@ -3177,7 +3180,7 @@ EmptyState.displayName = "EmptyState";
3177
3180
 
3178
3181
  // src/components/copy-button.tsx
3179
3182
  import * as React50 from "react";
3180
- import { Check as Check6, Copy } from "lucide-react";
3183
+ import { Check as Check7, Copy } from "lucide-react";
3181
3184
  import { jsx as jsx60, jsxs as jsxs34 } from "react/jsx-runtime";
3182
3185
  var MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
3183
3186
  var CopyButton = React50.forwardRef(
@@ -3213,7 +3216,7 @@ var CopyButton = React50.forwardRef(
3213
3216
  className: cn(className),
3214
3217
  ...props,
3215
3218
  "aria-label": copied ? "Copied" : masked ? `${label} ending ${tail}` : label,
3216
- icon: copied ? /* @__PURE__ */ jsx60(Check6, { className: "text-text-success" }) : /* @__PURE__ */ jsx60(Copy, {})
3219
+ icon: copied ? /* @__PURE__ */ jsx60(Check7, { className: "text-text-success" }) : /* @__PURE__ */ jsx60(Copy, {})
3217
3220
  }
3218
3221
  )
3219
3222
  );
@@ -4497,7 +4500,7 @@ RemoveButton.displayName = "RemoveButton";
4497
4500
 
4498
4501
  // src/components/grant-role-picker.tsx
4499
4502
  import * as React63 from "react";
4500
- import { Check as Check7 } from "lucide-react";
4503
+ import { Check as Check8 } from "lucide-react";
4501
4504
  import { Fragment as Fragment7, jsx as jsx76, jsxs as jsxs48 } from "react/jsx-runtime";
4502
4505
  var WEIGHT_TONE = {
4503
4506
  faint: "text-text-secondary",
@@ -4536,7 +4539,7 @@ var GrantRolePicker = React63.forwardRef(
4536
4539
  const removeWords = grantRemoveLabel(void 0, notInForce !== void 0);
4537
4540
  const valueNote = !current ? notes?.missing : rungs && !pickable.some((r) => r.id === value) ? notes?.aboveCap : void 0;
4538
4541
  const item = (r) => /* @__PURE__ */ jsxs48(DropdownMenuItem, { onSelect: () => onChange(r.id), className: "items-start gap-2 py-1.5", children: [
4539
- /* @__PURE__ */ jsx76(Check7, { className: cn("mt-0.5 size-3.5 shrink-0 text-text-primary", r.id !== value && "invisible") }),
4542
+ /* @__PURE__ */ jsx76(Check8, { className: cn("mt-0.5 size-3.5 shrink-0 text-text-primary", r.id !== value && "invisible") }),
4540
4543
  /* @__PURE__ */ jsxs48("span", { className: "flex flex-col", children: [
4541
4544
  /* @__PURE__ */ jsx76("span", { className: cn("text-sm", WEIGHT_TONE[r.weight ?? "normal"]), children: r.name }),
4542
4545
  r.hint && /* @__PURE__ */ jsx76("span", { className: "text-xs text-text-tertiary", children: r.hint })
@@ -4580,7 +4583,7 @@ var GrantRolePicker = React63.forwardRef(
4580
4583
  "aria-label": removeDetail ? grantRemoveLabel(removeDetail, notInForce !== void 0) : void 0,
4581
4584
  className: "gap-2 py-1.5",
4582
4585
  children: [
4583
- rungs && /* @__PURE__ */ jsx76(Check7, { className: "invisible size-3.5 shrink-0" }),
4586
+ rungs && /* @__PURE__ */ jsx76(Check8, { className: "invisible size-3.5 shrink-0" }),
4584
4587
  removeWords
4585
4588
  ]
4586
4589
  }
@@ -5028,28 +5031,10 @@ function AppSidebar({
5028
5031
  className
5029
5032
  ),
5030
5033
  children: [
5031
- /* @__PURE__ */ jsx83("div", { className: cn("flex h-14 items-center gap-2", collapsed ? "justify-center px-1" : "px-3"), children: collapsed ? collapsible ? logoCollapsed ?? logo ? (
5032
- /* The collapsed rail (52px) can't fit the logo mark beside the pin side by side —
5033
- so the pin overlays the mark instead, revealed on hover/focus, same as pre-flat-rail. */
5034
- /* @__PURE__ */ jsxs54("div", { className: "group relative flex size-8 items-center justify-center", children: [
5035
- /* @__PURE__ */ jsx83("span", { className: "pointer-events-none transition-opacity group-hover:opacity-0 group-focus-within:opacity-0", children: logoCollapsed ?? logo }),
5036
- /* @__PURE__ */ jsx83(
5037
- "button",
5038
- {
5039
- type: "button",
5040
- onClick: toggle,
5041
- "aria-label": "Expand sidebar",
5042
- "aria-expanded": false,
5043
- className: "absolute inset-0 flex items-center justify-center rounded-md text-text-secondary opacity-0 transition-opacity hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-border-focus group-hover:opacity-100 group-focus-within:opacity-100",
5044
- children: /* @__PURE__ */ jsx83(PanelLeft, { className: "size-4", "aria-hidden": "true" })
5045
- }
5046
- )
5047
- ] })
5048
- ) : (
5049
- /* No mark to hide behind (no `logoCollapsed`/`logo` given — `header` doesn't
5050
- count, it's expanded-only). Hover-revealing the pin over nothing would leave
5051
- an invisible 32px box as the only way back to expanded, so render it plain
5052
- and fully visible instead. */
5034
+ /* @__PURE__ */ jsx83("div", { className: cn("flex h-14 items-center gap-2", collapsed ? "justify-center px-1" : "px-3"), children: collapsed ? collapsible ? (
5035
+ /* The 52px rail holds one 32px box, and the way back to expanded is what it holds.
5036
+ The logo has the expanded band and the top bar; the pin has nowhere else, and a
5037
+ pin hidden behind the mark is no pin at all on a device that cannot hover. */
5053
5038
  /* @__PURE__ */ jsx83(
5054
5039
  "button",
5055
5040
  {
@@ -5110,7 +5095,7 @@ var SidebarProductHeader = React69.forwardRef(
5110
5095
  SidebarProductHeader.displayName = "SidebarProductHeader";
5111
5096
 
5112
5097
  // src/components/org-product-switcher.tsx
5113
- import { ChevronsUpDown as ChevronsUpDown3, Check as Check8 } from "lucide-react";
5098
+ import { ChevronsUpDown as ChevronsUpDown3, Check as Check9 } from "lucide-react";
5114
5099
  import { Fragment as Fragment11, jsx as jsx85, jsxs as jsxs56 } from "react/jsx-runtime";
5115
5100
  var triggerBox = "flex w-full items-center gap-2.5 rounded-xl px-1.5 py-1 text-left transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus";
5116
5101
  var menuItem = "gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-text-secondary focus:bg-[var(--menu-hov)] focus:text-text-primary";
@@ -5189,7 +5174,7 @@ function OrgProductSwitcher({
5189
5174
  organizations.map((o) => /* @__PURE__ */ jsxs56(DropdownMenuItem, { className: menuItem, onSelect: () => onOrgSelect(o.id), children: [
5190
5175
  /* @__PURE__ */ jsx85(Mark2, { item: o, size: "sm" }),
5191
5176
  /* @__PURE__ */ jsx85(ItemLabel, { item: o, kind: "organization" }),
5192
- o.id === activeOrgId && /* @__PURE__ */ jsx85(Check8, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
5177
+ o.id === activeOrgId && /* @__PURE__ */ jsx85(Check9, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
5193
5178
  ] }, o.id)),
5194
5179
  products.length > 0 && /* @__PURE__ */ jsxs56(Fragment11, { children: [
5195
5180
  /* @__PURE__ */ jsx85(DropdownMenuSeparator, { className: "mx-0 shrink-0 bg-border-subtle" }),
@@ -5197,7 +5182,7 @@ function OrgProductSwitcher({
5197
5182
  products.map((p) => /* @__PURE__ */ jsxs56(DropdownMenuItem, { className: menuItem, onSelect: () => onProductSelect?.(p.id), children: [
5198
5183
  /* @__PURE__ */ jsx85(Mark2, { item: p, size: "sm" }),
5199
5184
  /* @__PURE__ */ jsx85(ItemLabel, { item: p, kind: "product" }),
5200
- p.id === activeProductId && /* @__PURE__ */ jsx85(Check8, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
5185
+ p.id === activeProductId && /* @__PURE__ */ jsx85(Check9, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
5201
5186
  ] }, p.id))
5202
5187
  ] }),
5203
5188
  actions && actions.length > 0 && /* @__PURE__ */ jsxs56(Fragment11, { children: [
@@ -6173,21 +6158,23 @@ import { BellRing, Settings } from "lucide-react";
6173
6158
  import * as React79 from "react";
6174
6159
 
6175
6160
  // src/components/notification-parts.tsx
6176
- import { Check as Check9 } from "lucide-react";
6161
+ import { Check as Check10 } from "lucide-react";
6177
6162
  import { jsx as jsx96 } from "react/jsx-runtime";
6178
6163
  var rowControlHitArea = "relative after:absolute after:-inset-x-2 after:-top-1.5 after:-bottom-2.5";
6179
6164
  function rowControlName(label, title) {
6180
6165
  return `${label} "${title}"`;
6181
6166
  }
6182
6167
  function MarkReadButton({ title, onClick }) {
6168
+ const label = `Mark "${title}" as read`;
6183
6169
  return /* @__PURE__ */ jsx96(
6184
- "button",
6170
+ Button,
6185
6171
  {
6186
- type: "button",
6187
- "aria-label": `Mark "${title}" as read`,
6172
+ variant: "ghost",
6173
+ size: "xs",
6174
+ icon: /* @__PURE__ */ jsx96(Check10, {}),
6175
+ "aria-label": label,
6188
6176
  onClick,
6189
- className: "relative flex size-5 shrink-0 items-center justify-center rounded-md text-text-tertiary opacity-0 transition-opacity after:absolute after:-inset-3 hover:text-text-primary focus-visible:opacity-100 group-hover:opacity-100",
6190
- children: /* @__PURE__ */ jsx96(Check9, { className: "size-3.5", "aria-hidden": "true" })
6177
+ className: "relative text-text-secondary after:absolute after:-inset-3 hover:text-text-primary"
6191
6178
  }
6192
6179
  );
6193
6180
  }
@@ -6399,7 +6386,7 @@ NotificationBell.displayName = "NotificationBell";
6399
6386
 
6400
6387
  // src/components/notification-center.tsx
6401
6388
  import * as React81 from "react";
6402
- import { Check as Check10, Search as Search2 } from "lucide-react";
6389
+ import { Check as Check11, Search as Search2 } from "lucide-react";
6403
6390
  import { jsx as jsx99, jsxs as jsxs66 } from "react/jsx-runtime";
6404
6391
  var chipBase = "rounded-lg px-3 py-1.5 text-sm font-medium transition-colors";
6405
6392
  var chipOn = "bg-bg-brand-subtle text-text-brand";
@@ -6446,7 +6433,7 @@ function CenterRow({
6446
6433
  item.body && /* @__PURE__ */ jsx99("p", { className: "mt-0.5 text-sm leading-snug text-text-secondary", children: item.body }),
6447
6434
  (item.receipt || item.deepLink) && /* @__PURE__ */ jsxs66("div", { className: "mt-2 flex flex-wrap items-center gap-x-4 gap-y-1.5", children: [
6448
6435
  item.receipt && /* @__PURE__ */ jsxs66("span", { className: "inline-flex items-center gap-1.5 text-sm text-text-tertiary", children: [
6449
- /* @__PURE__ */ jsx99(Check10, { className: "size-3 shrink-0 text-text-success", "aria-hidden": "true" }),
6436
+ /* @__PURE__ */ jsx99(Check11, { className: "size-3 shrink-0 text-text-success", "aria-hidden": "true" }),
6450
6437
  item.receipt
6451
6438
  ] }),
6452
6439
  item.deepLink && /* @__PURE__ */ jsx99(
@@ -7677,7 +7664,7 @@ ListCells.displayName = "ListCells";
7677
7664
 
7678
7665
  // src/components/theme-picker.tsx
7679
7666
  import * as React87 from "react";
7680
- import { Check as Check11, Monitor as Monitor2 } from "lucide-react";
7667
+ import { Check as Check12, Monitor as Monitor2 } from "lucide-react";
7681
7668
  import { jsx as jsx105, jsxs as jsxs71 } from "react/jsx-runtime";
7682
7669
  var THEME_SWATCHES = {
7683
7670
  // --bg-surface --bg-sunken --bg-overlay --border-default --text-tertiary
@@ -7753,7 +7740,7 @@ var Picker = React87.forwardRef(function Picker2({ value, onValueChange, classNa
7753
7740
  selected ? "font-semibold text-text-primary" : "text-text-secondary"
7754
7741
  ),
7755
7742
  children: [
7756
- /* @__PURE__ */ jsx105(Check11, { className: cn("size-4 shrink-0", !selected && "invisible"), "aria-hidden": true }),
7743
+ /* @__PURE__ */ jsx105(Check12, { className: cn("size-4 shrink-0", !selected && "invisible"), "aria-hidden": true }),
7757
7744
  o.label
7758
7745
  ]
7759
7746
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lessly/ui",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Lessly design system — shared UI primitives, tokens, and theme",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",
@@ -37,7 +37,7 @@
37
37
  "storybook": "storybook dev -p 6006 --no-open",
38
38
  "build-storybook": "storybook build",
39
39
  "changeset": "changeset",
40
- "release:version": "changeset version && node scripts/stamp-changelog-date.mjs",
40
+ "release:version": "changeset version && node scripts/stamp-changelog-date.mjs && pnpm gen-changelog",
41
41
  "release:publish": "node scripts/release-publish.mjs",
42
42
  "release:tag": "changeset tag",
43
43
  "dev-site": "vite --config site/vite.config.ts",