@xenide-io/the-old-ui-theme 0.6.2 → 0.6.5
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/suite.d.mts +7 -4
- package/dist/suite.d.ts +7 -4
- package/dist/suite.js +377 -180
- package/dist/suite.mjs +389 -181
- package/package.json +1 -1
- package/src/styles/suite-skin.css +136 -32
- package/src/suite/components/ai-panel.tsx +306 -137
- package/src/suite/components/suite-layout.test.tsx +5 -0
- package/src/suite/components/suite-layout.tsx +22 -12
- package/src/suite/components/suite-sidebar.tsx +3 -1
- package/src/suite/components/suite-user-menu.tsx +43 -7
- package/src/suite/components/today-page-frame.tsx +4 -5
|
@@ -193,7 +193,9 @@ export function SuiteSidebar({
|
|
|
193
193
|
<div
|
|
194
194
|
className={cn(
|
|
195
195
|
"flex items-center gap-2",
|
|
196
|
-
collapsed
|
|
196
|
+
collapsed
|
|
197
|
+
? "flex-col items-center justify-center [&_[data-test$='-visible-sign-out']]:hidden [&>div]:w-auto"
|
|
198
|
+
: "w-full min-w-0",
|
|
197
199
|
)}
|
|
198
200
|
>
|
|
199
201
|
{renderNode(userMenu, collapsed)}
|
|
@@ -38,6 +38,27 @@ function computeInitials(
|
|
|
38
38
|
.toUpperCase();
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Deterministic coloured fallback: derives a stable accent from the user's
|
|
43
|
+
* email or name so avatars without a photo get a per-user colour instead of a
|
|
44
|
+
* flat grey. Uses theme `--ph-*` tokens so it adapts to light and dark themes.
|
|
45
|
+
*/
|
|
46
|
+
const AVATAR_TOKENS = [
|
|
47
|
+
"bg-ph-brand",
|
|
48
|
+
"bg-ph-violet",
|
|
49
|
+
"bg-ph-info",
|
|
50
|
+
"bg-ph-success",
|
|
51
|
+
"bg-ph-danger",
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
function avatarColorClass(seed: string): string {
|
|
55
|
+
let hash = 0;
|
|
56
|
+
for (let i = 0; i < seed.length; i += 1) {
|
|
57
|
+
hash = seed.charCodeAt(i) + ((hash << 5) - hash);
|
|
58
|
+
}
|
|
59
|
+
return AVATAR_TOKENS[Math.abs(hash) % AVATAR_TOKENS.length];
|
|
60
|
+
}
|
|
61
|
+
|
|
41
62
|
/**
|
|
42
63
|
* Suite account context menu — one tap on the avatar opens a small menu with
|
|
43
64
|
* profile settings and sign out. Desktop sidebars can also expose the legacy
|
|
@@ -58,20 +79,27 @@ export function SuiteUserMenu({
|
|
|
58
79
|
}: SuiteUserMenuProps) {
|
|
59
80
|
const router = useRouter();
|
|
60
81
|
const initials = fallbackInitials ?? computeInitials(name, email);
|
|
82
|
+
const fallbackColor = avatarColorClass(email || name || "?");
|
|
61
83
|
|
|
84
|
+
// Match Tides Avatar `sm` (40px). Colour comes from theme `--ph-*` tokens.
|
|
62
85
|
const avatar = (
|
|
63
|
-
<span className="inline-flex h-
|
|
86
|
+
<span className="inline-flex h-10 w-10 items-center justify-center overflow-hidden rounded-full border border-ph-border">
|
|
64
87
|
{image ? (
|
|
65
88
|
<Image
|
|
66
89
|
src={image}
|
|
67
90
|
alt=""
|
|
68
91
|
width={40}
|
|
69
92
|
height={40}
|
|
70
|
-
className="h-
|
|
93
|
+
className="h-full w-full object-cover"
|
|
71
94
|
unoptimized
|
|
72
95
|
/>
|
|
73
96
|
) : (
|
|
74
|
-
<span
|
|
97
|
+
<span
|
|
98
|
+
className={cn(
|
|
99
|
+
"flex h-full w-full items-center justify-center text-sm font-semibold text-white",
|
|
100
|
+
fallbackColor,
|
|
101
|
+
)}
|
|
102
|
+
>
|
|
75
103
|
{initials}
|
|
76
104
|
</span>
|
|
77
105
|
)}
|
|
@@ -89,7 +117,10 @@ export function SuiteUserMenu({
|
|
|
89
117
|
sideOffset={6}
|
|
90
118
|
collisionPadding={16}
|
|
91
119
|
modal={false}
|
|
92
|
-
className={
|
|
120
|
+
className={cn(
|
|
121
|
+
"[&_.ph-dropdown-trigger]:rounded-full",
|
|
122
|
+
showSignOutAction ? undefined : className,
|
|
123
|
+
)}
|
|
93
124
|
data-test={dataTest}
|
|
94
125
|
>
|
|
95
126
|
<div className="px-2 py-1.5">
|
|
@@ -120,14 +151,19 @@ export function SuiteUserMenu({
|
|
|
120
151
|
}
|
|
121
152
|
|
|
122
153
|
return (
|
|
123
|
-
<div
|
|
124
|
-
{
|
|
154
|
+
<div
|
|
155
|
+
className={cn(
|
|
156
|
+
"flex w-full min-w-0 flex-1 items-center justify-between gap-2",
|
|
157
|
+
className,
|
|
158
|
+
)}
|
|
159
|
+
>
|
|
160
|
+
<div className="shrink-0">{accountMenu}</div>
|
|
125
161
|
<button
|
|
126
162
|
type="button"
|
|
127
163
|
data-test={`${dataTest}-visible-sign-out`}
|
|
128
164
|
title="Sign out"
|
|
129
165
|
aria-label="Sign out"
|
|
130
|
-
className="inline-flex h-
|
|
166
|
+
className="inline-flex h-10 w-10 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"
|
|
131
167
|
onClick={onSignOut}
|
|
132
168
|
>
|
|
133
169
|
<LogOut className="h-4 w-4" aria-hidden />
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Today page content wrapper
|
|
7
|
-
*
|
|
8
|
-
* Glow/clouds are absolute and do not create a nested scrollport.
|
|
6
|
+
* Today page content wrapper. The frame owns scrolling; its decorative layer
|
|
7
|
+
* is sticky so the original glow and clouds stay fixed while content moves.
|
|
9
8
|
*/
|
|
10
9
|
export function TodayPageFrame({ children }: { children: ReactNode }) {
|
|
11
10
|
return (
|
|
12
11
|
<div
|
|
13
12
|
data-test="today-page"
|
|
14
|
-
className="today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-
|
|
13
|
+
className="today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-clip"
|
|
15
14
|
>
|
|
16
15
|
<div
|
|
17
|
-
className="pointer-events-none
|
|
16
|
+
className="today-page-frame__backdrop pointer-events-none overflow-hidden"
|
|
18
17
|
aria-hidden
|
|
19
18
|
>
|
|
20
19
|
<div className="today-page-frame__glow absolute inset-0" />
|