@xenide-io/the-old-ui-theme 0.9.17 → 0.10.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/{Chip-BzuNgJIa.d.mts → Chip-DKT-82Lf.d.mts} +5 -3
- package/dist/{Chip-BzuNgJIa.d.ts → Chip-DKT-82Lf.d.ts} +5 -3
- package/dist/{chunk-6SVJAU5K.mjs → chunk-LHE4ROON.mjs} +977 -521
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +138 -99
- package/dist/index.mjs +1 -1
- package/dist/suite.d.mts +23 -1
- package/dist/suite.d.ts +23 -1
- package/dist/suite.js +4250 -4041
- package/dist/suite.mjs +1008 -795
- package/dist/tailwind-preset.js +10 -1
- package/dist/tailwind-preset.mjs +10 -1
- package/dist/ui.d.mts +33 -4
- package/dist/ui.d.ts +33 -4
- package/dist/ui.js +1024 -566
- package/dist/ui.mjs +13 -1
- package/docs/macos-identity-audit.md +279 -0
- package/package.json +1 -1
- package/src/app/globals.css +334 -44
- package/src/components/ui/Accordion.tsx +4 -7
- package/src/components/ui/Avatar.tsx +5 -5
- package/src/components/ui/Calendar.tsx +7 -7
- package/src/components/ui/CodeBlock.tsx +3 -10
- package/src/components/ui/CollapsibleSection.tsx +4 -4
- package/src/components/ui/CommandPalette.tsx +7 -10
- package/src/components/ui/EmptyState.tsx +2 -2
- package/src/components/ui/Input.tsx +1 -1
- package/src/components/ui/Marketing.tsx +128 -0
- package/src/components/ui/MarketingIllustrations.tsx +287 -0
- package/src/components/ui/Panel.tsx +1 -1
- package/src/components/ui/SegmentedControl.tsx +59 -13
- package/src/components/ui/ShowcaseWrapper.tsx +3 -3
- package/src/components/ui/Table.tsx +18 -6
- package/src/components/ui/Typography.tsx +4 -4
- package/src/components/ui/avatar-stat.test.tsx +14 -1
- package/src/components/ui/index.ts +13 -12
- package/src/components/ui/interaction-primitives.test.tsx +12 -6
- package/src/components/ui/marketing.test.tsx +39 -0
- package/src/components/ui/table.test.tsx +20 -0
- package/src/styles/suite-skin.css +405 -40
- package/src/styles/themes.css +45 -45
- package/src/styles/typography.css +25 -1
- package/src/suite/components/ai-panel.tsx +17 -17
- package/src/suite/components/app-switcher.tsx +9 -9
- package/src/suite/components/suite-app-layout.tsx +7 -4
- package/src/suite/components/suite-bottom-nav.tsx +1 -1
- package/src/suite/components/suite-clients-projects-directory.tsx +6 -6
- package/src/suite/components/suite-entity-icon.tsx +3 -3
- package/src/suite/components/suite-integration-picker.tsx +7 -7
- package/src/suite/components/suite-integration-rules.tsx +5 -5
- package/src/suite/components/suite-layout.test.tsx +32 -3
- package/src/suite/components/suite-layout.tsx +4 -4
- package/src/suite/components/suite-mobile-drawer.tsx +2 -2
- package/src/suite/components/suite-mobile-header.tsx +1 -1
- package/src/suite/components/suite-notification-bell.tsx +4 -4
- package/src/suite/components/suite-notification-settings.tsx +171 -0
- package/src/suite/components/suite-palette-library.test.tsx +46 -0
- package/src/suite/components/suite-palette-library.tsx +82 -15
- package/src/suite/components/suite-settings-layout.tsx +2 -2
- package/src/suite/components/suite-settings-mobile-nav.tsx +5 -9
- package/src/suite/components/suite-sidebar.test.tsx +39 -0
- package/src/suite/components/suite-sidebar.tsx +41 -19
- package/src/suite/components/suite-skeleton.tsx +6 -6
- package/src/suite/components/suite-user-menu.tsx +2 -2
- package/src/suite/components/today-calibrating.tsx +3 -3
- package/src/suite/components/today-ui.tsx +12 -12
- package/src/suite/components/workspace-switcher.tsx +3 -3
- package/src/suite/index.ts +6 -0
- package/tailwind-preset.ts +9 -0
|
@@ -530,7 +530,7 @@ export function SuiteAiPanel({
|
|
|
530
530
|
type="button"
|
|
531
531
|
onClick={() => void handleClear()}
|
|
532
532
|
disabled={waiting}
|
|
533
|
-
className="
|
|
533
|
+
className="ph-btn ph-btn-ghost ph-btn-sm ml-auto h-9 text-xs text-ph-subtle"
|
|
534
534
|
data-test="ask-ai-clear"
|
|
535
535
|
>
|
|
536
536
|
<Erase className="h-3.5 w-3.5" />
|
|
@@ -558,7 +558,7 @@ export function SuiteAiPanel({
|
|
|
558
558
|
|
|
559
559
|
{!hydrating && messages.length === 0 && !error ? (
|
|
560
560
|
<div className="mx-auto mt-4 flex max-w-sm flex-col items-center px-1 text-center">
|
|
561
|
-
<span className="flex h-10 w-10 items-center justify-center rounded-
|
|
561
|
+
<span className="flex h-10 w-10 items-center justify-center rounded-[var(--ph-radius-surface)] bg-ph-brand/10 text-ph-brand">
|
|
562
562
|
<Icon className="h-5 w-5" />
|
|
563
563
|
</span>
|
|
564
564
|
<p className="mt-3 font-display text-base font-semibold text-ph-ink">
|
|
@@ -575,7 +575,7 @@ export function SuiteAiPanel({
|
|
|
575
575
|
type="button"
|
|
576
576
|
onClick={() => void ask(preset.prompt)}
|
|
577
577
|
disabled={waiting || hydrating}
|
|
578
|
-
className="group flex w-full items-center gap-2 rounded-
|
|
578
|
+
className="group flex w-full items-center gap-2 rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface px-3 py-2 text-left text-sm text-ph-ink transition-[background-color,border-color,box-shadow] hover:border-[var(--ph-selected-border)] hover:bg-[var(--ph-surface-hover)] focus-visible:outline-none focus-visible:shadow-[var(--ph-focus-halo)] disabled:opacity-40"
|
|
579
579
|
>
|
|
580
580
|
<Sparks className="h-4 w-4 shrink-0 text-ph-brand" />
|
|
581
581
|
<span className="min-w-0 flex-1 truncate">
|
|
@@ -620,7 +620,7 @@ export function SuiteAiPanel({
|
|
|
620
620
|
}}
|
|
621
621
|
rows={2}
|
|
622
622
|
data-test="ask-ai-edit-input"
|
|
623
|
-
className="w-full resize-none rounded-2xl rounded-br-md border border-ph-border bg-ph-surface px-3 py-2 text-sm leading-relaxed text-ph-ink outline-none focus-visible:border-ph-
|
|
623
|
+
className="w-full resize-none rounded-2xl rounded-br-md border border-ph-border bg-ph-surface px-3 py-2 text-sm leading-relaxed text-ph-ink outline-none focus-visible:border-[var(--ph-selected-border)] focus-visible:shadow-[var(--ph-focus-halo)]"
|
|
624
624
|
/>
|
|
625
625
|
<div className="flex justify-end gap-2">
|
|
626
626
|
<button
|
|
@@ -629,7 +629,7 @@ export function SuiteAiPanel({
|
|
|
629
629
|
setEditingIndex(null);
|
|
630
630
|
setEditDraft("");
|
|
631
631
|
}}
|
|
632
|
-
className="
|
|
632
|
+
className="ph-btn ph-btn-secondary ph-btn-xs"
|
|
633
633
|
>
|
|
634
634
|
Cancel
|
|
635
635
|
</button>
|
|
@@ -638,7 +638,7 @@ export function SuiteAiPanel({
|
|
|
638
638
|
data-test="ask-ai-edit-save"
|
|
639
639
|
disabled={!editDraft.trim() || waiting}
|
|
640
640
|
onClick={() => void saveEdit(index)}
|
|
641
|
-
className="
|
|
641
|
+
className="ph-btn ph-btn-primary ph-btn-xs"
|
|
642
642
|
>
|
|
643
643
|
Save
|
|
644
644
|
</button>
|
|
@@ -663,7 +663,7 @@ export function SuiteAiPanel({
|
|
|
663
663
|
copiedIndex === index ? "Copied" : "Copy message"
|
|
664
664
|
}
|
|
665
665
|
data-test="ask-ai-copy"
|
|
666
|
-
className="
|
|
666
|
+
className="ph-btn ph-btn-ghost ph-btn-square ph-btn-xs h-7 w-7 text-ph-mutedtext"
|
|
667
667
|
>
|
|
668
668
|
{copiedIndex === index ? (
|
|
669
669
|
<Check className="h-3.5 w-3.5" />
|
|
@@ -679,7 +679,7 @@ export function SuiteAiPanel({
|
|
|
679
679
|
}}
|
|
680
680
|
aria-label="Edit message"
|
|
681
681
|
data-test="ask-ai-edit"
|
|
682
|
-
className="
|
|
682
|
+
className="ph-btn ph-btn-ghost ph-btn-square ph-btn-xs h-7 w-7 text-ph-mutedtext"
|
|
683
683
|
>
|
|
684
684
|
<EditPencil className="h-3.5 w-3.5" />
|
|
685
685
|
</button>
|
|
@@ -727,7 +727,7 @@ export function SuiteAiPanel({
|
|
|
727
727
|
key={action.id}
|
|
728
728
|
data-test="ask-ai-action"
|
|
729
729
|
data-status={action.status}
|
|
730
|
-
className="rounded-
|
|
730
|
+
className="rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface px-3 py-2 text-sm text-ph-ink"
|
|
731
731
|
>
|
|
732
732
|
<p className="font-medium">{action.summary}</p>
|
|
733
733
|
{action.status === "proposed" ? (
|
|
@@ -737,7 +737,7 @@ export function SuiteAiPanel({
|
|
|
737
737
|
data-test="ask-ai-action-confirm"
|
|
738
738
|
disabled={Boolean(resolvingId) || !resolveAction}
|
|
739
739
|
onClick={() => void handleResolve(action.id, "confirm")}
|
|
740
|
-
className="
|
|
740
|
+
className="ph-btn ph-btn-primary ph-btn-xs"
|
|
741
741
|
>
|
|
742
742
|
{resolvingId === action.id ? "Working…" : "Confirm"}
|
|
743
743
|
</button>
|
|
@@ -746,7 +746,7 @@ export function SuiteAiPanel({
|
|
|
746
746
|
data-test="ask-ai-action-cancel"
|
|
747
747
|
disabled={Boolean(resolvingId) || !resolveAction}
|
|
748
748
|
onClick={() => void handleResolve(action.id, "cancel")}
|
|
749
|
-
className="
|
|
749
|
+
className="ph-btn ph-btn-secondary ph-btn-xs"
|
|
750
750
|
>
|
|
751
751
|
Cancel
|
|
752
752
|
</button>
|
|
@@ -805,7 +805,7 @@ export function SuiteAiPanel({
|
|
|
805
805
|
{error ? (
|
|
806
806
|
<div
|
|
807
807
|
role="alert"
|
|
808
|
-
className="flex items-start gap-2 rounded-
|
|
808
|
+
className="flex items-start gap-2 rounded-[var(--ph-radius-surface)] border border-ph-danger/30 bg-ph-danger/10 px-3 py-2.5 text-sm text-ph-ink"
|
|
809
809
|
>
|
|
810
810
|
<WarningTriangle className="mt-0.5 h-4 w-4 shrink-0 text-ph-danger" />
|
|
811
811
|
<div className="min-w-0 flex-1">
|
|
@@ -815,7 +815,7 @@ export function SuiteAiPanel({
|
|
|
815
815
|
type="button"
|
|
816
816
|
onClick={retry}
|
|
817
817
|
disabled={waiting}
|
|
818
|
-
className="
|
|
818
|
+
className="ph-btn ph-btn-secondary ph-btn-xs mt-2 gap-1.5"
|
|
819
819
|
>
|
|
820
820
|
Try again
|
|
821
821
|
</button>
|
|
@@ -830,7 +830,7 @@ export function SuiteAiPanel({
|
|
|
830
830
|
<button
|
|
831
831
|
type="button"
|
|
832
832
|
onClick={() => scrollToBottom("smooth")}
|
|
833
|
-
className="
|
|
833
|
+
className="ph-btn ph-btn-ghost ph-btn-circle h-9 w-9 border border-ph-border bg-ph-surface text-ph-subtle shadow-[var(--ph-shadow-floating)]"
|
|
834
834
|
aria-label="Scroll to latest"
|
|
835
835
|
>
|
|
836
836
|
<ArrowDown className="h-4 w-4" />
|
|
@@ -841,7 +841,7 @@ export function SuiteAiPanel({
|
|
|
841
841
|
</div>
|
|
842
842
|
|
|
843
843
|
<div className="px-2 pt-2 pb-[max(2rem,calc(env(safe-area-inset-bottom)+1rem))]">
|
|
844
|
-
<div className="flex items-end gap-1.5
|
|
844
|
+
<div className="suite-ai-composer flex items-end gap-1.5 border bg-ph-surface px-1.5 py-1">
|
|
845
845
|
<label htmlFor={inputId} className="sr-only">
|
|
846
846
|
Ask a question
|
|
847
847
|
</label>
|
|
@@ -871,7 +871,7 @@ export function SuiteAiPanel({
|
|
|
871
871
|
type="button"
|
|
872
872
|
onClick={stop}
|
|
873
873
|
data-test="ask-ai-stop"
|
|
874
|
-
className="
|
|
874
|
+
className="ph-btn ph-btn-ghost ph-btn-circle h-9 w-9 shrink-0 bg-ph-muted text-ph-ink"
|
|
875
875
|
aria-label="Stop generating"
|
|
876
876
|
>
|
|
877
877
|
<Square className="h-3.5 w-3.5 fill-current" />
|
|
@@ -884,7 +884,7 @@ export function SuiteAiPanel({
|
|
|
884
884
|
onClick={() => void ask(prompt)}
|
|
885
885
|
disabled={!prompt.trim()}
|
|
886
886
|
data-test="ask-ai-send"
|
|
887
|
-
className="
|
|
887
|
+
className="ph-btn ph-btn-primary ph-btn-circle h-9 w-9 shrink-0"
|
|
888
888
|
aria-label="Send message"
|
|
889
889
|
>
|
|
890
890
|
<ArrowUp className="h-4 w-4" />
|
|
@@ -12,20 +12,20 @@ import type {
|
|
|
12
12
|
|
|
13
13
|
export function appSwitcherTriggerClass(open: boolean, collapsed = false) {
|
|
14
14
|
return cn(
|
|
15
|
-
"group flex min-w-0 items-center gap-2 rounded-
|
|
15
|
+
"group flex min-w-0 items-center gap-2 rounded-[var(--ph-radius-control)] border px-2 py-1.5 text-left transition-[color,background-color,border-color,box-shadow] duration-150",
|
|
16
16
|
collapsed ? "h-11 w-11 justify-center px-0 py-0" : "w-full",
|
|
17
17
|
open
|
|
18
|
-
? "border-ph-
|
|
19
|
-
: "border-transparent hover:border-ph-border hover:bg-ph-
|
|
18
|
+
? "border-[var(--ph-selected-border)] bg-[var(--ph-selected-bg)] shadow-[var(--ph-shadow-control)]"
|
|
19
|
+
: "border-transparent hover:border-ph-border hover:bg-[var(--ph-surface-hover)]",
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function appSwitcherMarkClass() {
|
|
24
|
-
return "h-8 w-8 shrink-0 rounded-
|
|
24
|
+
return "h-8 w-8 shrink-0 rounded-[var(--ph-radius-control)]";
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export function appSwitcherMenuItemClass() {
|
|
28
|
-
return "
|
|
28
|
+
return "px-2 py-2";
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export function AppSwitcherMark({
|
|
@@ -58,7 +58,7 @@ export function AppSwitcherChevron({
|
|
|
58
58
|
return (
|
|
59
59
|
<span
|
|
60
60
|
className={cn(
|
|
61
|
-
"absolute bottom-0 right-0 flex h-3 w-3 items-center justify-center rounded-full border border-ph-border bg-ph-surface
|
|
61
|
+
"absolute bottom-0 right-0 flex h-3 w-3 items-center justify-center rounded-full border border-ph-border bg-ph-surface transition-colors",
|
|
62
62
|
open && "border-ph-brand/40 bg-ph-brand/10",
|
|
63
63
|
)}
|
|
64
64
|
aria-hidden
|
|
@@ -76,7 +76,7 @@ export function AppSwitcherChevron({
|
|
|
76
76
|
return (
|
|
77
77
|
<span
|
|
78
78
|
className={cn(
|
|
79
|
-
"border-ph-border/80 flex h-5 w-5 shrink-0 items-center justify-center rounded-
|
|
79
|
+
"border-ph-border/80 flex h-5 w-5 shrink-0 items-center justify-center rounded-[var(--ph-radius-control)] border bg-ph-canvas transition-[color,background-color,border-color] duration-150",
|
|
80
80
|
open
|
|
81
81
|
? "border-ph-brand/35 bg-ph-brand/10 text-ph-brand"
|
|
82
82
|
: "text-ph-mutedtext group-hover:border-ph-border group-hover:bg-ph-surface",
|
|
@@ -160,7 +160,7 @@ export function AppSwitcher({
|
|
|
160
160
|
}
|
|
161
161
|
>
|
|
162
162
|
<div id="app-switcher-menu" className="p-1" data-test="app-switcher-menu">
|
|
163
|
-
<p className="px-3 py-2 text-[
|
|
163
|
+
<p className="px-3 py-2 text-[length:var(--ph-type-overline)] font-semibold uppercase tracking-[0.08em] text-ph-mutedtext">
|
|
164
164
|
Switch application
|
|
165
165
|
</p>
|
|
166
166
|
{apps
|
|
@@ -204,7 +204,7 @@ export function AppSwitcher({
|
|
|
204
204
|
setOpen(false);
|
|
205
205
|
onSelect(app, { newTab: true });
|
|
206
206
|
}}
|
|
207
|
-
className="absolute right-1.5 top-1/2 z-[1] flex h-8 -translate-y-1/2 justify-center
|
|
207
|
+
className="absolute right-1.5 top-1/2 z-[1] flex h-8 -translate-y-1/2 justify-center p-0 text-ph-mutedtext"
|
|
208
208
|
style={{ width: "2rem" }}
|
|
209
209
|
>
|
|
210
210
|
<OpenNewWindow className="h-4 w-4" aria-hidden="true" />
|
|
@@ -59,7 +59,7 @@ export function SuiteAppLayout({
|
|
|
59
59
|
>
|
|
60
60
|
<aside
|
|
61
61
|
aria-label="Sidebar"
|
|
62
|
-
className="relative hidden shrink-0 flex-col overflow-visible border-r
|
|
62
|
+
className="suite-app-layout__sidebar relative hidden shrink-0 flex-col overflow-visible border-r ease-out lg:flex"
|
|
63
63
|
style={{ width: `${sidebarWidth}px` }}
|
|
64
64
|
data-collapsed={collapsed ? "true" : "false"}
|
|
65
65
|
>
|
|
@@ -81,7 +81,10 @@ export function SuiteAppLayout({
|
|
|
81
81
|
onKeyDown={(event) => {
|
|
82
82
|
if (event.key === "Home") {
|
|
83
83
|
event.preventDefault();
|
|
84
|
-
|
|
84
|
+
onResizeBy?.(SIDEBAR_RAIL_WIDTH - sidebarWidth);
|
|
85
|
+
} else if (event.key === "End") {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
onResizeBy?.(SIDEBAR_MAX_WIDTH - sidebarWidth);
|
|
85
88
|
} else if (event.key === "ArrowLeft") {
|
|
86
89
|
event.preventDefault();
|
|
87
90
|
onResizeBy?.(-16);
|
|
@@ -90,7 +93,7 @@ export function SuiteAppLayout({
|
|
|
90
93
|
onResizeBy?.(16);
|
|
91
94
|
}
|
|
92
95
|
}}
|
|
93
|
-
className="absolute inset-y-0 right-0 z-20 w-2 cursor-col-resize touch-none
|
|
96
|
+
className="suite-sidebar-resize-handle absolute inset-y-0 right-0 z-20 w-2 cursor-col-resize touch-none before:absolute before:-left-2 before:-right-2 before:inset-y-0 before:content-['']"
|
|
94
97
|
/>
|
|
95
98
|
) : null}
|
|
96
99
|
</aside>
|
|
@@ -104,7 +107,7 @@ export function SuiteAppLayout({
|
|
|
104
107
|
tabIndex={0}
|
|
105
108
|
data-lock-scroll={lockMainScroll ? "true" : undefined}
|
|
106
109
|
className={cn(
|
|
107
|
-
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none
|
|
110
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
108
111
|
"suite-app-layout__main",
|
|
109
112
|
lockMainScroll ? "overflow-hidden" : "overflow-y-auto",
|
|
110
113
|
)}
|
|
@@ -89,7 +89,7 @@ export function SuiteBottomNav({
|
|
|
89
89
|
}
|
|
90
90
|
aria-current={active ? "page" : undefined}
|
|
91
91
|
className={cn(
|
|
92
|
-
"suite-bottom-nav__item relative flex min-h-[60px] min-w-0 flex-col items-center justify-center gap-1 px-1 pb-1.5 pt-2 text-[
|
|
92
|
+
"suite-bottom-nav__item relative flex min-h-[60px] min-w-0 flex-col items-center justify-center gap-1 px-1 pb-1.5 pt-2 text-[length:var(--ph-type-overline)] font-medium leading-none text-ph-mutedtext transition-colors duration-200 focus-visible:outline-none focus-visible:shadow-[inset_0_0_0_3px_color-mix(in_oklab,var(--ph-focus-ring)_30%,transparent)] motion-reduce:transition-none",
|
|
93
93
|
active && "font-semibold text-ph-brand",
|
|
94
94
|
)}
|
|
95
95
|
>
|
|
@@ -117,7 +117,7 @@ function DirectoryIconPicker({
|
|
|
117
117
|
return (
|
|
118
118
|
<div className="space-y-2">
|
|
119
119
|
<span className="mb-1.5 block text-sm font-medium text-ph-ink">Icon</span>
|
|
120
|
-
<div className="rounded-
|
|
120
|
+
<div className="rounded-[var(--ph-radius-surface)] border border-ph-border bg-[var(--ph-surface-inset)] p-3">
|
|
121
121
|
<div className="flex items-center gap-3">
|
|
122
122
|
<SuiteEntityIcon
|
|
123
123
|
imageUrl={preview}
|
|
@@ -178,7 +178,7 @@ function DirectoryIcon({
|
|
|
178
178
|
color={item.color}
|
|
179
179
|
tinted
|
|
180
180
|
className="h-8 w-8 text-sm"
|
|
181
|
-
roundedClass="rounded-
|
|
181
|
+
roundedClass="rounded-[var(--ph-radius-control)]"
|
|
182
182
|
/>
|
|
183
183
|
);
|
|
184
184
|
}
|
|
@@ -458,7 +458,7 @@ export function SuiteClientsProjectsDirectory({
|
|
|
458
458
|
{loading ? (
|
|
459
459
|
<p className="text-sm text-ph-mutedtext">Loading directory...</p>
|
|
460
460
|
) : (
|
|
461
|
-
<div className="overflow-hidden rounded-
|
|
461
|
+
<div className="overflow-hidden rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface lg:grid lg:min-h-[22rem] lg:grid-cols-[minmax(14rem,18rem)_1fr]">
|
|
462
462
|
<section
|
|
463
463
|
className={cn(
|
|
464
464
|
"border-ph-border lg:border-r",
|
|
@@ -515,7 +515,7 @@ export function SuiteClientsProjectsDirectory({
|
|
|
515
515
|
clientButtonRefs.current[client.id] = element;
|
|
516
516
|
}}
|
|
517
517
|
className={cn(
|
|
518
|
-
"flex w-full items-center gap-2.5 rounded-
|
|
518
|
+
"flex w-full items-center gap-2.5 rounded-[var(--ph-radius-control)] px-2.5 py-2 text-left",
|
|
519
519
|
selected ? "bg-ph-muted" : "hover:bg-ph-canvas",
|
|
520
520
|
)}
|
|
521
521
|
>
|
|
@@ -627,12 +627,12 @@ export function SuiteClientsProjectsDirectory({
|
|
|
627
627
|
selectedProjects.map((project) => (
|
|
628
628
|
<li key={project.id}>
|
|
629
629
|
<div
|
|
630
|
-
className="flex items-center gap-3 rounded-
|
|
630
|
+
className="flex items-center gap-3 rounded-[var(--ph-radius-control)] px-2 py-1 hover:bg-ph-canvas"
|
|
631
631
|
onClick={() => openEdit(project, "project")}
|
|
632
632
|
>
|
|
633
633
|
<button
|
|
634
634
|
type="button"
|
|
635
|
-
className="flex min-w-0 flex-1 items-center gap-3 rounded-
|
|
635
|
+
className="flex min-w-0 flex-1 items-center gap-3 rounded-[var(--ph-radius-control)] py-1 text-left focus-visible:outline-none focus-visible:shadow-[var(--ph-focus-halo)]"
|
|
636
636
|
onClick={() => openEdit(project, "project")}
|
|
637
637
|
>
|
|
638
638
|
<DirectoryIcon item={project} />
|
|
@@ -50,7 +50,7 @@ export function SuiteEntityIcon({
|
|
|
50
50
|
}}
|
|
51
51
|
>
|
|
52
52
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
53
|
-
<img src={src ?? undefined} alt="" className="h-full w-full object-
|
|
53
|
+
<img src={src ?? undefined} alt="" className="h-full w-full object-contain" />
|
|
54
54
|
</span>
|
|
55
55
|
);
|
|
56
56
|
}
|
|
@@ -71,8 +71,8 @@ export function SuiteEntityIcon({
|
|
|
71
71
|
title={label ?? undefined}
|
|
72
72
|
>
|
|
73
73
|
<Folder
|
|
74
|
-
className="h-[
|
|
75
|
-
strokeWidth={1.
|
|
74
|
+
className="h-[88%] w-[88%]"
|
|
75
|
+
strokeWidth={1.8}
|
|
76
76
|
aria-hidden
|
|
77
77
|
/>
|
|
78
78
|
</span>
|
|
@@ -91,7 +91,7 @@ const DESCRIPTION_LIMIT = 90;
|
|
|
91
91
|
function IntegrationSkeletonCard() {
|
|
92
92
|
return (
|
|
93
93
|
<div
|
|
94
|
-
className="flex min-h-36 min-w-0 animate-pulse flex-col justify-between rounded-
|
|
94
|
+
className="flex min-h-36 min-w-0 animate-pulse flex-col justify-between rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface p-4"
|
|
95
95
|
aria-hidden="true"
|
|
96
96
|
>
|
|
97
97
|
<div className="flex items-start gap-3">
|
|
@@ -608,7 +608,7 @@ export function SuiteIntegrationPicker({
|
|
|
608
608
|
</button>
|
|
609
609
|
{categoryMenuOpen ? (
|
|
610
610
|
<div
|
|
611
|
-
className="absolute z-20 mt-2 max-h-[min(22rem,calc(100dvh-12rem))] w-full max-w-full overflow-hidden rounded-
|
|
611
|
+
className="absolute z-20 mt-2 max-h-[min(22rem,calc(100dvh-12rem))] w-full max-w-full overflow-hidden rounded-[var(--ph-radius-overlay)] border border-[var(--ph-border-control)] bg-[var(--ph-surface-overlay)] p-2 shadow-[var(--ph-shadow-floating)]"
|
|
612
612
|
>
|
|
613
613
|
<Input
|
|
614
614
|
ref={categorySearchRef}
|
|
@@ -643,7 +643,7 @@ export function SuiteIntegrationPicker({
|
|
|
643
643
|
ref={(element) => {
|
|
644
644
|
categoryOptionRefs.current[value] = element;
|
|
645
645
|
}}
|
|
646
|
-
className={`flex w-full min-w-0 items-center rounded-
|
|
646
|
+
className={`flex w-full min-w-0 items-center rounded-[var(--ph-radius-control)] px-3 py-2 text-left text-sm break-words focus-visible:outline-none focus-visible:shadow-[var(--ph-focus-halo)] ${activeCategory === value ? "bg-[var(--ph-selected-bg)] text-[var(--ph-selected-text)] shadow-[inset_0_0_0_1px_var(--ph-selected-border)]" : "text-ph-ink hover:bg-[var(--ph-surface-hover)]"}`}
|
|
647
647
|
onClick={() => selectCategory(value)}
|
|
648
648
|
onKeyDown={(event) => {
|
|
649
649
|
if (event.key === "Escape") {
|
|
@@ -692,7 +692,7 @@ export function SuiteIntegrationPicker({
|
|
|
692
692
|
return (
|
|
693
693
|
<div
|
|
694
694
|
key={item.id}
|
|
695
|
-
className="flex min-h-36 min-w-0 flex-col justify-between rounded-
|
|
695
|
+
className="flex min-h-36 min-w-0 flex-col justify-between rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface p-4"
|
|
696
696
|
>
|
|
697
697
|
<button
|
|
698
698
|
type="button"
|
|
@@ -701,7 +701,7 @@ export function SuiteIntegrationPicker({
|
|
|
701
701
|
longDescription &&
|
|
702
702
|
setExpanded(isExpanded ? null : item.id)
|
|
703
703
|
}
|
|
704
|
-
aria-expanded={isExpanded}
|
|
704
|
+
aria-expanded={longDescription ? isExpanded : undefined}
|
|
705
705
|
>
|
|
706
706
|
<span className="flex items-start gap-3">
|
|
707
707
|
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-ph-muted text-ph-ink">
|
|
@@ -801,7 +801,7 @@ export function SuiteIntegrationPicker({
|
|
|
801
801
|
{connectedItems.map((item) => (
|
|
802
802
|
<div
|
|
803
803
|
key={item.id}
|
|
804
|
-
className="flex items-center justify-between gap-3 rounded-
|
|
804
|
+
className="flex items-center justify-between gap-3 rounded-[var(--ph-radius-surface)] border border-ph-border bg-[var(--ph-surface-inset)] p-3"
|
|
805
805
|
>
|
|
806
806
|
<span className="flex min-w-0 items-center gap-2 text-sm text-ph-ink">
|
|
807
807
|
{item.icon}
|
|
@@ -885,7 +885,7 @@ export function SuiteIntegrationPicker({
|
|
|
885
885
|
<button
|
|
886
886
|
key={scheme}
|
|
887
887
|
type="button"
|
|
888
|
-
className="flex w-full items-center justify-between rounded-
|
|
888
|
+
className="flex w-full items-center justify-between rounded-[var(--ph-radius-control)] border border-ph-border bg-ph-surface px-3 py-3 text-left text-sm text-ph-ink transition-[background-color,border-color,box-shadow] hover:border-[var(--ph-selected-border)] hover:bg-[var(--ph-surface-hover)] focus-visible:outline-none focus-visible:shadow-[var(--ph-focus-halo)]"
|
|
889
889
|
onClick={() => void prepareConnection(methodItem, scheme)}
|
|
890
890
|
data-test={`${dataTest}-choose-${scheme.toLowerCase()}`}
|
|
891
891
|
>
|
|
@@ -221,7 +221,7 @@ export function SuiteIntegrationRules({
|
|
|
221
221
|
<p className="mt-4 text-sm text-ph-subtle">Loading rules...</p>
|
|
222
222
|
) : rules.length === 0 ? (
|
|
223
223
|
<div
|
|
224
|
-
className="mt-4 rounded-
|
|
224
|
+
className="mt-4 rounded-[var(--ph-radius-surface)] border border-dashed border-ph-border bg-[var(--ph-surface-inset)] px-4 py-6 text-center"
|
|
225
225
|
data-test={`${dataTest}-empty`}
|
|
226
226
|
>
|
|
227
227
|
<p className="text-sm text-ph-subtle">
|
|
@@ -234,7 +234,7 @@ export function SuiteIntegrationRules({
|
|
|
234
234
|
{rules.map((rule) => (
|
|
235
235
|
<li
|
|
236
236
|
key={rule.id}
|
|
237
|
-
className="flex items-center justify-between gap-3 rounded-
|
|
237
|
+
className="flex items-center justify-between gap-3 rounded-[var(--ph-radius-surface)] border border-ph-border bg-[var(--ph-surface-inset)] px-3 py-3"
|
|
238
238
|
data-test={`${dataTest}-rule-${rule.id}`}
|
|
239
239
|
>
|
|
240
240
|
<div className="min-w-0">
|
|
@@ -282,7 +282,7 @@ export function SuiteIntegrationRules({
|
|
|
282
282
|
|
|
283
283
|
{canManage && formOpen && onCreate ? (
|
|
284
284
|
<form
|
|
285
|
-
className="mt-4 space-y-3 rounded-
|
|
285
|
+
className="mt-4 space-y-3 rounded-[var(--ph-radius-surface)] border border-ph-border bg-ph-surface p-4"
|
|
286
286
|
onSubmit={(event) => void submitForm(event)}
|
|
287
287
|
data-test={`${dataTest}-form`}
|
|
288
288
|
>
|
|
@@ -435,7 +435,7 @@ export function SuiteIntegrationRules({
|
|
|
435
435
|
</p>
|
|
436
436
|
{events.length === 0 ? (
|
|
437
437
|
<p
|
|
438
|
-
className="mt-4 rounded-
|
|
438
|
+
className="mt-4 rounded-[var(--ph-radius-surface)] border border-dashed border-ph-border bg-[var(--ph-surface-inset)] px-4 py-6 text-center text-sm text-ph-subtle"
|
|
439
439
|
data-test={`${dataTest}-events-empty`}
|
|
440
440
|
>
|
|
441
441
|
No integration events yet.
|
|
@@ -445,7 +445,7 @@ export function SuiteIntegrationRules({
|
|
|
445
445
|
{events.map((event) => (
|
|
446
446
|
<li
|
|
447
447
|
key={event.id}
|
|
448
|
-
className="flex items-center justify-between gap-3 rounded-
|
|
448
|
+
className="flex items-center justify-between gap-3 rounded-[var(--ph-radius-surface)] border border-ph-border bg-[var(--ph-surface-inset)] px-3 py-2"
|
|
449
449
|
>
|
|
450
450
|
<div className="min-w-0">
|
|
451
451
|
<p className="truncate text-sm text-ph-ink">
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { cleanup, render, screen, within } from "@testing-library/react";
|
|
2
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
1
|
+
import { cleanup, fireEvent, render, screen, within } from "@testing-library/react";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
SIDEBAR_MAX_WIDTH,
|
|
6
|
+
SIDEBAR_RAIL_WIDTH,
|
|
7
|
+
sidebarColumnWidth,
|
|
8
|
+
} from "../lib/use-sidebar-width";
|
|
5
9
|
import { SuiteAppLayout } from "./suite-app-layout";
|
|
6
10
|
import { SuitePageHeader } from "./suite-layout";
|
|
7
11
|
|
|
@@ -36,6 +40,31 @@ describe("sidebar resize handle", () => {
|
|
|
36
40
|
expect(handle?.previousElementSibling).toHaveClass("isolate");
|
|
37
41
|
expect(handle).toHaveClass("z-20");
|
|
38
42
|
});
|
|
43
|
+
|
|
44
|
+
it("supports range-style keyboard minimum, maximum, and steps", () => {
|
|
45
|
+
const onResizeBy = vi.fn();
|
|
46
|
+
render(
|
|
47
|
+
<SuiteAppLayout
|
|
48
|
+
sidebarWidth={240}
|
|
49
|
+
onStartResize={() => {}}
|
|
50
|
+
onResizeBy={onResizeBy}
|
|
51
|
+
sidebar={<div>Sidebar</div>}
|
|
52
|
+
>
|
|
53
|
+
Page
|
|
54
|
+
</SuiteAppLayout>,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const handle = screen.getByRole("separator", { name: "Resize sidebar" });
|
|
58
|
+
fireEvent.keyDown(handle, { key: "Home" });
|
|
59
|
+
fireEvent.keyDown(handle, { key: "End" });
|
|
60
|
+
fireEvent.keyDown(handle, { key: "ArrowLeft" });
|
|
61
|
+
fireEvent.keyDown(handle, { key: "ArrowRight" });
|
|
62
|
+
|
|
63
|
+
expect(onResizeBy).toHaveBeenNthCalledWith(1, SIDEBAR_RAIL_WIDTH - 240);
|
|
64
|
+
expect(onResizeBy).toHaveBeenNthCalledWith(2, SIDEBAR_MAX_WIDTH - 240);
|
|
65
|
+
expect(onResizeBy).toHaveBeenNthCalledWith(3, -16);
|
|
66
|
+
expect(onResizeBy).toHaveBeenNthCalledWith(4, 16);
|
|
67
|
+
});
|
|
39
68
|
});
|
|
40
69
|
|
|
41
70
|
describe("suite scroll ownership", () => {
|
|
@@ -192,7 +192,7 @@ export function SuitePageHeader({
|
|
|
192
192
|
data-test={dataTest}
|
|
193
193
|
data-stuck={sticky ? (stuck ? 'true' : 'false') : undefined}
|
|
194
194
|
className={cn(
|
|
195
|
-
'flex min-w-0 shrink-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3',
|
|
195
|
+
'suite-page-header flex min-w-0 shrink-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3',
|
|
196
196
|
// No extra pt here — page inset sets the shared title baseline.
|
|
197
197
|
sticky && 'suite-page-header-sticky',
|
|
198
198
|
className,
|
|
@@ -213,7 +213,7 @@ export function SuitePageHeader({
|
|
|
213
213
|
<div className="flex min-w-0 items-center gap-3">
|
|
214
214
|
{resolvedIcon ? (
|
|
215
215
|
<div
|
|
216
|
-
className="hidden shrink-0 sm:flex sm:items-center [&_svg]:h-6 [&_svg]:w-6"
|
|
216
|
+
className="suite-page-header__icon hidden shrink-0 sm:flex sm:items-center [&_svg]:h-6 [&_svg]:w-6"
|
|
217
217
|
aria-hidden="true"
|
|
218
218
|
>
|
|
219
219
|
{resolvedIcon}
|
|
@@ -222,14 +222,14 @@ export function SuitePageHeader({
|
|
|
222
222
|
<div className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
|
|
223
223
|
<h1
|
|
224
224
|
className={cn(
|
|
225
|
-
'min-w-0 break-words font-display
|
|
225
|
+
'ph-page-title min-w-0 break-words font-display font-semibold text-ph-ink text-balance',
|
|
226
226
|
titleClassName,
|
|
227
227
|
)}
|
|
228
228
|
>
|
|
229
229
|
{title}
|
|
230
230
|
</h1>
|
|
231
231
|
{badge ? (
|
|
232
|
-
<span className="rounded-
|
|
232
|
+
<span className="rounded-[var(--ph-radius-control)] bg-ph-muted px-2 py-0.5 text-[length:var(--ph-type-overline)] font-semibold uppercase tracking-wide text-ph-subtle">
|
|
233
233
|
{badge}
|
|
234
234
|
</span>
|
|
235
235
|
) : null}
|
|
@@ -98,7 +98,7 @@ export function SuiteMobileDrawer({
|
|
|
98
98
|
data-test={panelDataTest}
|
|
99
99
|
aria-modal="true"
|
|
100
100
|
className={cn(
|
|
101
|
-
"fixed inset-y-0 left-0 z-50 flex h-dvh max-h-dvh w-[86%] max-w-72 flex-col overflow-hidden bg-ph-surface shadow-
|
|
101
|
+
"fixed inset-y-0 left-0 z-50 flex h-dvh max-h-dvh w-[86%] max-w-72 flex-col overflow-hidden border-r border-ph-border bg-ph-surface shadow-[var(--ph-shadow-floating)] outline-none motion-safe:transition-transform motion-safe:ease-spring-fast lg:hidden",
|
|
102
102
|
side === "right" && "left-auto right-0",
|
|
103
103
|
shown
|
|
104
104
|
? "translate-x-0"
|
|
@@ -127,7 +127,7 @@ export function SuiteMobileDrawer({
|
|
|
127
127
|
type="button"
|
|
128
128
|
id={closeButtonId}
|
|
129
129
|
data-test={closeButtonDataTest}
|
|
130
|
-
className="-mr-1.5
|
|
130
|
+
className="ph-btn ph-btn-ghost ph-btn-square -mr-1.5 h-11 w-11 text-ph-mutedtext"
|
|
131
131
|
aria-label={closeLabel}
|
|
132
132
|
>
|
|
133
133
|
<X className="h-4 w-4" aria-hidden />
|
|
@@ -54,7 +54,7 @@ export function SuiteMobileHeader({
|
|
|
54
54
|
type="button"
|
|
55
55
|
id={menuId}
|
|
56
56
|
data-test={menuDataTest}
|
|
57
|
-
className="suite-press
|
|
57
|
+
className="ph-btn ph-btn-ghost ph-btn-square suite-press h-11 w-11 shrink-0 text-ph-ink"
|
|
58
58
|
onClick={onMenuClick}
|
|
59
59
|
aria-label={menuLabel}
|
|
60
60
|
>
|
|
@@ -65,7 +65,7 @@ export function SuiteNotificationBell({
|
|
|
65
65
|
open={open}
|
|
66
66
|
onOpenChange={onOpenChange}
|
|
67
67
|
trigger={
|
|
68
|
-
<span className="relative inline-flex h-11 w-11 items-center justify-center overflow-visible rounded-full text-ph-mutedtext transition hover:bg-ph-muted hover:text-ph-ink">
|
|
68
|
+
<span className="relative inline-flex h-11 w-11 items-center justify-center overflow-visible rounded-full text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink">
|
|
69
69
|
<span className="relative inline-flex h-5 w-5">
|
|
70
70
|
<Bell className="h-5 w-5" strokeWidth={1.75} aria-hidden />
|
|
71
71
|
{unread > 0 ? (
|
|
@@ -85,7 +85,7 @@ export function SuiteNotificationBell({
|
|
|
85
85
|
id={`${dataTest}-mark-all`}
|
|
86
86
|
data-test={`${dataTest}-mark-all`}
|
|
87
87
|
onClick={markAllRead}
|
|
88
|
-
className="
|
|
88
|
+
className="ph-btn ph-btn-link ph-btn-xs text-xs"
|
|
89
89
|
>
|
|
90
90
|
Mark all read
|
|
91
91
|
</button>
|
|
@@ -106,7 +106,7 @@ export function SuiteNotificationBell({
|
|
|
106
106
|
setOpen(false);
|
|
107
107
|
select(n);
|
|
108
108
|
}}
|
|
109
|
-
className="flex w-full flex-col gap-0.5 px-3 py-2 text-left
|
|
109
|
+
className="ph-dropdown-item flex w-full flex-col items-stretch gap-0.5 px-3 py-2 text-left"
|
|
110
110
|
>
|
|
111
111
|
<span className="flex items-center gap-2">
|
|
112
112
|
{!n.read_at ? (
|
|
@@ -124,7 +124,7 @@ export function SuiteNotificationBell({
|
|
|
124
124
|
{n.body}
|
|
125
125
|
</span>
|
|
126
126
|
) : null}
|
|
127
|
-
<span className="text-
|
|
127
|
+
<span className="text-xs text-ph-subtle">
|
|
128
128
|
{n.source_app} · {timeAgo(n.created_at)}
|
|
129
129
|
</span>
|
|
130
130
|
</button>
|