@xenide-io/the-old-ui-theme 0.5.2 → 0.5.3
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/README.md +47 -34
- package/dist/{chunk-RZXHZWUB.mjs → chunk-VFTZXPXM.mjs} +30 -143
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -143
- package/dist/index.mjs +1 -1
- package/dist/suite.d.mts +19 -14
- package/dist/suite.d.ts +19 -14
- package/dist/suite.js +168 -96
- package/dist/suite.mjs +168 -96
- package/dist/ui.js +30 -143
- package/dist/ui.mjs +1 -1
- package/package.json +1 -1
- package/src/app/globals.css +1 -0
- package/src/components/ui/ThemeSwitcher.tsx +12 -3
- package/src/styles/suite-skin.css +71 -1
- package/src/styles/themes.css +445 -1656
- package/src/suite/components/suite-app-layout.tsx +31 -10
- package/src/suite/components/suite-sidebar.tsx +50 -42
- package/src/suite/components/suite-user-menu.tsx +48 -26
- package/src/suite/components/today-page-frame.tsx +1 -1
- package/src/suite/icons/app-accents.ts +38 -43
- package/src/suite/icons/glyph-parts.tsx +16 -9
- package/src/suite/icons/glyphs.ts +130 -99
- package/src/suite/lib/apps.ts +1 -1
- package/src/suite/lib/use-sidebar-width.ts +23 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import { type ReactNode, type PointerEvent } from
|
|
3
|
+
import { type ReactNode, type PointerEvent } from "react";
|
|
4
4
|
|
|
5
|
-
import { cn } from
|
|
5
|
+
import { cn } from "../lib/cn";
|
|
6
6
|
|
|
7
7
|
export interface SuiteAppLayoutProps {
|
|
8
8
|
sidebar: ReactNode;
|
|
@@ -20,6 +20,8 @@ export interface SuiteAppLayoutProps {
|
|
|
20
20
|
lockMainScroll?: boolean;
|
|
21
21
|
/** Drag this to resize the sidebar. */
|
|
22
22
|
onStartResize?: (e: PointerEvent<HTMLDivElement>) => void;
|
|
23
|
+
/** Keyboard equivalent for the resize handle. */
|
|
24
|
+
onResizeBy?: (delta: number) => void;
|
|
23
25
|
/** Double-click to reset sidebar width. */
|
|
24
26
|
onResetWidth?: () => void;
|
|
25
27
|
className?: string;
|
|
@@ -39,18 +41,22 @@ export function SuiteAppLayout({
|
|
|
39
41
|
collapsed = false,
|
|
40
42
|
lockMainScroll = false,
|
|
41
43
|
onStartResize,
|
|
44
|
+
onResizeBy,
|
|
42
45
|
onResetWidth,
|
|
43
46
|
className,
|
|
44
47
|
}: SuiteAppLayoutProps) {
|
|
45
48
|
return (
|
|
46
49
|
<div
|
|
47
50
|
data-test="app-shell"
|
|
48
|
-
className={cn(
|
|
51
|
+
className={cn(
|
|
52
|
+
"suite-app-layout flex min-h-dvh lg:h-screen lg:overflow-hidden",
|
|
53
|
+
className,
|
|
54
|
+
)}
|
|
49
55
|
>
|
|
50
56
|
<aside
|
|
51
|
-
className="relative hidden shrink-0 flex-col overflow-
|
|
57
|
+
className="relative hidden shrink-0 flex-col overflow-visible border-r border-ph-border ease-out lg:flex"
|
|
52
58
|
style={{ width: `${sidebarWidth}px` }}
|
|
53
|
-
data-collapsed={collapsed ?
|
|
59
|
+
data-collapsed={collapsed ? "true" : "false"}
|
|
54
60
|
>
|
|
55
61
|
{sidebar}
|
|
56
62
|
{onStartResize ? (
|
|
@@ -58,9 +64,23 @@ export function SuiteAppLayout({
|
|
|
58
64
|
role="separator"
|
|
59
65
|
aria-orientation="vertical"
|
|
60
66
|
aria-label="Resize sidebar"
|
|
67
|
+
data-test="sidebar-resize-handle"
|
|
68
|
+
tabIndex={onResizeBy ? 0 : undefined}
|
|
61
69
|
onPointerDown={onStartResize}
|
|
62
70
|
onDoubleClick={onResetWidth}
|
|
63
|
-
|
|
71
|
+
onKeyDown={(event) => {
|
|
72
|
+
if (event.key === "Home") {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
onResetWidth?.();
|
|
75
|
+
} else if (event.key === "ArrowLeft") {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
onResizeBy?.(-16);
|
|
78
|
+
} else if (event.key === "ArrowRight") {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
onResizeBy?.(16);
|
|
81
|
+
}
|
|
82
|
+
}}
|
|
83
|
+
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)]"
|
|
64
84
|
/>
|
|
65
85
|
) : null}
|
|
66
86
|
</aside>
|
|
@@ -72,10 +92,11 @@ export function SuiteAppLayout({
|
|
|
72
92
|
<main
|
|
73
93
|
id="main-content"
|
|
74
94
|
tabIndex={-1}
|
|
75
|
-
data-lock-scroll={lockMainScroll ?
|
|
95
|
+
data-lock-scroll={lockMainScroll ? "true" : undefined}
|
|
76
96
|
className={cn(
|
|
77
|
-
|
|
78
|
-
|
|
97
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
98
|
+
"suite-app-layout__main",
|
|
99
|
+
lockMainScroll ? "overflow-hidden" : "overflow-y-auto",
|
|
79
100
|
)}
|
|
80
101
|
>
|
|
81
102
|
{children}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import Link from
|
|
4
|
-
import { type ReactNode } from
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { type ReactNode } from "react";
|
|
5
5
|
|
|
6
|
-
import { cn } from
|
|
7
|
-
import { Tooltip } from
|
|
8
|
-
import type { SuiteNavIcon } from
|
|
6
|
+
import { cn } from "../lib/cn";
|
|
7
|
+
import { Tooltip } from "../../components/ui/Tooltip";
|
|
8
|
+
import type { SuiteNavIcon } from "./suite-bottom-nav";
|
|
9
9
|
|
|
10
10
|
type CollapsedNode = ReactNode | ((collapsed: boolean) => ReactNode);
|
|
11
11
|
|
|
@@ -38,8 +38,11 @@ export interface SuiteSidebarProps {
|
|
|
38
38
|
surface?: boolean;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function renderNode(
|
|
42
|
-
|
|
41
|
+
function renderNode(
|
|
42
|
+
node: CollapsedNode | undefined,
|
|
43
|
+
collapsed: boolean,
|
|
44
|
+
): ReactNode {
|
|
45
|
+
if (typeof node === "function") return node(collapsed);
|
|
43
46
|
return node;
|
|
44
47
|
}
|
|
45
48
|
|
|
@@ -66,42 +69,41 @@ export function SuiteSidebar({
|
|
|
66
69
|
return (
|
|
67
70
|
<div
|
|
68
71
|
className={cn(
|
|
69
|
-
|
|
70
|
-
surface ?
|
|
72
|
+
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
73
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
71
74
|
className,
|
|
72
75
|
)}
|
|
73
76
|
>
|
|
74
77
|
{/* Header */}
|
|
75
78
|
<div
|
|
76
79
|
className={cn(
|
|
77
|
-
|
|
78
|
-
surface ?
|
|
80
|
+
"flex shrink-0 border-b border-ph-border",
|
|
81
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
79
82
|
collapsed
|
|
80
|
-
?
|
|
81
|
-
:
|
|
83
|
+
? "flex-col items-center gap-1 px-1 py-2"
|
|
84
|
+
: "h-14 items-center justify-between gap-2 px-3",
|
|
82
85
|
)}
|
|
83
86
|
>
|
|
84
|
-
<div className={cn(
|
|
87
|
+
<div className={cn("min-w-0", collapsed ? "shrink-0" : "flex-1")}>
|
|
85
88
|
{renderNode(appSwitcher, collapsed)}
|
|
86
89
|
</div>
|
|
87
90
|
{collapsed ? null : (
|
|
88
|
-
<div className="shrink-0">
|
|
91
|
+
<div className="shrink-0">
|
|
92
|
+
{renderNode(notificationBell, collapsed)}
|
|
93
|
+
</div>
|
|
89
94
|
)}
|
|
90
95
|
</div>
|
|
91
96
|
|
|
92
97
|
{/* Nav body */}
|
|
93
98
|
<div
|
|
94
99
|
className={cn(
|
|
95
|
-
|
|
96
|
-
surface ?
|
|
97
|
-
collapsed ?
|
|
100
|
+
"flex min-h-0 flex-1 flex-col overflow-y-auto",
|
|
101
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
102
|
+
collapsed ? "px-1.5 py-2" : "p-2",
|
|
98
103
|
)}
|
|
99
104
|
>
|
|
100
|
-
<nav
|
|
101
|
-
|
|
102
|
-
className="shrink-0 space-y-0.5"
|
|
103
|
-
>
|
|
104
|
-
<div className={cn('mb-3', collapsed && 'flex justify-center')}>
|
|
105
|
+
<nav aria-label="Pages" className="shrink-0 space-y-0.5">
|
|
106
|
+
<div className={cn("mb-3", collapsed && "flex justify-center")}>
|
|
105
107
|
{renderNode(contextSwitcher, collapsed)}
|
|
106
108
|
</div>
|
|
107
109
|
|
|
@@ -114,21 +116,21 @@ export function SuiteSidebar({
|
|
|
114
116
|
key={item.label}
|
|
115
117
|
href={item.href}
|
|
116
118
|
data-test="nav-link"
|
|
117
|
-
aria-current={active ?
|
|
119
|
+
aria-current={active ? "page" : undefined}
|
|
118
120
|
onClick={item.onClick}
|
|
119
121
|
className={cn(
|
|
120
|
-
|
|
122
|
+
"group relative flex items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
|
|
121
123
|
active
|
|
122
|
-
?
|
|
123
|
-
:
|
|
124
|
+
? "bg-ph-muted"
|
|
125
|
+
: "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
|
|
124
126
|
collapsed
|
|
125
|
-
?
|
|
126
|
-
:
|
|
127
|
+
? "mx-auto size-10 shrink-0 justify-center gap-0 px-0 py-0"
|
|
128
|
+
: "w-full px-2.5 py-2",
|
|
127
129
|
)}
|
|
128
130
|
>
|
|
129
131
|
<span
|
|
130
132
|
className={cn(
|
|
131
|
-
|
|
133
|
+
"relative flex h-4 w-4 shrink-0 items-center justify-center",
|
|
132
134
|
item.iconClassName,
|
|
133
135
|
)}
|
|
134
136
|
aria-hidden
|
|
@@ -140,15 +142,19 @@ export function SuiteSidebar({
|
|
|
140
142
|
</span>
|
|
141
143
|
<span
|
|
142
144
|
className={cn(
|
|
143
|
-
|
|
144
|
-
active
|
|
145
|
-
|
|
145
|
+
"relative truncate",
|
|
146
|
+
active
|
|
147
|
+
? "text-ph-ink"
|
|
148
|
+
: "text-ph-subtle group-hover:text-ph-ink",
|
|
149
|
+
collapsed && "sr-only",
|
|
146
150
|
)}
|
|
147
151
|
>
|
|
148
152
|
{item.label}
|
|
149
153
|
</span>
|
|
150
154
|
{!collapsed && item.badge ? (
|
|
151
|
-
<span className="relative ml-auto shrink-0">
|
|
155
|
+
<span className="relative ml-auto shrink-0">
|
|
156
|
+
{item.badge}
|
|
157
|
+
</span>
|
|
152
158
|
) : null}
|
|
153
159
|
</Link>
|
|
154
160
|
);
|
|
@@ -176,20 +182,22 @@ export function SuiteSidebar({
|
|
|
176
182
|
{/* Footer */}
|
|
177
183
|
<div
|
|
178
184
|
className={cn(
|
|
179
|
-
|
|
180
|
-
surface ?
|
|
181
|
-
collapsed ?
|
|
185
|
+
"shrink-0 border-t border-ph-border",
|
|
186
|
+
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
187
|
+
collapsed ? "p-1.5" : "p-3",
|
|
182
188
|
)}
|
|
183
189
|
>
|
|
184
190
|
<div
|
|
185
191
|
className={cn(
|
|
186
|
-
|
|
187
|
-
collapsed
|
|
192
|
+
"flex items-center gap-2",
|
|
193
|
+
collapsed ? "flex-col justify-center" : "min-w-0",
|
|
188
194
|
)}
|
|
189
195
|
>
|
|
190
196
|
{renderNode(userMenu, collapsed)}
|
|
191
|
-
{
|
|
192
|
-
<div className="
|
|
197
|
+
{footerExtras ? (
|
|
198
|
+
<div className={cn("shrink-0", collapsed ? "mt-2" : "ml-auto")}>
|
|
199
|
+
{renderNode(footerExtras, collapsed)}
|
|
200
|
+
</div>
|
|
193
201
|
) : null}
|
|
194
202
|
</div>
|
|
195
203
|
</div>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import Image from
|
|
4
|
-
import { useRouter } from
|
|
5
|
-
import { LogOut, Settings } from
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { LogOut, Settings } from "iconoir-react";
|
|
6
6
|
|
|
7
|
-
import { cn } from
|
|
8
|
-
import { DropdownMenu, DropdownItem } from
|
|
7
|
+
import { cn } from "../lib/cn";
|
|
8
|
+
import { DropdownMenu, DropdownItem } from "../../components/ui/DropdownMenu";
|
|
9
9
|
|
|
10
10
|
export interface SuiteUserMenuProps {
|
|
11
11
|
name?: string | null;
|
|
@@ -16,26 +16,30 @@ export interface SuiteUserMenuProps {
|
|
|
16
16
|
onSignOut: () => void;
|
|
17
17
|
/** Fallback letter(s) when there is no avatar image. */
|
|
18
18
|
fallbackInitials?: string;
|
|
19
|
+
/** Show the old desktop sidebar sign-out action beside the avatar. */
|
|
20
|
+
showSignOutAction?: boolean;
|
|
19
21
|
dataTest?: string;
|
|
20
22
|
className?: string;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
function computeInitials(
|
|
24
|
-
|
|
25
|
+
function computeInitials(
|
|
26
|
+
name: string | null | undefined,
|
|
27
|
+
email: string | null | undefined,
|
|
28
|
+
): string {
|
|
29
|
+
const source = (name || email || "?").trim();
|
|
25
30
|
return source
|
|
26
31
|
.split(/[\s@]+/)
|
|
27
32
|
.filter(Boolean)
|
|
28
33
|
.slice(0, 2)
|
|
29
34
|
.map((part) => part[0])
|
|
30
|
-
.join(
|
|
35
|
+
.join("")
|
|
31
36
|
.toUpperCase();
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
/**
|
|
35
|
-
* Suite account context menu — one tap on the avatar opens a small menu
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* logout icon cluttering the mobile chrome).
|
|
40
|
+
* Suite account context menu — one tap on the avatar opens a small menu with
|
|
41
|
+
* profile settings and sign out. Desktop sidebars can also expose the legacy
|
|
42
|
+
* adjacent sign-out action without adding it to mobile chrome.
|
|
39
43
|
*/
|
|
40
44
|
export function SuiteUserMenu({
|
|
41
45
|
name,
|
|
@@ -44,32 +48,33 @@ export function SuiteUserMenu({
|
|
|
44
48
|
settingsHref,
|
|
45
49
|
onSignOut,
|
|
46
50
|
fallbackInitials,
|
|
47
|
-
|
|
51
|
+
showSignOutAction = false,
|
|
52
|
+
dataTest = "suite-user-menu",
|
|
48
53
|
className,
|
|
49
54
|
}: SuiteUserMenuProps) {
|
|
50
55
|
const router = useRouter();
|
|
51
56
|
const initials = fallbackInitials ?? computeInitials(name, email);
|
|
52
57
|
|
|
53
58
|
const avatar = (
|
|
54
|
-
<span className="inline-flex h-11 w-11 items-center justify-center rounded-full transition-colors hover:bg-ph-muted">
|
|
59
|
+
<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">
|
|
55
60
|
{image ? (
|
|
56
61
|
<Image
|
|
57
62
|
src={image}
|
|
58
63
|
alt=""
|
|
59
|
-
width={
|
|
60
|
-
height={
|
|
61
|
-
className="h-
|
|
64
|
+
width={40}
|
|
65
|
+
height={40}
|
|
66
|
+
className="h-10 w-10 rounded-full object-cover"
|
|
62
67
|
unoptimized
|
|
63
68
|
/>
|
|
64
69
|
) : (
|
|
65
|
-
<span className="flex h-
|
|
70
|
+
<span className="flex h-10 w-10 items-center justify-center rounded-full bg-ph-muted text-sm font-semibold text-ph-brand">
|
|
66
71
|
{initials}
|
|
67
72
|
</span>
|
|
68
73
|
)}
|
|
69
74
|
</span>
|
|
70
75
|
);
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
const accountMenu = (
|
|
73
78
|
<DropdownMenu
|
|
74
79
|
trigger={avatar}
|
|
75
80
|
aria-label="Account menu"
|
|
@@ -78,12 +83,12 @@ export function SuiteUserMenu({
|
|
|
78
83
|
sideOffset={6}
|
|
79
84
|
collisionPadding={16}
|
|
80
85
|
modal={false}
|
|
81
|
-
className={className}
|
|
86
|
+
className={showSignOutAction ? undefined : className}
|
|
82
87
|
data-test={dataTest}
|
|
83
88
|
>
|
|
84
89
|
<div className="px-2 py-1.5">
|
|
85
90
|
<p className="truncate text-sm font-medium text-ph-ink">
|
|
86
|
-
{name || email ||
|
|
91
|
+
{name || email || "Account"}
|
|
87
92
|
</p>
|
|
88
93
|
{email ? (
|
|
89
94
|
<p className="truncate text-xs text-ph-mutedtext">{email}</p>
|
|
@@ -97,13 +102,30 @@ export function SuiteUserMenu({
|
|
|
97
102
|
<Settings className="h-4 w-4 text-ph-mutedtext" aria-hidden />
|
|
98
103
|
Profile settings
|
|
99
104
|
</DropdownItem>
|
|
100
|
-
<DropdownItem
|
|
101
|
-
data-test={`${dataTest}-sign-out`}
|
|
102
|
-
onClick={onSignOut}
|
|
103
|
-
>
|
|
105
|
+
<DropdownItem data-test={`${dataTest}-sign-out`} onClick={onSignOut}>
|
|
104
106
|
<LogOut className="h-4 w-4 text-ph-mutedtext" aria-hidden />
|
|
105
107
|
Sign out
|
|
106
108
|
</DropdownItem>
|
|
107
109
|
</DropdownMenu>
|
|
108
110
|
);
|
|
111
|
+
|
|
112
|
+
if (!showSignOutAction) {
|
|
113
|
+
return accountMenu;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className={cn("flex min-w-0 items-center gap-2", className)}>
|
|
118
|
+
{accountMenu}
|
|
119
|
+
<button
|
|
120
|
+
type="button"
|
|
121
|
+
data-test={`${dataTest}-visible-sign-out`}
|
|
122
|
+
title="Sign out"
|
|
123
|
+
aria-label="Sign out"
|
|
124
|
+
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"
|
|
125
|
+
onClick={onSignOut}
|
|
126
|
+
>
|
|
127
|
+
<LogOut className="h-4 w-4" aria-hidden />
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
109
131
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Today page content wrapper with soft
|
|
6
|
+
* Today page content wrapper with a soft themed visual treatment.
|
|
7
7
|
* Does not own scrolling — `#main-content` is the scrollport so sticky headers work.
|
|
8
8
|
* Glow/clouds are absolute and do not create a nested scrollport.
|
|
9
9
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SuiteIconName } from
|
|
1
|
+
import type { SuiteIconName } from "./glyphs";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Per-app brand colours for the suite icon system — the single place hexes
|
|
@@ -8,12 +8,7 @@ import type { SuiteIconName } from './glyphs';
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
export type SuiteAccentSlug =
|
|
11
|
-
|
|
|
12
|
-
| 'tides'
|
|
13
|
-
| 'kraken'
|
|
14
|
-
| 'shellstack'
|
|
15
|
-
| 'crew'
|
|
16
|
-
| 'nakama';
|
|
11
|
+
"turtletime" | "tides" | "kraken" | "shellstack" | "crew" | "nakama";
|
|
17
12
|
|
|
18
13
|
export interface SuiteAppAccent {
|
|
19
14
|
/** Display name (default aria label for app marks). */
|
|
@@ -30,55 +25,55 @@ export interface SuiteAppAccent {
|
|
|
30
25
|
|
|
31
26
|
export const APP_ACCENTS: Record<SuiteAccentSlug, SuiteAppAccent> = {
|
|
32
27
|
turtletime: {
|
|
33
|
-
label:
|
|
34
|
-
accent:
|
|
35
|
-
tile:
|
|
36
|
-
onTile:
|
|
37
|
-
onTileAccent:
|
|
28
|
+
label: "TurtleTime",
|
|
29
|
+
accent: "#3f8f57",
|
|
30
|
+
tile: "#173521",
|
|
31
|
+
onTile: "#f7ead0",
|
|
32
|
+
onTileAccent: "#f3c24e",
|
|
38
33
|
},
|
|
39
34
|
tides: {
|
|
40
|
-
label:
|
|
41
|
-
accent:
|
|
42
|
-
tile:
|
|
43
|
-
onTile:
|
|
44
|
-
onTileAccent:
|
|
35
|
+
label: "Tides",
|
|
36
|
+
accent: "#a63bb5",
|
|
37
|
+
tile: "#8f2d96",
|
|
38
|
+
onTile: "#ffffff",
|
|
39
|
+
onTileAccent: "#bfe3ff",
|
|
45
40
|
},
|
|
46
41
|
kraken: {
|
|
47
|
-
label:
|
|
48
|
-
accent:
|
|
49
|
-
tile:
|
|
50
|
-
onTile:
|
|
51
|
-
onTileAccent:
|
|
42
|
+
label: "Kraken",
|
|
43
|
+
accent: "#737373",
|
|
44
|
+
tile: "#191919",
|
|
45
|
+
onTile: "#ffffff",
|
|
46
|
+
onTileAccent: "#d4d4d4",
|
|
52
47
|
},
|
|
53
48
|
shellstack: {
|
|
54
|
-
label:
|
|
55
|
-
accent:
|
|
56
|
-
tile:
|
|
57
|
-
onTile:
|
|
58
|
-
onTileAccent:
|
|
49
|
+
label: "ShellStack",
|
|
50
|
+
accent: "#5e5893",
|
|
51
|
+
tile: "#5e5893",
|
|
52
|
+
onTile: "#ffffff",
|
|
53
|
+
onTileAccent: "#c4a7e7",
|
|
59
54
|
},
|
|
60
55
|
crew: {
|
|
61
|
-
label:
|
|
62
|
-
accent:
|
|
63
|
-
tile:
|
|
64
|
-
onTile:
|
|
65
|
-
onTileAccent:
|
|
56
|
+
label: "Crew",
|
|
57
|
+
accent: "#0891b2",
|
|
58
|
+
tile: "#155e75",
|
|
59
|
+
onTile: "#ffffff",
|
|
60
|
+
onTileAccent: "#a5f3fc",
|
|
66
61
|
},
|
|
67
62
|
nakama: {
|
|
68
|
-
label:
|
|
69
|
-
accent:
|
|
70
|
-
tile:
|
|
71
|
-
onTile:
|
|
72
|
-
onTileAccent:
|
|
63
|
+
label: "Nakama",
|
|
64
|
+
accent: "#b8eb44",
|
|
65
|
+
tile: "#17101f",
|
|
66
|
+
onTile: "#fff2e2",
|
|
67
|
+
onTileAccent: "#f54b87",
|
|
73
68
|
},
|
|
74
69
|
};
|
|
75
70
|
|
|
76
71
|
/** Which glyph represents each app. */
|
|
77
72
|
export const APP_GLYPHS: Record<SuiteAccentSlug, SuiteIconName> = {
|
|
78
|
-
turtletime:
|
|
79
|
-
tides:
|
|
80
|
-
kraken:
|
|
81
|
-
shellstack:
|
|
82
|
-
crew:
|
|
83
|
-
nakama:
|
|
73
|
+
turtletime: "timer-shell",
|
|
74
|
+
tides: "kanban-wave",
|
|
75
|
+
kraken: "squid-doc",
|
|
76
|
+
shellstack: "stack-hex",
|
|
77
|
+
crew: "crew-bot",
|
|
78
|
+
nakama: "nakama-fist",
|
|
84
79
|
};
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import type { SuiteGlyphElement } from
|
|
3
|
+
import type { SuiteGlyphElement } from "./glyphs";
|
|
4
4
|
|
|
5
5
|
function GlyphElement({ element }: { element: SuiteGlyphElement }) {
|
|
6
|
-
const fill = element.filled ?
|
|
7
|
-
const stroke = element.filled ?
|
|
6
|
+
const fill = element.filled ? "currentColor" : "none";
|
|
7
|
+
const stroke = element.filled ? "none" : undefined;
|
|
8
8
|
switch (element.kind) {
|
|
9
|
-
case
|
|
10
|
-
return
|
|
11
|
-
|
|
9
|
+
case "path":
|
|
10
|
+
return (
|
|
11
|
+
<path
|
|
12
|
+
d={element.d}
|
|
13
|
+
fill={fill}
|
|
14
|
+
stroke={stroke}
|
|
15
|
+
transform={element.transform}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
case "circle":
|
|
12
19
|
return (
|
|
13
20
|
<circle
|
|
14
21
|
cx={element.cx}
|
|
@@ -18,7 +25,7 @@ function GlyphElement({ element }: { element: SuiteGlyphElement }) {
|
|
|
18
25
|
stroke={stroke}
|
|
19
26
|
/>
|
|
20
27
|
);
|
|
21
|
-
case
|
|
28
|
+
case "rect":
|
|
22
29
|
return (
|
|
23
30
|
<rect
|
|
24
31
|
x={element.x}
|
|
@@ -55,7 +62,7 @@ export function GlyphParts({
|
|
|
55
62
|
{accented.length > 0 ? (
|
|
56
63
|
<g
|
|
57
64
|
className={accentClassName}
|
|
58
|
-
style={{ color:
|
|
65
|
+
style={{ color: "var(--suite-icon-accent, currentColor)" }}
|
|
59
66
|
>
|
|
60
67
|
{accented.map((el, i) => (
|
|
61
68
|
<GlyphElement key={i} element={el} />
|