@xenide-io/the-old-ui-theme 0.5.3 → 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.
- package/dist/{index-Od4pIP4F.d.mts → Chip-C5hRFAhe.d.mts} +10 -606
- package/dist/{index-Od4pIP4F.d.ts → Chip-C5hRFAhe.d.ts} +10 -606
- package/dist/{chunk-G53YLHVE.mjs → chunk-E5ZBQYEX.mjs} +59 -9
- package/dist/{chunk-VFTZXPXM.mjs → chunk-SBBKXV35.mjs} +144 -79
- package/dist/index.d.mts +3 -79
- package/dist/index.d.ts +3 -79
- package/dist/index.js +524 -3595
- package/dist/index.mjs +3 -765
- package/dist/suite.d.mts +38 -12
- package/dist/suite.d.ts +38 -12
- package/dist/suite.js +84 -15
- package/dist/suite.mjs +53 -13
- package/dist/ui.d.mts +608 -2
- package/dist/ui.d.ts +608 -2
- package/dist/ui.js +202 -87
- package/dist/ui.mjs +2 -2
- package/package.json +2 -6
- package/scripts/install-theme-dev.sh +60 -0
- package/scripts/sync-posthog-icons.mjs +75 -0
- package/src/components/ui/Chip.tsx +36 -18
- package/src/components/ui/CommandPalette.test.tsx +41 -0
- package/src/components/ui/CommandPalette.tsx +58 -9
- package/src/components/ui/DropdownMenu.tsx +50 -11
- package/src/components/ui/SegmentedControl.tsx +2 -1
- package/src/components/ui/SettingsLayout.tsx +19 -5
- package/src/components/ui/interaction-primitives.test.tsx +52 -0
- package/src/styles/suite-skin.css +17 -35
- package/src/suite/components/app-switcher.tsx +32 -25
- package/src/suite/components/command-palette-host.tsx +20 -8
- package/src/suite/components/suite-app-layout.tsx +1 -1
- package/src/suite/components/suite-bottom-nav.tsx +23 -18
- package/src/suite/components/suite-layout.test.tsx +44 -0
- package/src/suite/components/suite-layout.tsx +3 -3
- package/src/suite/components/suite-mobile-drawer.tsx +12 -0
- package/src/suite/components/suite-mobile-header.tsx +15 -9
- package/src/suite/components/suite-notification-bell.tsx +23 -11
- package/src/suite/components/suite-settings-mobile-nav.tsx +2 -0
- package/src/suite/components/suite-sidebar.tsx +6 -3
- package/src/suite/components/suite-user-menu.tsx +6 -0
- package/src/suite/lib/injected.ts +12 -11
- package/src/components/charts/index.ts +0 -9
- package/src/components/charts/quill/BarChart.tsx +0 -85
- package/src/components/charts/quill/FunnelChart.tsx +0 -49
- package/src/components/charts/quill/InsightShell.tsx +0 -27
- package/src/components/charts/quill/MetricCard.tsx +0 -44
- package/src/components/charts/quill/PieChart.tsx +0 -81
- package/src/components/charts/quill/Sparkline.tsx +0 -57
- package/src/components/charts/quill/TimeSeriesLineChart.tsx +0 -62
- package/src/components/charts/quill/index.ts +0 -9
package/dist/suite.d.mts
CHANGED
|
@@ -130,10 +130,12 @@ declare function TodayEmptyState({ title, description, }: {
|
|
|
130
130
|
*/
|
|
131
131
|
interface SuiteDropdownMenuProps {
|
|
132
132
|
trigger: ReactNode;
|
|
133
|
+
triggerId?: string;
|
|
134
|
+
triggerDataTest?: string;
|
|
133
135
|
children: ReactNode;
|
|
134
|
-
|
|
135
|
-
align?:
|
|
136
|
-
side?:
|
|
136
|
+
"aria-label": string;
|
|
137
|
+
align?: "start" | "center" | "end";
|
|
138
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
137
139
|
sideOffset?: number;
|
|
138
140
|
className?: string;
|
|
139
141
|
panelClassName?: string;
|
|
@@ -155,10 +157,14 @@ type SuiteCommandPaletteComponent = ComponentType<{
|
|
|
155
157
|
onClose: () => void;
|
|
156
158
|
placeholder?: string;
|
|
157
159
|
className?: string;
|
|
160
|
+
id?: string;
|
|
161
|
+
dataTest?: string;
|
|
162
|
+
inputId?: string;
|
|
163
|
+
inputDataTest?: string;
|
|
158
164
|
}>;
|
|
159
165
|
/** App-branded spinner (each app has its own AppSpinner design). */
|
|
160
166
|
type SuiteSpinnerComponent = ComponentType<{
|
|
161
|
-
size?:
|
|
167
|
+
size?: "sm" | "md" | "lg";
|
|
162
168
|
className?: string;
|
|
163
169
|
label?: string;
|
|
164
170
|
}>;
|
|
@@ -186,7 +192,7 @@ interface SuiteAppEntry {
|
|
|
186
192
|
* visible app list, the cross-app navigation handler, and the theme
|
|
187
193
|
* dropdown primitives.
|
|
188
194
|
*/
|
|
189
|
-
declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapsed, dropdownMenu: DropdownMenu, dropdownItem: DropdownItem, }: {
|
|
195
|
+
declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapsed, dropdownMenu: DropdownMenu, dropdownItem: DropdownItem, triggerId, triggerDataTest, }: {
|
|
190
196
|
apps: SuiteAppEntry[];
|
|
191
197
|
currentApp: string;
|
|
192
198
|
onSelect: (app: SuiteAppEntry) => void;
|
|
@@ -195,6 +201,8 @@ declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapse
|
|
|
195
201
|
collapsed?: boolean;
|
|
196
202
|
dropdownMenu: SuiteDropdownMenuComponent;
|
|
197
203
|
dropdownItem: SuiteDropdownItemComponent;
|
|
204
|
+
triggerId?: string;
|
|
205
|
+
triggerDataTest?: string;
|
|
198
206
|
}): react.JSX.Element;
|
|
199
207
|
|
|
200
208
|
/** Cross-app (suite) notification from `/api/notifications/` — shared across ShellStack apps. */
|
|
@@ -214,23 +222,30 @@ interface SuiteNotificationsResponse {
|
|
|
214
222
|
notifications: SuiteNotification[];
|
|
215
223
|
unread_count: number;
|
|
216
224
|
}
|
|
217
|
-
declare function SuiteNotificationBell({ fetchNotifications, markRead, markAllRead, dropdownMenu: DropdownMenu, cacheKey, }: {
|
|
225
|
+
declare function SuiteNotificationBell({ fetchNotifications, markRead, markAllRead, dropdownMenu: DropdownMenu, cacheKey, dataTest, triggerId, triggerDataTest, }: {
|
|
218
226
|
fetchNotifications: () => Promise<SuiteNotificationsResponse>;
|
|
219
227
|
markRead: (id: string) => Promise<unknown>;
|
|
220
228
|
markAllRead: () => Promise<unknown>;
|
|
221
229
|
dropdownMenu: SuiteDropdownMenuComponent;
|
|
222
230
|
/** sessionStorage key for stale-while-revalidate; `null` disables caching. */
|
|
223
231
|
cacheKey?: string | null;
|
|
232
|
+
dataTest?: string;
|
|
233
|
+
triggerId?: string;
|
|
234
|
+
triggerDataTest?: string;
|
|
224
235
|
}): react.JSX.Element;
|
|
225
236
|
|
|
226
237
|
/**
|
|
227
238
|
* Cmd/Ctrl+K command palette host. Apps build the item list and inject the
|
|
228
239
|
* theme CommandPalette primitive.
|
|
229
240
|
*/
|
|
230
|
-
declare function CommandPaletteHost({ items, isAuthenticated, placeholder, commandPalette: CommandPalette, }: {
|
|
241
|
+
declare function CommandPaletteHost({ items, isAuthenticated, placeholder, id, dataTest, inputId, inputDataTest, commandPalette: CommandPalette, }: {
|
|
231
242
|
items: SuiteCommandItem[];
|
|
232
243
|
isAuthenticated?: boolean;
|
|
233
244
|
placeholder?: string;
|
|
245
|
+
id?: string;
|
|
246
|
+
dataTest?: string;
|
|
247
|
+
inputId?: string;
|
|
248
|
+
inputDataTest?: string;
|
|
234
249
|
commandPalette: SuiteCommandPaletteComponent;
|
|
235
250
|
}): react.JSX.Element | null;
|
|
236
251
|
|
|
@@ -244,7 +259,7 @@ declare function DeferredChrome({ children }: {
|
|
|
244
259
|
* close, body scroll-lock and focus hand-off while open. Nav content stays
|
|
245
260
|
* app-side via `children`.
|
|
246
261
|
*/
|
|
247
|
-
declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseButton, title, closeLabel, backdropLabel, dialogLabel, durationMs, dataTest, panelDataTest, panelClassName, }: {
|
|
262
|
+
declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseButton, title, closeLabel, backdropLabel, dialogLabel, durationMs, dataTest, panelDataTest, backdropId, backdropDataTest, closeButtonId, closeButtonDataTest, panelClassName, }: {
|
|
248
263
|
open: boolean;
|
|
249
264
|
onClose: () => void;
|
|
250
265
|
children: ReactNode;
|
|
@@ -262,13 +277,17 @@ declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseBut
|
|
|
262
277
|
durationMs?: number;
|
|
263
278
|
dataTest?: string;
|
|
264
279
|
panelDataTest?: string;
|
|
280
|
+
backdropId?: string;
|
|
281
|
+
backdropDataTest?: string;
|
|
282
|
+
closeButtonId?: string;
|
|
283
|
+
closeButtonDataTest?: string;
|
|
265
284
|
/** Panel surface overrides (e.g. `bg-ph-canvas`). */
|
|
266
285
|
panelClassName?: string;
|
|
267
286
|
}): react.JSX.Element | null;
|
|
268
287
|
|
|
269
288
|
type SuiteMenuIcon = ComponentType<{
|
|
270
289
|
className?: string;
|
|
271
|
-
|
|
290
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
272
291
|
}>;
|
|
273
292
|
/**
|
|
274
293
|
* Suite mobile app bar — the standardized top of every app on phone/tablet.
|
|
@@ -276,7 +295,7 @@ type SuiteMenuIcon = ComponentType<{
|
|
|
276
295
|
* Translucent + blurred (suite-skin.css `.suite-app-bar`), safe-area aware,
|
|
277
296
|
* 44px minimum touch targets. Desktop chrome (rail/top bar) stays app-side.
|
|
278
297
|
*/
|
|
279
|
-
declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, actions, menuLabel, menuDataTest, dataTest, className, }: {
|
|
298
|
+
declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, actions, menuLabel, menuId, menuDataTest, dataTest, className, }: {
|
|
280
299
|
/** Optional — omit to drop the hamburger (bottom-nav apps don't need one). */
|
|
281
300
|
onMenuClick?: () => void;
|
|
282
301
|
/** Leading button glyph — defaults to Menu; browse-style drawers can swap it. */
|
|
@@ -286,6 +305,7 @@ declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, act
|
|
|
286
305
|
/** Right-hand slot — search, bell, avatar (keep this order). */
|
|
287
306
|
actions?: ReactNode;
|
|
288
307
|
menuLabel?: string;
|
|
308
|
+
menuId?: string;
|
|
289
309
|
menuDataTest?: string;
|
|
290
310
|
dataTest?: string;
|
|
291
311
|
className?: string;
|
|
@@ -322,6 +342,8 @@ interface SuiteUserMenuProps {
|
|
|
322
342
|
/** Show the old desktop sidebar sign-out action beside the avatar. */
|
|
323
343
|
showSignOutAction?: boolean;
|
|
324
344
|
dataTest?: string;
|
|
345
|
+
triggerId?: string;
|
|
346
|
+
triggerDataTest?: string;
|
|
325
347
|
className?: string;
|
|
326
348
|
}
|
|
327
349
|
/**
|
|
@@ -329,13 +351,13 @@ interface SuiteUserMenuProps {
|
|
|
329
351
|
* profile settings and sign out. Desktop sidebars can also expose the legacy
|
|
330
352
|
* adjacent sign-out action without adding it to mobile chrome.
|
|
331
353
|
*/
|
|
332
|
-
declare function SuiteUserMenu({ name, email, image, settingsHref, onSignOut, fallbackInitials, showSignOutAction, dataTest, className, }: SuiteUserMenuProps): react.JSX.Element;
|
|
354
|
+
declare function SuiteUserMenu({ name, email, image, settingsHref, onSignOut, fallbackInitials, showSignOutAction, dataTest, triggerId, triggerDataTest, className, }: SuiteUserMenuProps): react.JSX.Element;
|
|
333
355
|
|
|
334
356
|
/** Any icon component that accepts sizing/stroke props (Lucide, theme icons). */
|
|
335
357
|
type SuiteNavIcon = ComponentType<{
|
|
336
358
|
className?: string;
|
|
337
359
|
strokeWidth?: number | string;
|
|
338
|
-
|
|
360
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
339
361
|
}>;
|
|
340
362
|
/**
|
|
341
363
|
* Suite bottom navigation — the mobile/tablet primary nav, identical in
|
|
@@ -348,6 +370,7 @@ interface SuiteBottomNavItem {
|
|
|
348
370
|
href: string;
|
|
349
371
|
label: string;
|
|
350
372
|
icon: SuiteNavIcon;
|
|
373
|
+
id?: string;
|
|
351
374
|
active?: boolean;
|
|
352
375
|
dataTest?: string;
|
|
353
376
|
}
|
|
@@ -788,6 +811,7 @@ interface SuiteSettingsNavItem {
|
|
|
788
811
|
label: string;
|
|
789
812
|
href: string;
|
|
790
813
|
icon: ElementType | ReactNode;
|
|
814
|
+
id?: string;
|
|
791
815
|
testId?: string;
|
|
792
816
|
}
|
|
793
817
|
interface SuiteSettingsMobileNavProps {
|
|
@@ -811,6 +835,8 @@ interface SuiteSidebarNavItem {
|
|
|
811
835
|
href: string;
|
|
812
836
|
label: string;
|
|
813
837
|
icon: SuiteNavIcon;
|
|
838
|
+
id?: string;
|
|
839
|
+
dataTest?: string;
|
|
814
840
|
active?: boolean;
|
|
815
841
|
onClick?: () => void;
|
|
816
842
|
badge?: ReactNode;
|
package/dist/suite.d.ts
CHANGED
|
@@ -130,10 +130,12 @@ declare function TodayEmptyState({ title, description, }: {
|
|
|
130
130
|
*/
|
|
131
131
|
interface SuiteDropdownMenuProps {
|
|
132
132
|
trigger: ReactNode;
|
|
133
|
+
triggerId?: string;
|
|
134
|
+
triggerDataTest?: string;
|
|
133
135
|
children: ReactNode;
|
|
134
|
-
|
|
135
|
-
align?:
|
|
136
|
-
side?:
|
|
136
|
+
"aria-label": string;
|
|
137
|
+
align?: "start" | "center" | "end";
|
|
138
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
137
139
|
sideOffset?: number;
|
|
138
140
|
className?: string;
|
|
139
141
|
panelClassName?: string;
|
|
@@ -155,10 +157,14 @@ type SuiteCommandPaletteComponent = ComponentType<{
|
|
|
155
157
|
onClose: () => void;
|
|
156
158
|
placeholder?: string;
|
|
157
159
|
className?: string;
|
|
160
|
+
id?: string;
|
|
161
|
+
dataTest?: string;
|
|
162
|
+
inputId?: string;
|
|
163
|
+
inputDataTest?: string;
|
|
158
164
|
}>;
|
|
159
165
|
/** App-branded spinner (each app has its own AppSpinner design). */
|
|
160
166
|
type SuiteSpinnerComponent = ComponentType<{
|
|
161
|
-
size?:
|
|
167
|
+
size?: "sm" | "md" | "lg";
|
|
162
168
|
className?: string;
|
|
163
169
|
label?: string;
|
|
164
170
|
}>;
|
|
@@ -186,7 +192,7 @@ interface SuiteAppEntry {
|
|
|
186
192
|
* visible app list, the cross-app navigation handler, and the theme
|
|
187
193
|
* dropdown primitives.
|
|
188
194
|
*/
|
|
189
|
-
declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapsed, dropdownMenu: DropdownMenu, dropdownItem: DropdownItem, }: {
|
|
195
|
+
declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapsed, dropdownMenu: DropdownMenu, dropdownItem: DropdownItem, triggerId, triggerDataTest, }: {
|
|
190
196
|
apps: SuiteAppEntry[];
|
|
191
197
|
currentApp: string;
|
|
192
198
|
onSelect: (app: SuiteAppEntry) => void;
|
|
@@ -195,6 +201,8 @@ declare function AppSwitcher({ apps, currentApp, onSelect, mark, title, collapse
|
|
|
195
201
|
collapsed?: boolean;
|
|
196
202
|
dropdownMenu: SuiteDropdownMenuComponent;
|
|
197
203
|
dropdownItem: SuiteDropdownItemComponent;
|
|
204
|
+
triggerId?: string;
|
|
205
|
+
triggerDataTest?: string;
|
|
198
206
|
}): react.JSX.Element;
|
|
199
207
|
|
|
200
208
|
/** Cross-app (suite) notification from `/api/notifications/` — shared across ShellStack apps. */
|
|
@@ -214,23 +222,30 @@ interface SuiteNotificationsResponse {
|
|
|
214
222
|
notifications: SuiteNotification[];
|
|
215
223
|
unread_count: number;
|
|
216
224
|
}
|
|
217
|
-
declare function SuiteNotificationBell({ fetchNotifications, markRead, markAllRead, dropdownMenu: DropdownMenu, cacheKey, }: {
|
|
225
|
+
declare function SuiteNotificationBell({ fetchNotifications, markRead, markAllRead, dropdownMenu: DropdownMenu, cacheKey, dataTest, triggerId, triggerDataTest, }: {
|
|
218
226
|
fetchNotifications: () => Promise<SuiteNotificationsResponse>;
|
|
219
227
|
markRead: (id: string) => Promise<unknown>;
|
|
220
228
|
markAllRead: () => Promise<unknown>;
|
|
221
229
|
dropdownMenu: SuiteDropdownMenuComponent;
|
|
222
230
|
/** sessionStorage key for stale-while-revalidate; `null` disables caching. */
|
|
223
231
|
cacheKey?: string | null;
|
|
232
|
+
dataTest?: string;
|
|
233
|
+
triggerId?: string;
|
|
234
|
+
triggerDataTest?: string;
|
|
224
235
|
}): react.JSX.Element;
|
|
225
236
|
|
|
226
237
|
/**
|
|
227
238
|
* Cmd/Ctrl+K command palette host. Apps build the item list and inject the
|
|
228
239
|
* theme CommandPalette primitive.
|
|
229
240
|
*/
|
|
230
|
-
declare function CommandPaletteHost({ items, isAuthenticated, placeholder, commandPalette: CommandPalette, }: {
|
|
241
|
+
declare function CommandPaletteHost({ items, isAuthenticated, placeholder, id, dataTest, inputId, inputDataTest, commandPalette: CommandPalette, }: {
|
|
231
242
|
items: SuiteCommandItem[];
|
|
232
243
|
isAuthenticated?: boolean;
|
|
233
244
|
placeholder?: string;
|
|
245
|
+
id?: string;
|
|
246
|
+
dataTest?: string;
|
|
247
|
+
inputId?: string;
|
|
248
|
+
inputDataTest?: string;
|
|
234
249
|
commandPalette: SuiteCommandPaletteComponent;
|
|
235
250
|
}): react.JSX.Element | null;
|
|
236
251
|
|
|
@@ -244,7 +259,7 @@ declare function DeferredChrome({ children }: {
|
|
|
244
259
|
* close, body scroll-lock and focus hand-off while open. Nav content stays
|
|
245
260
|
* app-side via `children`.
|
|
246
261
|
*/
|
|
247
|
-
declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseButton, title, closeLabel, backdropLabel, dialogLabel, durationMs, dataTest, panelDataTest, panelClassName, }: {
|
|
262
|
+
declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseButton, title, closeLabel, backdropLabel, dialogLabel, durationMs, dataTest, panelDataTest, backdropId, backdropDataTest, closeButtonId, closeButtonDataTest, panelClassName, }: {
|
|
248
263
|
open: boolean;
|
|
249
264
|
onClose: () => void;
|
|
250
265
|
children: ReactNode;
|
|
@@ -262,13 +277,17 @@ declare function SuiteMobileDrawer({ open, onClose, children, side, showCloseBut
|
|
|
262
277
|
durationMs?: number;
|
|
263
278
|
dataTest?: string;
|
|
264
279
|
panelDataTest?: string;
|
|
280
|
+
backdropId?: string;
|
|
281
|
+
backdropDataTest?: string;
|
|
282
|
+
closeButtonId?: string;
|
|
283
|
+
closeButtonDataTest?: string;
|
|
265
284
|
/** Panel surface overrides (e.g. `bg-ph-canvas`). */
|
|
266
285
|
panelClassName?: string;
|
|
267
286
|
}): react.JSX.Element | null;
|
|
268
287
|
|
|
269
288
|
type SuiteMenuIcon = ComponentType<{
|
|
270
289
|
className?: string;
|
|
271
|
-
|
|
290
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
272
291
|
}>;
|
|
273
292
|
/**
|
|
274
293
|
* Suite mobile app bar — the standardized top of every app on phone/tablet.
|
|
@@ -276,7 +295,7 @@ type SuiteMenuIcon = ComponentType<{
|
|
|
276
295
|
* Translucent + blurred (suite-skin.css `.suite-app-bar`), safe-area aware,
|
|
277
296
|
* 44px minimum touch targets. Desktop chrome (rail/top bar) stays app-side.
|
|
278
297
|
*/
|
|
279
|
-
declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, actions, menuLabel, menuDataTest, dataTest, className, }: {
|
|
298
|
+
declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, actions, menuLabel, menuId, menuDataTest, dataTest, className, }: {
|
|
280
299
|
/** Optional — omit to drop the hamburger (bottom-nav apps don't need one). */
|
|
281
300
|
onMenuClick?: () => void;
|
|
282
301
|
/** Leading button glyph — defaults to Menu; browse-style drawers can swap it. */
|
|
@@ -286,6 +305,7 @@ declare function SuiteMobileHeader({ onMenuClick, menuIcon: MenuIcon, title, act
|
|
|
286
305
|
/** Right-hand slot — search, bell, avatar (keep this order). */
|
|
287
306
|
actions?: ReactNode;
|
|
288
307
|
menuLabel?: string;
|
|
308
|
+
menuId?: string;
|
|
289
309
|
menuDataTest?: string;
|
|
290
310
|
dataTest?: string;
|
|
291
311
|
className?: string;
|
|
@@ -322,6 +342,8 @@ interface SuiteUserMenuProps {
|
|
|
322
342
|
/** Show the old desktop sidebar sign-out action beside the avatar. */
|
|
323
343
|
showSignOutAction?: boolean;
|
|
324
344
|
dataTest?: string;
|
|
345
|
+
triggerId?: string;
|
|
346
|
+
triggerDataTest?: string;
|
|
325
347
|
className?: string;
|
|
326
348
|
}
|
|
327
349
|
/**
|
|
@@ -329,13 +351,13 @@ interface SuiteUserMenuProps {
|
|
|
329
351
|
* profile settings and sign out. Desktop sidebars can also expose the legacy
|
|
330
352
|
* adjacent sign-out action without adding it to mobile chrome.
|
|
331
353
|
*/
|
|
332
|
-
declare function SuiteUserMenu({ name, email, image, settingsHref, onSignOut, fallbackInitials, showSignOutAction, dataTest, className, }: SuiteUserMenuProps): react.JSX.Element;
|
|
354
|
+
declare function SuiteUserMenu({ name, email, image, settingsHref, onSignOut, fallbackInitials, showSignOutAction, dataTest, triggerId, triggerDataTest, className, }: SuiteUserMenuProps): react.JSX.Element;
|
|
333
355
|
|
|
334
356
|
/** Any icon component that accepts sizing/stroke props (Lucide, theme icons). */
|
|
335
357
|
type SuiteNavIcon = ComponentType<{
|
|
336
358
|
className?: string;
|
|
337
359
|
strokeWidth?: number | string;
|
|
338
|
-
|
|
360
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
339
361
|
}>;
|
|
340
362
|
/**
|
|
341
363
|
* Suite bottom navigation — the mobile/tablet primary nav, identical in
|
|
@@ -348,6 +370,7 @@ interface SuiteBottomNavItem {
|
|
|
348
370
|
href: string;
|
|
349
371
|
label: string;
|
|
350
372
|
icon: SuiteNavIcon;
|
|
373
|
+
id?: string;
|
|
351
374
|
active?: boolean;
|
|
352
375
|
dataTest?: string;
|
|
353
376
|
}
|
|
@@ -788,6 +811,7 @@ interface SuiteSettingsNavItem {
|
|
|
788
811
|
label: string;
|
|
789
812
|
href: string;
|
|
790
813
|
icon: ElementType | ReactNode;
|
|
814
|
+
id?: string;
|
|
791
815
|
testId?: string;
|
|
792
816
|
}
|
|
793
817
|
interface SuiteSettingsMobileNavProps {
|
|
@@ -811,6 +835,8 @@ interface SuiteSidebarNavItem {
|
|
|
811
835
|
href: string;
|
|
812
836
|
label: string;
|
|
813
837
|
icon: SuiteNavIcon;
|
|
838
|
+
id?: string;
|
|
839
|
+
dataTest?: string;
|
|
814
840
|
active?: boolean;
|
|
815
841
|
onClick?: () => void;
|
|
816
842
|
badge?: ReactNode;
|
package/dist/suite.js
CHANGED
|
@@ -1266,13 +1266,17 @@ function AppSwitcher({
|
|
|
1266
1266
|
title,
|
|
1267
1267
|
collapsed = false,
|
|
1268
1268
|
dropdownMenu: DropdownMenu2,
|
|
1269
|
-
dropdownItem: DropdownItem2
|
|
1269
|
+
dropdownItem: DropdownItem2,
|
|
1270
|
+
triggerId,
|
|
1271
|
+
triggerDataTest
|
|
1270
1272
|
}) {
|
|
1271
1273
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
1272
1274
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1273
1275
|
DropdownMenu2,
|
|
1274
1276
|
{
|
|
1275
1277
|
"aria-label": "Switch application",
|
|
1278
|
+
triggerId: triggerId != null ? triggerId : "app-switcher-trigger",
|
|
1279
|
+
triggerDataTest: triggerDataTest != null ? triggerDataTest : "app-switcher-trigger",
|
|
1276
1280
|
className: collapsed ? "w-11 shrink-0" : "min-w-0 flex-1",
|
|
1277
1281
|
panelClassName: "w-64",
|
|
1278
1282
|
align: "start",
|
|
@@ -1294,11 +1298,12 @@ function AppSwitcher({
|
|
|
1294
1298
|
]
|
|
1295
1299
|
}
|
|
1296
1300
|
),
|
|
1297
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-1", "data-test": "app-switcher-menu", children: [
|
|
1301
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { id: "app-switcher-menu", className: "p-1", "data-test": "app-switcher-menu", children: [
|
|
1298
1302
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-ph-mutedtext", children: "Switch application" }),
|
|
1299
1303
|
apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1300
1304
|
DropdownItem2,
|
|
1301
1305
|
{
|
|
1306
|
+
id: `switch-app-${app.slug}`,
|
|
1302
1307
|
"data-test": `switch-app-${app.slug}`,
|
|
1303
1308
|
onMouseDown: (e) => e.preventDefault(),
|
|
1304
1309
|
onClick: () => {
|
|
@@ -1433,7 +1438,10 @@ function SuiteNotificationBell({
|
|
|
1433
1438
|
markRead,
|
|
1434
1439
|
markAllRead,
|
|
1435
1440
|
dropdownMenu: DropdownMenu2,
|
|
1436
|
-
cacheKey = "suite-notifications-cache"
|
|
1441
|
+
cacheKey = "suite-notifications-cache",
|
|
1442
|
+
dataTest = "suite-notifications",
|
|
1443
|
+
triggerId,
|
|
1444
|
+
triggerDataTest
|
|
1437
1445
|
}) {
|
|
1438
1446
|
const router = (0, import_navigation.useRouter)();
|
|
1439
1447
|
const [open, setOpen] = (0, import_react2.useState)(false);
|
|
@@ -1534,11 +1542,13 @@ function SuiteNotificationBell({
|
|
|
1534
1542
|
DropdownMenu2,
|
|
1535
1543
|
{
|
|
1536
1544
|
"aria-label": "Notifications",
|
|
1545
|
+
triggerId: triggerId != null ? triggerId : `${dataTest}-trigger`,
|
|
1546
|
+
triggerDataTest: triggerDataTest != null ? triggerDataTest : `${dataTest}-trigger`,
|
|
1537
1547
|
align: "end",
|
|
1538
1548
|
panelClassName: "w-80 overflow-hidden p-0",
|
|
1539
1549
|
open,
|
|
1540
1550
|
onOpenChange,
|
|
1541
|
-
trigger: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "relative inline-flex h-
|
|
1551
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
1542
1552
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_iconoir_react3.Bell, { className: "h-5 w-5", strokeWidth: 1.75, "aria-hidden": true }),
|
|
1543
1553
|
unread > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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
|
|
1544
1554
|
] }),
|
|
@@ -1549,6 +1559,8 @@ function SuiteNotificationBell({
|
|
|
1549
1559
|
"button",
|
|
1550
1560
|
{
|
|
1551
1561
|
type: "button",
|
|
1562
|
+
id: `${dataTest}-mark-all`,
|
|
1563
|
+
"data-test": `${dataTest}-mark-all`,
|
|
1552
1564
|
onClick: markAll,
|
|
1553
1565
|
className: "text-xs font-medium text-ph-brand hover:underline",
|
|
1554
1566
|
children: "Mark all read"
|
|
@@ -1559,6 +1571,8 @@ function SuiteNotificationBell({
|
|
|
1559
1571
|
"button",
|
|
1560
1572
|
{
|
|
1561
1573
|
type: "button",
|
|
1574
|
+
id: `${dataTest}-item-${n.id}`,
|
|
1575
|
+
"data-test": `${dataTest}-item-${n.id}`,
|
|
1562
1576
|
onClick: () => void openItem(n),
|
|
1563
1577
|
className: "flex w-full flex-col gap-0.5 px-3 py-2 text-left transition hover:bg-ph-muted",
|
|
1564
1578
|
children: [
|
|
@@ -1603,6 +1617,10 @@ function CommandPaletteHost({
|
|
|
1603
1617
|
items,
|
|
1604
1618
|
isAuthenticated = true,
|
|
1605
1619
|
placeholder = "Type a command or search\u2026",
|
|
1620
|
+
id,
|
|
1621
|
+
dataTest,
|
|
1622
|
+
inputId,
|
|
1623
|
+
inputDataTest,
|
|
1606
1624
|
commandPalette: CommandPalette
|
|
1607
1625
|
}) {
|
|
1608
1626
|
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
@@ -1623,7 +1641,11 @@ function CommandPaletteHost({
|
|
|
1623
1641
|
items,
|
|
1624
1642
|
isOpen: open,
|
|
1625
1643
|
onClose: () => setOpen(false),
|
|
1626
|
-
placeholder
|
|
1644
|
+
placeholder,
|
|
1645
|
+
id,
|
|
1646
|
+
dataTest,
|
|
1647
|
+
inputId,
|
|
1648
|
+
inputDataTest
|
|
1627
1649
|
}
|
|
1628
1650
|
);
|
|
1629
1651
|
}
|
|
@@ -1671,6 +1693,10 @@ function SuiteMobileDrawer({
|
|
|
1671
1693
|
durationMs = 200,
|
|
1672
1694
|
dataTest,
|
|
1673
1695
|
panelDataTest,
|
|
1696
|
+
backdropId,
|
|
1697
|
+
backdropDataTest,
|
|
1698
|
+
closeButtonId,
|
|
1699
|
+
closeButtonDataTest,
|
|
1674
1700
|
panelClassName
|
|
1675
1701
|
}) {
|
|
1676
1702
|
const [rendered, setRendered] = (0, import_react5.useState)(open);
|
|
@@ -1722,6 +1748,8 @@ function SuiteMobileDrawer({
|
|
|
1722
1748
|
"button",
|
|
1723
1749
|
{
|
|
1724
1750
|
type: "button",
|
|
1751
|
+
id: backdropId,
|
|
1752
|
+
"data-test": backdropDataTest,
|
|
1725
1753
|
tabIndex: -1,
|
|
1726
1754
|
className: cn(
|
|
1727
1755
|
"absolute inset-0 bg-black/25 backdrop-blur-sm motion-safe:transition-opacity motion-safe:ease-spring-subtle",
|
|
@@ -1762,6 +1790,8 @@ function SuiteMobileDrawer({
|
|
|
1762
1790
|
"button",
|
|
1763
1791
|
{
|
|
1764
1792
|
type: "button",
|
|
1793
|
+
id: closeButtonId,
|
|
1794
|
+
"data-test": closeButtonDataTest,
|
|
1765
1795
|
onClick: onClose,
|
|
1766
1796
|
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",
|
|
1767
1797
|
"aria-label": closeLabel,
|
|
@@ -1787,6 +1817,7 @@ function SuiteMobileHeader({
|
|
|
1787
1817
|
title,
|
|
1788
1818
|
actions,
|
|
1789
1819
|
menuLabel = "Open navigation",
|
|
1820
|
+
menuId,
|
|
1790
1821
|
menuDataTest,
|
|
1791
1822
|
dataTest,
|
|
1792
1823
|
className
|
|
@@ -1804,6 +1835,7 @@ function SuiteMobileHeader({
|
|
|
1804
1835
|
"button",
|
|
1805
1836
|
{
|
|
1806
1837
|
type: "button",
|
|
1838
|
+
id: menuId,
|
|
1807
1839
|
"data-test": menuDataTest,
|
|
1808
1840
|
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",
|
|
1809
1841
|
onClick: onMenuClick,
|
|
@@ -1943,7 +1975,7 @@ function SuitePageHeader({
|
|
|
1943
1975
|
"data-test": dataTest,
|
|
1944
1976
|
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1945
1977
|
className: cn(
|
|
1946
|
-
"flex items-start justify-between gap-4
|
|
1978
|
+
"flex min-w-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3",
|
|
1947
1979
|
// No extra pt here — page inset sets the shared title baseline.
|
|
1948
1980
|
// Stuck state adds pad via .suite-page-header-sticky[data-stuck].
|
|
1949
1981
|
sticky && "suite-page-header-sticky",
|
|
@@ -1967,7 +1999,7 @@ function SuitePageHeader({
|
|
|
1967
1999
|
"h1",
|
|
1968
2000
|
{
|
|
1969
2001
|
className: cn(
|
|
1970
|
-
"font-display text-[1.625rem] font-bold leading-none tracking-tight text-ph-ink sm:text-[2.25rem]",
|
|
2002
|
+
"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]",
|
|
1971
2003
|
titleClassName
|
|
1972
2004
|
),
|
|
1973
2005
|
children: title
|
|
@@ -1987,7 +2019,7 @@ function SuitePageHeader({
|
|
|
1987
2019
|
}
|
|
1988
2020
|
) : null
|
|
1989
2021
|
] }),
|
|
1990
|
-
actions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex
|
|
2022
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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
|
|
1991
2023
|
]
|
|
1992
2024
|
}
|
|
1993
2025
|
);
|
|
@@ -2148,7 +2180,14 @@ function DropdownContent({
|
|
|
2148
2180
|
sticky: "partial",
|
|
2149
2181
|
children: [
|
|
2150
2182
|
children,
|
|
2151
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2183
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2184
|
+
DropdownPrimitive.Arrow,
|
|
2185
|
+
{
|
|
2186
|
+
className: "ph-dropdown-arrow",
|
|
2187
|
+
width: 12,
|
|
2188
|
+
height: 6
|
|
2189
|
+
}
|
|
2190
|
+
)
|
|
2152
2191
|
]
|
|
2153
2192
|
}
|
|
2154
2193
|
) });
|
|
@@ -2156,6 +2195,8 @@ function DropdownContent({
|
|
|
2156
2195
|
function DropdownMenu(_a) {
|
|
2157
2196
|
var _b = _a, {
|
|
2158
2197
|
trigger,
|
|
2198
|
+
triggerId,
|
|
2199
|
+
triggerDataTest,
|
|
2159
2200
|
children,
|
|
2160
2201
|
align,
|
|
2161
2202
|
side,
|
|
@@ -2173,6 +2214,8 @@ function DropdownMenu(_a) {
|
|
|
2173
2214
|
disabled
|
|
2174
2215
|
} = _b, props = __objRest(_b, [
|
|
2175
2216
|
"trigger",
|
|
2217
|
+
"triggerId",
|
|
2218
|
+
"triggerDataTest",
|
|
2176
2219
|
"children",
|
|
2177
2220
|
"align",
|
|
2178
2221
|
"side",
|
|
@@ -2197,7 +2240,17 @@ function DropdownMenu(_a) {
|
|
|
2197
2240
|
onOpenChange,
|
|
2198
2241
|
modal,
|
|
2199
2242
|
children: [
|
|
2200
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Trigger, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Trigger, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2244
|
+
"button",
|
|
2245
|
+
{
|
|
2246
|
+
type: "button",
|
|
2247
|
+
id: triggerId,
|
|
2248
|
+
"data-test": triggerDataTest,
|
|
2249
|
+
className: "ph-dropdown-trigger",
|
|
2250
|
+
"aria-label": ariaLabel,
|
|
2251
|
+
children: trigger
|
|
2252
|
+
}
|
|
2253
|
+
) }),
|
|
2201
2254
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2202
2255
|
DropdownContent,
|
|
2203
2256
|
{
|
|
@@ -2216,7 +2269,15 @@ function DropdownMenu(_a) {
|
|
|
2216
2269
|
) }));
|
|
2217
2270
|
}
|
|
2218
2271
|
function DropdownItem(_a) {
|
|
2219
|
-
var _b = _a, {
|
|
2272
|
+
var _b = _a, {
|
|
2273
|
+
className,
|
|
2274
|
+
children,
|
|
2275
|
+
disabled
|
|
2276
|
+
} = _b, props = __objRest(_b, [
|
|
2277
|
+
"className",
|
|
2278
|
+
"children",
|
|
2279
|
+
"disabled"
|
|
2280
|
+
]);
|
|
2220
2281
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Item, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2221
2282
|
"button",
|
|
2222
2283
|
__spreadProps(__spreadValues({
|
|
@@ -2244,6 +2305,8 @@ function SuiteUserMenu({
|
|
|
2244
2305
|
fallbackInitials,
|
|
2245
2306
|
showSignOutAction = false,
|
|
2246
2307
|
dataTest = "suite-user-menu",
|
|
2308
|
+
triggerId,
|
|
2309
|
+
triggerDataTest,
|
|
2247
2310
|
className
|
|
2248
2311
|
}) {
|
|
2249
2312
|
const router = (0, import_navigation2.useRouter)();
|
|
@@ -2263,6 +2326,8 @@ function SuiteUserMenu({
|
|
|
2263
2326
|
DropdownMenu,
|
|
2264
2327
|
{
|
|
2265
2328
|
trigger: avatar,
|
|
2329
|
+
triggerId: triggerId != null ? triggerId : `${dataTest}-trigger`,
|
|
2330
|
+
triggerDataTest: triggerDataTest != null ? triggerDataTest : `${dataTest}-trigger`,
|
|
2266
2331
|
"aria-label": "Account menu",
|
|
2267
2332
|
align: "end",
|
|
2268
2333
|
side: "bottom",
|
|
@@ -2363,6 +2428,7 @@ function SuiteBottomNav({
|
|
|
2363
2428
|
import_link.default,
|
|
2364
2429
|
{
|
|
2365
2430
|
href: item.href,
|
|
2431
|
+
id: item.id,
|
|
2366
2432
|
"data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
2367
2433
|
"aria-current": active ? "page" : void 0,
|
|
2368
2434
|
className: cn(
|
|
@@ -3260,6 +3326,7 @@ function SuiteSettingsMobileNav({
|
|
|
3260
3326
|
"button",
|
|
3261
3327
|
{
|
|
3262
3328
|
type: "button",
|
|
3329
|
+
id: item.id,
|
|
3263
3330
|
"data-test": item.testId,
|
|
3264
3331
|
onClick: () => onSelect(item.href),
|
|
3265
3332
|
"aria-current": active ? "page" : void 0,
|
|
@@ -3472,19 +3539,21 @@ function SuiteSidebar({
|
|
|
3472
3539
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("nav", { "aria-label": "Pages", className: "shrink-0 space-y-0.5", children: [
|
|
3473
3540
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
|
|
3474
3541
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "space-y-0.5", children: navItems.map((item) => {
|
|
3542
|
+
var _a;
|
|
3475
3543
|
const Icon = item.icon;
|
|
3476
3544
|
const active = Boolean(item.active);
|
|
3477
3545
|
const link = /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3478
3546
|
import_link2.default,
|
|
3479
3547
|
{
|
|
3480
3548
|
href: item.href,
|
|
3481
|
-
|
|
3549
|
+
id: item.id,
|
|
3550
|
+
"data-test": (_a = item.dataTest) != null ? _a : "nav-link",
|
|
3482
3551
|
"aria-current": active ? "page" : void 0,
|
|
3483
3552
|
onClick: item.onClick,
|
|
3484
3553
|
className: cn(
|
|
3485
|
-
"group relative flex items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
|
|
3554
|
+
"group relative flex min-h-11 touch-manipulation items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
|
|
3486
3555
|
active ? "bg-ph-muted" : "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
|
|
3487
|
-
collapsed ? "mx-auto size-
|
|
3556
|
+
collapsed ? "mx-auto size-11 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
3488
3557
|
),
|
|
3489
3558
|
children: [
|
|
3490
3559
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
@@ -3582,7 +3651,7 @@ function SuiteAppLayout({
|
|
|
3582
3651
|
{
|
|
3583
3652
|
"data-test": "app-shell",
|
|
3584
3653
|
className: cn(
|
|
3585
|
-
"suite-app-layout flex
|
|
3654
|
+
"suite-app-layout flex h-dvh overflow-hidden",
|
|
3586
3655
|
className
|
|
3587
3656
|
),
|
|
3588
3657
|
children: [
|