@xenide-io/the-old-ui-theme 0.5.2 → 0.5.4

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.
Files changed (59) hide show
  1. package/README.md +47 -34
  2. package/dist/{index-Od4pIP4F.d.mts → Chip-C5hRFAhe.d.mts} +10 -606
  3. package/dist/{index-Od4pIP4F.d.ts → Chip-C5hRFAhe.d.ts} +10 -606
  4. package/dist/{chunk-G53YLHVE.mjs → chunk-E5ZBQYEX.mjs} +59 -9
  5. package/dist/{chunk-RZXHZWUB.mjs → chunk-SBBKXV35.mjs} +174 -222
  6. package/dist/index.d.mts +4 -80
  7. package/dist/index.d.ts +4 -80
  8. package/dist/index.js +562 -3746
  9. package/dist/index.mjs +3 -765
  10. package/dist/suite.d.mts +56 -25
  11. package/dist/suite.d.ts +56 -25
  12. package/dist/suite.js +248 -107
  13. package/dist/suite.mjs +217 -105
  14. package/dist/ui.d.mts +608 -2
  15. package/dist/ui.d.ts +608 -2
  16. package/dist/ui.js +232 -230
  17. package/dist/ui.mjs +2 -2
  18. package/package.json +2 -6
  19. package/scripts/install-theme-dev.sh +60 -0
  20. package/scripts/sync-posthog-icons.mjs +75 -0
  21. package/src/app/globals.css +1 -0
  22. package/src/components/ui/Chip.tsx +36 -18
  23. package/src/components/ui/CommandPalette.test.tsx +41 -0
  24. package/src/components/ui/CommandPalette.tsx +58 -9
  25. package/src/components/ui/DropdownMenu.tsx +50 -11
  26. package/src/components/ui/SegmentedControl.tsx +2 -1
  27. package/src/components/ui/SettingsLayout.tsx +19 -5
  28. package/src/components/ui/ThemeSwitcher.tsx +12 -3
  29. package/src/components/ui/interaction-primitives.test.tsx +52 -0
  30. package/src/styles/suite-skin.css +53 -1
  31. package/src/styles/themes.css +445 -1656
  32. package/src/suite/components/app-switcher.tsx +32 -25
  33. package/src/suite/components/command-palette-host.tsx +20 -8
  34. package/src/suite/components/suite-app-layout.tsx +31 -10
  35. package/src/suite/components/suite-bottom-nav.tsx +23 -18
  36. package/src/suite/components/suite-layout.test.tsx +44 -0
  37. package/src/suite/components/suite-layout.tsx +3 -3
  38. package/src/suite/components/suite-mobile-drawer.tsx +12 -0
  39. package/src/suite/components/suite-mobile-header.tsx +15 -9
  40. package/src/suite/components/suite-notification-bell.tsx +23 -11
  41. package/src/suite/components/suite-settings-mobile-nav.tsx +2 -0
  42. package/src/suite/components/suite-sidebar.tsx +54 -43
  43. package/src/suite/components/suite-user-menu.tsx +54 -26
  44. package/src/suite/components/today-page-frame.tsx +1 -1
  45. package/src/suite/icons/app-accents.ts +38 -43
  46. package/src/suite/icons/glyph-parts.tsx +16 -9
  47. package/src/suite/icons/glyphs.ts +130 -99
  48. package/src/suite/lib/apps.ts +1 -1
  49. package/src/suite/lib/injected.ts +12 -11
  50. package/src/suite/lib/use-sidebar-width.ts +23 -8
  51. package/src/components/charts/index.ts +0 -9
  52. package/src/components/charts/quill/BarChart.tsx +0 -85
  53. package/src/components/charts/quill/FunnelChart.tsx +0 -49
  54. package/src/components/charts/quill/InsightShell.tsx +0 -27
  55. package/src/components/charts/quill/MetricCard.tsx +0 -44
  56. package/src/components/charts/quill/PieChart.tsx +0 -81
  57. package/src/components/charts/quill/Sparkline.tsx +0 -57
  58. package/src/components/charts/quill/TimeSeriesLineChart.tsx +0 -62
  59. package/src/components/charts/quill/index.ts +0 -9
package/dist/suite.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  DropdownItem,
3
3
  DropdownMenu,
4
4
  Tooltip
5
- } from "./chunk-G53YLHVE.mjs";
5
+ } from "./chunk-E5ZBQYEX.mjs";
6
6
  import {
7
7
  SuiteThemeProvider,
8
8
  useSuiteTheme
@@ -99,10 +99,10 @@ var APP_ACCENTS = {
99
99
  },
100
100
  nakama: {
101
101
  label: "Nakama",
102
- accent: "#0891b2",
103
- tile: "#155e75",
104
- onTile: "#ffffff",
105
- onTileAccent: "#a5f3fc"
102
+ accent: "#b8eb44",
103
+ tile: "#17101f",
104
+ onTile: "#fff2e2",
105
+ onTileAccent: "#f54b87"
106
106
  }
107
107
  };
108
108
  var APP_GLYPHS = {
@@ -111,7 +111,7 @@ var APP_GLYPHS = {
111
111
  kraken: "squid-doc",
112
112
  shellstack: "stack-hex",
113
113
  crew: "crew-bot",
114
- nakama: "crew-bot"
114
+ nakama: "nakama-fist"
115
115
  };
116
116
 
117
117
  // src/suite/icons/glyph-parts.tsx
@@ -121,7 +121,15 @@ function GlyphElement({ element }) {
121
121
  const stroke = element.filled ? "none" : void 0;
122
122
  switch (element.kind) {
123
123
  case "path":
124
- return /* @__PURE__ */ jsx2("path", { d: element.d, fill, stroke });
124
+ return /* @__PURE__ */ jsx2(
125
+ "path",
126
+ {
127
+ d: element.d,
128
+ fill,
129
+ stroke,
130
+ transform: element.transform
131
+ }
132
+ );
125
133
  case "circle":
126
134
  return /* @__PURE__ */ jsx2(
127
135
  "circle",
@@ -226,6 +234,24 @@ var SUITE_GLYPHS = {
226
234
  { kind: "path", d: "M9.6 14.6q2.4 1.7 4.8 0", accent: true }
227
235
  ]
228
236
  },
237
+ "nakama-fist": {
238
+ description: "Nakama \u2014 raised fist with neon crew signal lines",
239
+ elements: [
240
+ {
241
+ kind: "path",
242
+ d: "M192 0c17.7 0 32 14.3 32 32v112h-64V32c0-17.7 14.3-32 32-32zM64 64c0-17.7-32-32 32-32s32 14.3 32 32v80H64V64zm192 0c0-17.7 14.3-32 32-32s32 14.3 32 32v96c0 17.7-14.3 32-32 32s-32-14.3-32-32V64zm96 64c0-17.7 14.3-32 32-32s32 14.3 32 32v64c0 17.7-14.3 32-32 32s-32-14.3-32-32v-64zm-96 88v-.6c9.4 5.4 20.3 8.6 32 8.6 13.2 0 25.4-4 35.6-10.8 8.7 24.9 32.5 42.8 60.4 42.8 11.7 0 22.6-3.1 32-8.6v8.6c0 52.3-25.1 98.8-64 128v96c0 17.7-14.3 32-32 32H160c-17.7 0-32-14.3-32-32v-78.4c-17.3-7.9-33.2-18.8-46.9-32.5L69.5 357.5C45.5 333.5 32 300.9 32 267v-27c0-35.3 28.7-64 64-64h88c22.1 0 40 17.9 40 40s-17.9 40-40 40h-56c-8.8 0-16 7.2-16 16s7.2 16 16 16h56c39.8 0 72-32.2 72-72z",
243
+ filled: true,
244
+ transform: "translate(2.5 1.75) scale(.0425 .0375)"
245
+ },
246
+ { kind: "path", d: "M7 18h3.5M12.2 18h3M8.5 19.5h6", accent: true },
247
+ {
248
+ kind: "path",
249
+ d: "M4.8 5.8h2.7M4.8 7.4h1.4M18.5 17.1h1.7",
250
+ accent: true
251
+ },
252
+ { kind: "circle", cx: 18.5, cy: 4.5, r: 0.8, accent: true, filled: true }
253
+ ]
254
+ },
229
255
  workspace: {
230
256
  description: "Workspace container \u2014 panel with header bar and content",
231
257
  elements: [
@@ -239,7 +265,15 @@ var SUITE_GLYPHS = {
239
265
  organisation: {
240
266
  description: "Organisation chart \u2014 root node with two members",
241
267
  elements: [
242
- { kind: "rect", x: 9.5, y: 3.5, width: 5, height: 5, rx: 1.4, accent: true },
268
+ {
269
+ kind: "rect",
270
+ x: 9.5,
271
+ y: 3.5,
272
+ width: 5,
273
+ height: 5,
274
+ rx: 1.4,
275
+ accent: true
276
+ },
243
277
  { kind: "path", d: "M12 8.5v2.5" },
244
278
  { kind: "path", d: "M6.75 13.5v-2.5h10.5v2.5" },
245
279
  { kind: "rect", x: 4.25, y: 13.5, width: 5, height: 5, rx: 1.4 },
@@ -283,7 +317,10 @@ var SUITE_GLYPHS = {
283
317
  "bell-wave": {
284
318
  description: "Notifications \u2014 bell with sound waves",
285
319
  elements: [
286
- { kind: "path", d: "M7 9.2a5 5 0 0 1 10 0c0 5.3 2.4 7.3 2.4 7.3H4.6S7 14.5 7 9.2" },
320
+ {
321
+ kind: "path",
322
+ d: "M7 9.2a5 5 0 0 1 10 0c0 5.3 2.4 7.3 2.4 7.3H4.6S7 14.5 7 9.2"
323
+ },
287
324
  { kind: "path", d: "M10.7 19.3a1.5 1.5 0 0 0 2.6 0" },
288
325
  { kind: "path", d: "M17.9 6.4a5.5 5.5 0 0 1 1.4 3.7", accent: true },
289
326
  { kind: "path", d: "M15.7 4a9.4 9.4 0 0 1 2.4 6", accent: true }
@@ -942,13 +979,17 @@ function AppSwitcher({
942
979
  title,
943
980
  collapsed = false,
944
981
  dropdownMenu: DropdownMenu2,
945
- dropdownItem: DropdownItem2
982
+ dropdownItem: DropdownItem2,
983
+ triggerId,
984
+ triggerDataTest
946
985
  }) {
947
986
  const [open, setOpen] = useState(false);
948
987
  return /* @__PURE__ */ jsx6(
949
988
  DropdownMenu2,
950
989
  {
951
990
  "aria-label": "Switch application",
991
+ triggerId: triggerId != null ? triggerId : "app-switcher-trigger",
992
+ triggerDataTest: triggerDataTest != null ? triggerDataTest : "app-switcher-trigger",
952
993
  className: collapsed ? "w-11 shrink-0" : "min-w-0 flex-1",
953
994
  panelClassName: "w-64",
954
995
  align: "start",
@@ -970,11 +1011,12 @@ function AppSwitcher({
970
1011
  ]
971
1012
  }
972
1013
  ),
973
- children: /* @__PURE__ */ jsxs6("div", { className: "p-1", "data-test": "app-switcher-menu", children: [
1014
+ children: /* @__PURE__ */ jsxs6("div", { id: "app-switcher-menu", className: "p-1", "data-test": "app-switcher-menu", children: [
974
1015
  /* @__PURE__ */ jsx6("p", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-ph-mutedtext", children: "Switch application" }),
975
1016
  apps.map((app) => /* @__PURE__ */ jsx6(
976
1017
  DropdownItem2,
977
1018
  {
1019
+ id: `switch-app-${app.slug}`,
978
1020
  "data-test": `switch-app-${app.slug}`,
979
1021
  onMouseDown: (e) => e.preventDefault(),
980
1022
  onClick: () => {
@@ -1109,7 +1151,10 @@ function SuiteNotificationBell({
1109
1151
  markRead,
1110
1152
  markAllRead,
1111
1153
  dropdownMenu: DropdownMenu2,
1112
- cacheKey = "suite-notifications-cache"
1154
+ cacheKey = "suite-notifications-cache",
1155
+ dataTest = "suite-notifications",
1156
+ triggerId,
1157
+ triggerDataTest
1113
1158
  }) {
1114
1159
  const router = useRouter();
1115
1160
  const [open, setOpen] = useState2(false);
@@ -1210,11 +1255,13 @@ function SuiteNotificationBell({
1210
1255
  DropdownMenu2,
1211
1256
  {
1212
1257
  "aria-label": "Notifications",
1258
+ triggerId: triggerId != null ? triggerId : `${dataTest}-trigger`,
1259
+ triggerDataTest: triggerDataTest != null ? triggerDataTest : `${dataTest}-trigger`,
1213
1260
  align: "end",
1214
1261
  panelClassName: "w-80 overflow-hidden p-0",
1215
1262
  open,
1216
1263
  onOpenChange,
1217
- trigger: /* @__PURE__ */ jsxs7("span", { className: "relative inline-flex h-9 w-9 items-center justify-center rounded-full text-ph-mutedtext transition hover:bg-ph-muted hover:text-ph-ink", children: [
1264
+ trigger: /* @__PURE__ */ jsxs7("span", { className: "relative inline-flex h-11 w-11 items-center justify-center rounded-full text-ph-mutedtext transition hover:bg-ph-muted hover:text-ph-ink", children: [
1218
1265
  /* @__PURE__ */ jsx7(Bell, { className: "h-5 w-5", strokeWidth: 1.75, "aria-hidden": true }),
1219
1266
  unread > 0 ? /* @__PURE__ */ jsx7("span", { className: "absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-ph-brand px-1 text-[10px] font-semibold leading-none text-white ring-2 ring-ph-surface", children: unread > 9 ? "9+" : unread }) : null
1220
1267
  ] }),
@@ -1225,6 +1272,8 @@ function SuiteNotificationBell({
1225
1272
  "button",
1226
1273
  {
1227
1274
  type: "button",
1275
+ id: `${dataTest}-mark-all`,
1276
+ "data-test": `${dataTest}-mark-all`,
1228
1277
  onClick: markAll,
1229
1278
  className: "text-xs font-medium text-ph-brand hover:underline",
1230
1279
  children: "Mark all read"
@@ -1235,6 +1284,8 @@ function SuiteNotificationBell({
1235
1284
  "button",
1236
1285
  {
1237
1286
  type: "button",
1287
+ id: `${dataTest}-item-${n.id}`,
1288
+ "data-test": `${dataTest}-item-${n.id}`,
1238
1289
  onClick: () => void openItem(n),
1239
1290
  className: "flex w-full flex-col gap-0.5 px-3 py-2 text-left transition hover:bg-ph-muted",
1240
1291
  children: [
@@ -1279,6 +1330,10 @@ function CommandPaletteHost({
1279
1330
  items,
1280
1331
  isAuthenticated = true,
1281
1332
  placeholder = "Type a command or search\u2026",
1333
+ id,
1334
+ dataTest,
1335
+ inputId,
1336
+ inputDataTest,
1282
1337
  commandPalette: CommandPalette
1283
1338
  }) {
1284
1339
  const [open, setOpen] = useState3(false);
@@ -1299,7 +1354,11 @@ function CommandPaletteHost({
1299
1354
  items,
1300
1355
  isOpen: open,
1301
1356
  onClose: () => setOpen(false),
1302
- placeholder
1357
+ placeholder,
1358
+ id,
1359
+ dataTest,
1360
+ inputId,
1361
+ inputDataTest
1303
1362
  }
1304
1363
  );
1305
1364
  }
@@ -1347,6 +1406,10 @@ function SuiteMobileDrawer({
1347
1406
  durationMs = 200,
1348
1407
  dataTest,
1349
1408
  panelDataTest,
1409
+ backdropId,
1410
+ backdropDataTest,
1411
+ closeButtonId,
1412
+ closeButtonDataTest,
1350
1413
  panelClassName
1351
1414
  }) {
1352
1415
  const [rendered, setRendered] = useState5(open);
@@ -1398,6 +1461,8 @@ function SuiteMobileDrawer({
1398
1461
  "button",
1399
1462
  {
1400
1463
  type: "button",
1464
+ id: backdropId,
1465
+ "data-test": backdropDataTest,
1401
1466
  tabIndex: -1,
1402
1467
  className: cn(
1403
1468
  "absolute inset-0 bg-black/25 backdrop-blur-sm motion-safe:transition-opacity motion-safe:ease-spring-subtle",
@@ -1438,6 +1503,8 @@ function SuiteMobileDrawer({
1438
1503
  "button",
1439
1504
  {
1440
1505
  type: "button",
1506
+ id: closeButtonId,
1507
+ "data-test": closeButtonDataTest,
1441
1508
  onClick: onClose,
1442
1509
  className: "-mr-1.5 inline-flex h-11 w-11 items-center justify-center rounded-lg text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
1443
1510
  "aria-label": closeLabel,
@@ -1463,6 +1530,7 @@ function SuiteMobileHeader({
1463
1530
  title,
1464
1531
  actions,
1465
1532
  menuLabel = "Open navigation",
1533
+ menuId,
1466
1534
  menuDataTest,
1467
1535
  dataTest,
1468
1536
  className
@@ -1480,6 +1548,7 @@ function SuiteMobileHeader({
1480
1548
  "button",
1481
1549
  {
1482
1550
  type: "button",
1551
+ id: menuId,
1483
1552
  "data-test": menuDataTest,
1484
1553
  className: "suite-press inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-xl text-ph-ink transition-colors hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
1485
1554
  onClick: onMenuClick,
@@ -1623,7 +1692,7 @@ function SuitePageHeader({
1623
1692
  "data-test": dataTest,
1624
1693
  "data-stuck": sticky ? stuck ? "true" : "false" : void 0,
1625
1694
  className: cn(
1626
- "flex items-start justify-between gap-4 pb-2 sm:pb-3",
1695
+ "flex min-w-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3",
1627
1696
  // No extra pt here — page inset sets the shared title baseline.
1628
1697
  // Stuck state adds pad via .suite-page-header-sticky[data-stuck].
1629
1698
  sticky && "suite-page-header-sticky",
@@ -1647,7 +1716,7 @@ function SuitePageHeader({
1647
1716
  "h1",
1648
1717
  {
1649
1718
  className: cn(
1650
- "font-display text-[1.625rem] font-bold leading-none tracking-tight text-ph-ink sm:text-[2.25rem]",
1719
+ "min-w-0 break-words font-display text-[1.625rem] font-bold leading-none tracking-tight text-ph-ink text-balance sm:text-[2.25rem]",
1651
1720
  titleClassName
1652
1721
  ),
1653
1722
  children: title
@@ -1667,7 +1736,7 @@ function SuitePageHeader({
1667
1736
  }
1668
1737
  ) : null
1669
1738
  ] }),
1670
- actions ? /* @__PURE__ */ jsx12("div", { className: "flex shrink-0 items-center gap-2 self-center", children: actions }) : null
1739
+ actions ? /* @__PURE__ */ jsx12("div", { className: "flex max-w-full items-center gap-2 self-stretch overflow-x-auto pb-1 sm:shrink-0 sm:self-center sm:overflow-visible sm:pb-0", children: actions }) : null
1671
1740
  ]
1672
1741
  }
1673
1742
  );
@@ -1806,33 +1875,38 @@ function SuiteUserMenu({
1806
1875
  settingsHref,
1807
1876
  onSignOut,
1808
1877
  fallbackInitials,
1878
+ showSignOutAction = false,
1809
1879
  dataTest = "suite-user-menu",
1880
+ triggerId,
1881
+ triggerDataTest,
1810
1882
  className
1811
1883
  }) {
1812
1884
  const router = useRouter2();
1813
1885
  const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
1814
- const avatar = /* @__PURE__ */ jsx14("span", { className: "inline-flex h-11 w-11 items-center justify-center rounded-full transition-colors hover:bg-ph-muted", children: image ? /* @__PURE__ */ jsx14(
1886
+ const avatar = /* @__PURE__ */ jsx14("span", { className: "inline-flex h-11 w-11 items-center justify-center rounded-full ring-2 ring-ph-border ring-offset-1 ring-offset-ph-canvas transition-colors hover:bg-ph-muted", children: image ? /* @__PURE__ */ jsx14(
1815
1887
  Image2,
1816
1888
  {
1817
1889
  src: image,
1818
1890
  alt: "",
1819
- width: 32,
1820
- height: 32,
1821
- className: "h-8 w-8 rounded-full object-cover",
1891
+ width: 40,
1892
+ height: 40,
1893
+ className: "h-10 w-10 rounded-full object-cover",
1822
1894
  unoptimized: true
1823
1895
  }
1824
- ) : /* @__PURE__ */ jsx14("span", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-ph-muted text-sm font-semibold text-ph-brand", children: initials }) });
1825
- return /* @__PURE__ */ jsxs12(
1896
+ ) : /* @__PURE__ */ jsx14("span", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-ph-muted text-sm font-semibold text-ph-brand", children: initials }) });
1897
+ const accountMenu = /* @__PURE__ */ jsxs12(
1826
1898
  DropdownMenu,
1827
1899
  {
1828
1900
  trigger: avatar,
1901
+ triggerId: triggerId != null ? triggerId : `${dataTest}-trigger`,
1902
+ triggerDataTest: triggerDataTest != null ? triggerDataTest : `${dataTest}-trigger`,
1829
1903
  "aria-label": "Account menu",
1830
1904
  align: "end",
1831
1905
  side: "bottom",
1832
1906
  sideOffset: 6,
1833
1907
  collisionPadding: 16,
1834
1908
  modal: false,
1835
- className,
1909
+ className: showSignOutAction ? void 0 : className,
1836
1910
  "data-test": dataTest,
1837
1911
  children: [
1838
1912
  /* @__PURE__ */ jsxs12("div", { className: "px-2 py-1.5", children: [
@@ -1851,20 +1925,31 @@ function SuiteUserMenu({
1851
1925
  ]
1852
1926
  }
1853
1927
  ),
1854
- /* @__PURE__ */ jsxs12(
1855
- DropdownItem,
1856
- {
1857
- "data-test": `${dataTest}-sign-out`,
1858
- onClick: onSignOut,
1859
- children: [
1860
- /* @__PURE__ */ jsx14(LogOut, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
1861
- "Sign out"
1862
- ]
1863
- }
1864
- )
1928
+ /* @__PURE__ */ jsxs12(DropdownItem, { "data-test": `${dataTest}-sign-out`, onClick: onSignOut, children: [
1929
+ /* @__PURE__ */ jsx14(LogOut, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
1930
+ "Sign out"
1931
+ ] })
1865
1932
  ]
1866
1933
  }
1867
1934
  );
1935
+ if (!showSignOutAction) {
1936
+ return accountMenu;
1937
+ }
1938
+ return /* @__PURE__ */ jsxs12("div", { className: cn("flex min-w-0 items-center gap-2", className), children: [
1939
+ accountMenu,
1940
+ /* @__PURE__ */ jsx14(
1941
+ "button",
1942
+ {
1943
+ type: "button",
1944
+ "data-test": `${dataTest}-visible-sign-out`,
1945
+ title: "Sign out",
1946
+ "aria-label": "Sign out",
1947
+ className: "inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-focus-ring",
1948
+ onClick: onSignOut,
1949
+ children: /* @__PURE__ */ jsx14(LogOut, { className: "h-4 w-4", "aria-hidden": true })
1950
+ }
1951
+ )
1952
+ ] });
1868
1953
  }
1869
1954
 
1870
1955
  // src/suite/components/suite-bottom-nav.tsx
@@ -1915,6 +2000,7 @@ function SuiteBottomNav({
1915
2000
  Link,
1916
2001
  {
1917
2002
  href: item.href,
2003
+ id: item.id,
1918
2004
  "data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
1919
2005
  "aria-current": active ? "page" : void 0,
1920
2006
  className: cn(
@@ -2544,8 +2630,9 @@ function snapWidth(width) {
2544
2630
  if (width < SIDEBAR_MIN_EXPANDED_WIDTH) return SIDEBAR_MIN_EXPANDED_WIDTH;
2545
2631
  return Math.min(SIDEBAR_MAX_WIDTH, width);
2546
2632
  }
2547
- function useSidebarWidth(storageKey) {
2548
- const [width, setWidth] = useState8(SIDEBAR_DEFAULT_WIDTH);
2633
+ function useSidebarWidth(storageKey, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
2634
+ const fallbackWidth = snapWidth(clampWidth(defaultWidth));
2635
+ const [width, setWidth] = useState8(fallbackWidth);
2549
2636
  const [narrowViewport, setNarrowViewport] = useState8(false);
2550
2637
  const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
2551
2638
  useEffect7(() => {
@@ -2579,17 +2666,17 @@ function useSidebarWidth(storageKey) {
2579
2666
  const setCollapsed = useCallback3(
2580
2667
  (value) => {
2581
2668
  setWidth((current) => {
2582
- const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? SIDEBAR_DEFAULT_WIDTH : snapWidth(current);
2669
+ const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? fallbackWidth : snapWidth(current);
2583
2670
  persist(next);
2584
2671
  return next;
2585
2672
  });
2586
2673
  },
2587
- [persist]
2674
+ [fallbackWidth, persist]
2588
2675
  );
2589
2676
  const resetWidth = useCallback3(() => {
2590
- setWidth(SIDEBAR_DEFAULT_WIDTH);
2591
- persist(SIDEBAR_DEFAULT_WIDTH);
2592
- }, [persist]);
2677
+ setWidth(fallbackWidth);
2678
+ persist(fallbackWidth);
2679
+ }, [fallbackWidth, persist]);
2593
2680
  const startResize = useCallback3(
2594
2681
  (event) => {
2595
2682
  event.preventDefault();
@@ -2612,7 +2699,17 @@ function useSidebarWidth(storageKey) {
2612
2699
  },
2613
2700
  [persist, width]
2614
2701
  );
2615
- return { width, collapsed, setCollapsed, resetWidth, startResize };
2702
+ const resizeBy = useCallback3(
2703
+ (delta) => {
2704
+ setWidth((current) => {
2705
+ const next = clampWidth(current + delta);
2706
+ persist(next);
2707
+ return next;
2708
+ });
2709
+ },
2710
+ [persist]
2711
+ );
2712
+ return { width, collapsed, setCollapsed, resetWidth, startResize, resizeBy };
2616
2713
  }
2617
2714
 
2618
2715
  // src/suite/lib/motion.tsx
@@ -2809,6 +2906,7 @@ function SuiteSettingsMobileNav({
2809
2906
  "button",
2810
2907
  {
2811
2908
  type: "button",
2909
+ id: item.id,
2812
2910
  "data-test": item.testId,
2813
2911
  onClick: () => onSelect(item.href),
2814
2912
  "aria-current": active ? "page" : void 0,
@@ -2881,67 +2979,62 @@ function SuiteSidebar({
2881
2979
  collapsed ? "px-1.5 py-2" : "p-2"
2882
2980
  ),
2883
2981
  children: [
2884
- /* @__PURE__ */ jsxs18(
2885
- "nav",
2886
- {
2887
- "aria-label": "Pages",
2888
- className: "shrink-0 space-y-0.5",
2889
- children: [
2890
- /* @__PURE__ */ jsx21("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
2891
- /* @__PURE__ */ jsx21("div", { className: "space-y-0.5", children: navItems.map((item) => {
2892
- const Icon = item.icon;
2893
- const active = Boolean(item.active);
2894
- const link = /* @__PURE__ */ jsxs18(
2895
- Link2,
2896
- {
2897
- href: item.href,
2898
- "data-test": "nav-link",
2899
- "aria-current": active ? "page" : void 0,
2900
- onClick: item.onClick,
2901
- className: cn(
2902
- "group relative flex items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
2903
- active ? "bg-ph-muted" : "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
2904
- collapsed ? "mx-auto size-10 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
2905
- ),
2906
- children: [
2907
- /* @__PURE__ */ jsx21(
2908
- "span",
2909
- {
2910
- className: cn(
2911
- "relative flex h-4 w-4 shrink-0 items-center justify-center",
2912
- item.iconClassName
2913
- ),
2914
- "aria-hidden": true,
2915
- children: /* @__PURE__ */ jsx21(
2916
- Icon,
2917
- {
2918
- className: "h-full w-full",
2919
- strokeWidth: active ? 2 : 1.75
2920
- }
2921
- )
2922
- }
2982
+ /* @__PURE__ */ jsxs18("nav", { "aria-label": "Pages", className: "shrink-0 space-y-0.5", children: [
2983
+ /* @__PURE__ */ jsx21("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
2984
+ /* @__PURE__ */ jsx21("div", { className: "space-y-0.5", children: navItems.map((item) => {
2985
+ var _a;
2986
+ const Icon = item.icon;
2987
+ const active = Boolean(item.active);
2988
+ const link = /* @__PURE__ */ jsxs18(
2989
+ Link2,
2990
+ {
2991
+ href: item.href,
2992
+ id: item.id,
2993
+ "data-test": (_a = item.dataTest) != null ? _a : "nav-link",
2994
+ "aria-current": active ? "page" : void 0,
2995
+ onClick: item.onClick,
2996
+ className: cn(
2997
+ "group relative flex min-h-11 touch-manipulation items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
2998
+ active ? "bg-ph-muted" : "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
2999
+ collapsed ? "mx-auto size-11 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
3000
+ ),
3001
+ children: [
3002
+ /* @__PURE__ */ jsx21(
3003
+ "span",
3004
+ {
3005
+ className: cn(
3006
+ "relative flex h-4 w-4 shrink-0 items-center justify-center",
3007
+ item.iconClassName
2923
3008
  ),
2924
- /* @__PURE__ */ jsx21(
2925
- "span",
3009
+ "aria-hidden": true,
3010
+ children: /* @__PURE__ */ jsx21(
3011
+ Icon,
2926
3012
  {
2927
- className: cn(
2928
- "relative truncate",
2929
- active ? "text-ph-ink" : "text-ph-subtle group-hover:text-ph-ink",
2930
- collapsed && "sr-only"
2931
- ),
2932
- children: item.label
3013
+ className: "h-full w-full",
3014
+ strokeWidth: active ? 2 : 1.75
2933
3015
  }
3016
+ )
3017
+ }
3018
+ ),
3019
+ /* @__PURE__ */ jsx21(
3020
+ "span",
3021
+ {
3022
+ className: cn(
3023
+ "relative truncate",
3024
+ active ? "text-ph-ink" : "text-ph-subtle group-hover:text-ph-ink",
3025
+ collapsed && "sr-only"
2934
3026
  ),
2935
- !collapsed && item.badge ? /* @__PURE__ */ jsx21("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
2936
- ]
2937
- },
2938
- item.label
2939
- );
2940
- return collapsed ? /* @__PURE__ */ jsx21(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
2941
- }) })
2942
- ]
2943
- }
2944
- ),
3027
+ children: item.label
3028
+ }
3029
+ ),
3030
+ !collapsed && item.badge ? /* @__PURE__ */ jsx21("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
3031
+ ]
3032
+ },
3033
+ item.label
3034
+ );
3035
+ return collapsed ? /* @__PURE__ */ jsx21(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
3036
+ }) })
3037
+ ] }),
2945
3038
  secondaryNav ? /* @__PURE__ */ jsx21(
2946
3039
  "div",
2947
3040
  {
@@ -2966,11 +3059,11 @@ function SuiteSidebar({
2966
3059
  {
2967
3060
  className: cn(
2968
3061
  "flex items-center gap-2",
2969
- collapsed && "justify-center"
3062
+ collapsed ? "flex-col justify-center" : "min-w-0"
2970
3063
  ),
2971
3064
  children: [
2972
3065
  renderNode(userMenu, collapsed),
2973
- !collapsed && footerExtras ? /* @__PURE__ */ jsx21("div", { className: "ml-auto shrink-0", children: renderNode(footerExtras, collapsed) }) : null
3066
+ footerExtras ? /* @__PURE__ */ jsx21("div", { className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: renderNode(footerExtras, collapsed) }) : null
2974
3067
  ]
2975
3068
  }
2976
3069
  )
@@ -2992,6 +3085,7 @@ function SuiteAppLayout({
2992
3085
  collapsed = false,
2993
3086
  lockMainScroll = false,
2994
3087
  onStartResize,
3088
+ onResizeBy,
2995
3089
  onResetWidth,
2996
3090
  className
2997
3091
  }) {
@@ -2999,12 +3093,15 @@ function SuiteAppLayout({
2999
3093
  "div",
3000
3094
  {
3001
3095
  "data-test": "app-shell",
3002
- className: cn("flex min-h-dvh lg:h-screen lg:overflow-hidden", className),
3096
+ className: cn(
3097
+ "suite-app-layout flex h-dvh overflow-hidden",
3098
+ className
3099
+ ),
3003
3100
  children: [
3004
3101
  /* @__PURE__ */ jsxs19(
3005
3102
  "aside",
3006
3103
  {
3007
- className: "relative hidden shrink-0 flex-col overflow-hidden border-r border-ph-border transition-[width] duration-200 ease-out lg:flex",
3104
+ className: "relative hidden shrink-0 flex-col overflow-visible border-r border-ph-border ease-out lg:flex",
3008
3105
  style: { width: `${sidebarWidth}px` },
3009
3106
  "data-collapsed": collapsed ? "true" : "false",
3010
3107
  children: [
@@ -3015,9 +3112,23 @@ function SuiteAppLayout({
3015
3112
  role: "separator",
3016
3113
  "aria-orientation": "vertical",
3017
3114
  "aria-label": "Resize sidebar",
3115
+ "data-test": "sidebar-resize-handle",
3116
+ tabIndex: onResizeBy ? 0 : void 0,
3018
3117
  onPointerDown: onStartResize,
3019
3118
  onDoubleClick: onResetWidth,
3020
- className: "absolute inset-y-0 right-0 z-10 w-1 cursor-col-resize transition-colors hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
3119
+ onKeyDown: (event) => {
3120
+ if (event.key === "Home") {
3121
+ event.preventDefault();
3122
+ onResetWidth == null ? void 0 : onResetWidth();
3123
+ } else if (event.key === "ArrowLeft") {
3124
+ event.preventDefault();
3125
+ onResizeBy == null ? void 0 : onResizeBy(-16);
3126
+ } else if (event.key === "ArrowRight") {
3127
+ event.preventDefault();
3128
+ onResizeBy == null ? void 0 : onResizeBy(16);
3129
+ }
3130
+ },
3131
+ className: "absolute inset-y-0 -right-1 z-10 w-2 cursor-col-resize touch-none transition-colors hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
3021
3132
  }
3022
3133
  ) : null
3023
3134
  ]
@@ -3033,6 +3144,7 @@ function SuiteAppLayout({
3033
3144
  "data-lock-scroll": lockMainScroll ? "true" : void 0,
3034
3145
  className: cn(
3035
3146
  "flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
3147
+ "suite-app-layout__main",
3036
3148
  lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
3037
3149
  ),
3038
3150
  children