@exxatdesignux/ui 0.2.14 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -1
  3. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +3 -0
  4. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +3 -1
  5. package/consumer-extras/patterns/collaboration-access-pattern.md +2 -0
  6. package/package.json +1 -1
  7. package/src/components/ui/dropdown-menu.tsx +2 -0
  8. package/src/components/ui/popover.tsx +2 -2
  9. package/src/components/ui/select.tsx +1 -1
  10. package/src/components/ui/tooltip.tsx +7 -1
  11. package/src/globals.css +27 -2
  12. package/src/theme.css +4 -2
  13. package/template/AGENTS.md +6 -4
  14. package/template/app/(app)/question-bank/layout.tsx +11 -4
  15. package/template/app/globals.css +34 -2
  16. package/template/components/app-sidebar.tsx +89 -41
  17. package/template/components/ask-leo-sidebar.tsx +1 -2
  18. package/template/components/compliance-board-view.tsx +11 -3
  19. package/template/components/compliance-list-view.tsx +16 -3
  20. package/template/components/compliance-table.tsx +5 -1
  21. package/template/components/data-table/index.tsx +25 -11
  22. package/template/components/data-views/finder-panel-view.tsx +2 -2
  23. package/template/components/data-views/index.ts +19 -0
  24. package/template/components/data-views/list-page-split-details-placeholder.tsx +3 -3
  25. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -1
  26. package/template/components/data-views/list-page-tree-column-header.tsx +1 -1
  27. package/template/components/data-views/outline-tree-menu.tsx +157 -0
  28. package/template/components/data-views/question-bank-folder-tree-branch.tsx +210 -0
  29. package/template/components/exxat-product-logo.tsx +11 -72
  30. package/template/components/folder-details-shell.tsx +1 -1
  31. package/template/components/hub-tree-panel-view.tsx +88 -80
  32. package/template/components/key-metrics.tsx +50 -13
  33. package/template/components/page-header.tsx +19 -10
  34. package/template/components/product-switcher.tsx +1 -4
  35. package/template/components/question-bank-board-view.tsx +11 -2
  36. package/template/components/question-bank-client.tsx +111 -69
  37. package/template/components/question-bank-list-view.tsx +12 -1
  38. package/template/components/question-bank-page-header.tsx +18 -2
  39. package/template/components/question-bank-secondary-nav.tsx +12 -225
  40. package/template/components/question-bank-table.tsx +6 -1
  41. package/template/components/secondary-panel.tsx +1 -1
  42. package/template/components/site-header.tsx +21 -2
  43. package/template/components/team-board-view.tsx +11 -3
  44. package/template/components/team-list-view.tsx +16 -3
  45. package/template/components/team-table.tsx +6 -2
  46. package/template/components/templates/dedicated-search-landing-template.tsx +86 -20
  47. package/template/components/templates/list-page.tsx +1 -3
  48. package/template/components/templates/nested-secondary-panel-shell.tsx +3 -4
  49. package/template/docs/collaboration-access-pattern.md +2 -0
  50. package/template/docs/question-bank-hub-header-pattern.md +25 -0
  51. package/template/hooks/use-secondary-panel-hub-nav.ts +17 -1
  52. package/template/lib/mock/navigation.tsx +30 -1
  53. package/template/lib/question-bank-nav.ts +26 -0
  54. package/template/package.json +3 -3
  55. package/template/components/command-menu-01.tsx +0 -133
  56. package/template/components/command-menu-02.tsx +0 -386
@@ -0,0 +1,157 @@
1
+ "use client"
2
+
3
+ /**
4
+ * Central outline-tree chrome — mirrors shadcn/ui **Sidebar** file-tree structure
5
+ * (`SidebarMenu` → `SidebarMenuItem` + `Collapsible` → `SidebarMenuSub` → rows) without
6
+ * coupling to `useSidebar`.
7
+ *
8
+ * - **`guideLayout="inset"`** — same rhythm as `SidebarMenuSub` (`mx-3.5` + `translate-x-px`).
9
+ * - **`guideLayout="chevronRail"`** — use with **`OutlineTreeCollapsibleContentRail`**: a **`w-6`**
10
+ * spacer lines up the vertical guide with the **horizontal center** of a **`size-8`** chevron
11
+ * when the folder row uses **`px-2`** (8px padding + 16px half of 32px chevron hit target).
12
+ *
13
+ * @see packages/ui/src/components/ui/sidebar.tsx — `SidebarMenuSub`, `SidebarMenuSubItem`
14
+ */
15
+
16
+ import * as React from "react"
17
+ import { CollapsibleContent } from "@/components/ui/collapsible"
18
+ import { cn } from "@/lib/utils"
19
+
20
+ export type OutlineTreeSurface = "sidebar" | "panel"
21
+
22
+ export type OutlineTreeGuideLayout = "inset" | "chevronRail"
23
+
24
+ const outlineTreeSubInsetClass: Record<OutlineTreeSurface, string> = {
25
+ sidebar:
26
+ "mx-3.5 flex min-w-0 list-none translate-x-px flex-col gap-1 border-s border-sidebar-border px-2.5 py-0.5 rtl:-translate-x-px",
27
+ panel:
28
+ "mx-3.5 flex min-w-0 list-none translate-x-px flex-col gap-1 border-s border-border/60 px-2.5 py-0.5 rtl:-translate-x-px",
29
+ }
30
+
31
+ const outlineTreeSubChevronRailClass: Record<OutlineTreeSurface, string> = {
32
+ sidebar:
33
+ "flex min-w-0 flex-1 list-none flex-col gap-1 border-s border-sidebar-border py-0.5 ps-2.5",
34
+ panel: "flex min-w-0 flex-1 list-none flex-col gap-1 border-s border-border/60 py-0.5 ps-2.5",
35
+ }
36
+
37
+ /** Pull row content onto the guide line — matches `SidebarMenuSubButton` horizontal nudge (inset layout only). */
38
+ export const OUTLINE_TREE_SUB_ROW_SHIFT_CLASS = "-translate-x-px rtl:translate-x-px"
39
+
40
+ /** `CollapsibleContent` row: spacer width = `px-2` (8px) + half of `size-8` chevron (16px) → guide under chevron center. */
41
+ export const OUTLINE_TREE_COLLAPSIBLE_CONTENT_RAIL_CLASS = "flex min-w-0 w-full"
42
+
43
+ /** Spacer column — keep in sync with folder row `px-2` + `size-8` chevron. */
44
+ export const OUTLINE_TREE_CHEVRON_GUIDE_SPACER_CLASS = "w-6 shrink-0"
45
+
46
+ /** Wrap `OutlineTreeSub` with `guideLayout="chevronRail"` so the vertical border meets the chevron center. */
47
+ export function OutlineTreeCollapsibleContentRail({
48
+ className,
49
+ children,
50
+ ...props
51
+ }: React.ComponentProps<typeof CollapsibleContent>) {
52
+ return (
53
+ <CollapsibleContent
54
+ className={cn(OUTLINE_TREE_COLLAPSIBLE_CONTENT_RAIL_CLASS, className)}
55
+ {...props}
56
+ >
57
+ <div className={OUTLINE_TREE_CHEVRON_GUIDE_SPACER_CLASS} aria-hidden />
58
+ {children}
59
+ </CollapsibleContent>
60
+ )
61
+ }
62
+
63
+ /** Nested list under a folder — vertical guide + indent. */
64
+ export function OutlineTreeSub({
65
+ surface = "panel",
66
+ guideLayout = "inset",
67
+ className,
68
+ ...props
69
+ }: React.ComponentProps<"ul"> & {
70
+ surface?: OutlineTreeSurface
71
+ guideLayout?: OutlineTreeGuideLayout
72
+ }) {
73
+ return (
74
+ <ul
75
+ data-slot="outline-tree-sub"
76
+ data-guide-layout={guideLayout}
77
+ className={cn(
78
+ guideLayout === "inset" && outlineTreeSubInsetClass[surface],
79
+ guideLayout === "chevronRail" && outlineTreeSubChevronRailClass[surface],
80
+ className,
81
+ )}
82
+ {...props}
83
+ />
84
+ )
85
+ }
86
+
87
+ /** Root or nested branch list — matches `SidebarMenu` spacing. */
88
+ export function OutlineTreeMenu({ className, ...props }: React.ComponentProps<"ul">) {
89
+ return (
90
+ <ul
91
+ data-slot="outline-tree-menu"
92
+ className={cn("flex w-full min-w-0 list-none flex-col gap-0", className)}
93
+ {...props}
94
+ />
95
+ )
96
+ }
97
+
98
+ /** Expandable folder row wrapper — matches `SidebarMenuItem`. */
99
+ export function OutlineTreeMenuItem({ className, ...props }: React.ComponentProps<"li">) {
100
+ return (
101
+ <li
102
+ data-slot="outline-tree-menu-item"
103
+ className={cn("group/menu-item relative min-w-0 w-full list-none", className)}
104
+ {...props}
105
+ />
106
+ )
107
+ }
108
+
109
+ /** Leaf / nested row inside `OutlineTreeSub` — matches `SidebarMenuSubItem`. */
110
+ export function OutlineTreeSubItem({ className, ...props }: React.ComponentProps<"li">) {
111
+ return (
112
+ <li
113
+ data-slot="outline-tree-sub-item"
114
+ className={cn("group/menu-sub-item relative min-w-0 w-full list-none", className)}
115
+ {...props}
116
+ />
117
+ )
118
+ }
119
+
120
+ export interface OutlineTreeLeafButtonProps extends React.ComponentProps<"button"> {
121
+ surface?: OutlineTreeSurface
122
+ isActive?: boolean
123
+ /** Inset `OutlineTreeSub` only — nudge like `SidebarMenuSubButton`. Ignored when parent uses `chevronRail`. */
124
+ subGuideAlign?: boolean
125
+ }
126
+
127
+ /** Selectable leaf row (file / terminal row) — `SidebarMenuSubButton`–aligned rhythm. */
128
+ export function OutlineTreeLeafButton({
129
+ surface = "panel",
130
+ isActive = false,
131
+ subGuideAlign = false,
132
+ className,
133
+ ...props
134
+ }: OutlineTreeLeafButtonProps) {
135
+ return (
136
+ <button
137
+ type="button"
138
+ data-active={isActive || undefined}
139
+ className={cn(
140
+ "flex min-h-8 w-full min-w-0 cursor-pointer select-none items-center gap-2 overflow-hidden rounded-md px-2 text-start text-sm outline-none ring-ring focus-visible:ring-2 focus-visible:ring-inset [&>svg]:size-4 [&>svg]:shrink-0",
141
+ subGuideAlign && OUTLINE_TREE_SUB_ROW_SHIFT_CLASS,
142
+ surface === "panel" &&
143
+ cn(
144
+ "text-foreground hover:bg-muted/50",
145
+ isActive && "bg-accent font-medium text-accent-foreground",
146
+ ),
147
+ surface === "sidebar" &&
148
+ cn(
149
+ "text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
150
+ isActive && "bg-sidebar-accent font-medium text-sidebar-accent-foreground",
151
+ ),
152
+ className,
153
+ )}
154
+ {...props}
155
+ />
156
+ )
157
+ }
@@ -0,0 +1,210 @@
1
+ "use client"
2
+
3
+ /**
4
+ * Question bank **Folders** tree — shared outline primitives (`OutlineTree*`) so the rail
5
+ * matches `HubTreePanelView` and shadcn sidebar file-tree rhythm.
6
+ */
7
+
8
+ import * as React from "react"
9
+ import Link from "next/link"
10
+ import { Collapsible, CollapsibleTrigger } from "@/components/ui/collapsible"
11
+ import { Button } from "@/components/ui/button"
12
+ import {
13
+ DropdownMenu,
14
+ DropdownMenuContent,
15
+ DropdownMenuItem,
16
+ DropdownMenuSeparator,
17
+ DropdownMenuTrigger,
18
+ } from "@/components/ui/dropdown-menu"
19
+ import { Tip } from "@/components/ui/tip"
20
+ import { cn } from "@/lib/utils"
21
+ import {
22
+ OutlineTreeCollapsibleContentRail,
23
+ OutlineTreeMenuItem,
24
+ OutlineTreeSub,
25
+ } from "@/components/data-views/outline-tree-menu"
26
+ import type { QuestionBankFolder } from "@/lib/mock/question-bank-folders"
27
+ import { QUESTION_BANK_FOLDER_ICON_COLORS } from "@/lib/mock/question-bank-folders"
28
+ import {
29
+ isQuestionBankNavActive,
30
+ questionBankHubScopeHref,
31
+ type QuestionBankNavState,
32
+ } from "@/lib/question-bank-nav"
33
+
34
+ export interface QuestionBankFolderTreeBranchProps {
35
+ folder: QuestionBankFolder
36
+ folders: QuestionBankFolder[]
37
+ pathname: string
38
+ hubSearchParams: URLSearchParams
39
+ nav: QuestionBankNavState
40
+ canManageFolders: boolean
41
+ canManageAccess: boolean
42
+ onAddSubfolder: (parentId: string) => void
43
+ onCustomizeFolder: (folder: QuestionBankFolder) => void
44
+ onManageAccess: () => void
45
+ onDeleteFolder: (folder: QuestionBankFolder) => void
46
+ }
47
+
48
+ export function QuestionBankFolderTreeBranch({
49
+ folder,
50
+ folders,
51
+ pathname,
52
+ hubSearchParams,
53
+ nav,
54
+ canManageFolders,
55
+ canManageAccess,
56
+ onAddSubfolder,
57
+ onCustomizeFolder,
58
+ onManageAccess,
59
+ onDeleteFolder,
60
+ }: QuestionBankFolderTreeBranchProps) {
61
+ const childFolders = React.useMemo(
62
+ () =>
63
+ folders
64
+ .filter(f => f.parentId === folder.id)
65
+ .sort((a, b) => a.name.localeCompare(b.name)),
66
+ [folders, folder.id],
67
+ )
68
+
69
+ const hasSubfolders = childFolders.length > 0
70
+ const isRootFolder = folder.parentId === null
71
+
72
+ const folderHref = questionBankHubScopeHref(pathname, hubSearchParams, {
73
+ scope: "folder",
74
+ folderId: folder.id,
75
+ })
76
+ const folderActive = isQuestionBankNavActive(pathname, nav, "folder", folder.id)
77
+
78
+ return (
79
+ <Collapsible defaultOpen={isRootFolder} className="group/collapsible">
80
+ <div
81
+ className={cn(
82
+ "group/row flex min-w-0 items-center rounded-md px-2 transition-colors",
83
+ folderActive
84
+ ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground ring-1 ring-inset ring-sidebar-border/80"
85
+ : "text-sidebar-foreground hover:bg-sidebar-accent/50",
86
+ )}
87
+ >
88
+ {hasSubfolders ? (
89
+ <CollapsibleTrigger asChild>
90
+ <button
91
+ type="button"
92
+ className="flex size-8 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
93
+ aria-label={`${folder.name} — expand or collapse`}
94
+ >
95
+ <i
96
+ className="fa-light fa-chevron-right text-xs transition-transform duration-150 group-data-[state=open]/collapsible:rotate-90"
97
+ aria-hidden
98
+ />
99
+ </button>
100
+ </CollapsibleTrigger>
101
+ ) : (
102
+ <div className="size-8 shrink-0" aria-hidden />
103
+ )}
104
+ <Tip label={folder.name} side="right">
105
+ <Link
106
+ href={folderHref}
107
+ scroll={false}
108
+ aria-current={folderActive ? "page" : undefined}
109
+ className={cn(
110
+ "flex min-w-0 flex-1 items-center gap-2 py-1.5 text-left text-sm transition-colors",
111
+ "rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
112
+ !folderActive && "text-sidebar-foreground",
113
+ )}
114
+ >
115
+ <i
116
+ className={cn(
117
+ "fa-light inline-flex size-4 shrink-0 items-center justify-center text-sm leading-none",
118
+ folder.icon,
119
+ QUESTION_BANK_FOLDER_ICON_COLORS[folder.colorKey],
120
+ )}
121
+ aria-hidden
122
+ />
123
+ <span className="min-w-0 flex-1 truncate leading-tight">{folder.name}</span>
124
+ {hasSubfolders ? (
125
+ <span className="shrink-0 text-xs tabular-nums text-muted-foreground">{childFolders.length}</span>
126
+ ) : null}
127
+ </Link>
128
+ </Tip>
129
+ {canManageFolders ? (
130
+ <DropdownMenu>
131
+ <Tip label={`Folder actions for ${folder.name}`} side="right">
132
+ <DropdownMenuTrigger asChild>
133
+ <Button
134
+ type="button"
135
+ size="icon-xs"
136
+ variant="ghost"
137
+ aria-label={`Folder actions for ${folder.name}`}
138
+ className="shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover/row:opacity-100 group-focus-within/row:opacity-100"
139
+ onClick={event => event.stopPropagation()}
140
+ >
141
+ <i className="fa-light fa-ellipsis text-xs" aria-hidden="true" />
142
+ </Button>
143
+ </DropdownMenuTrigger>
144
+ </Tip>
145
+ <DropdownMenuContent align="end">
146
+ <DropdownMenuItem
147
+ onSelect={() => {
148
+ window.setTimeout(() => onAddSubfolder(folder.id), 0)
149
+ }}
150
+ >
151
+ <i className="fa-light fa-plus text-xs" aria-hidden="true" />
152
+ Add folder
153
+ </DropdownMenuItem>
154
+ <DropdownMenuItem
155
+ onSelect={() => {
156
+ window.setTimeout(() => onCustomizeFolder(folder), 0)
157
+ }}
158
+ >
159
+ <i className="fa-light fa-wand-magic-sparkles text-xs" aria-hidden="true" />
160
+ Customize
161
+ </DropdownMenuItem>
162
+ <DropdownMenuItem
163
+ disabled={!canManageAccess}
164
+ onSelect={() => {
165
+ window.setTimeout(() => onManageAccess(), 0)
166
+ }}
167
+ >
168
+ <i className="fa-light fa-user-gear text-xs" aria-hidden="true" />
169
+ Manage access
170
+ </DropdownMenuItem>
171
+ <DropdownMenuSeparator />
172
+ <DropdownMenuItem
173
+ variant="destructive"
174
+ onSelect={() => {
175
+ window.setTimeout(() => onDeleteFolder(folder), 0)
176
+ }}
177
+ >
178
+ <i className="fa-light fa-trash text-xs" aria-hidden="true" />
179
+ Delete
180
+ </DropdownMenuItem>
181
+ </DropdownMenuContent>
182
+ </DropdownMenu>
183
+ ) : null}
184
+ </div>
185
+ {hasSubfolders ? (
186
+ <OutlineTreeCollapsibleContentRail>
187
+ <OutlineTreeSub surface="sidebar" guideLayout="chevronRail">
188
+ {childFolders.map(child => (
189
+ <OutlineTreeMenuItem key={child.id}>
190
+ <QuestionBankFolderTreeBranch
191
+ folder={child}
192
+ folders={folders}
193
+ pathname={pathname}
194
+ hubSearchParams={hubSearchParams}
195
+ nav={nav}
196
+ canManageFolders={canManageFolders}
197
+ canManageAccess={canManageAccess}
198
+ onAddSubfolder={onAddSubfolder}
199
+ onCustomizeFolder={onCustomizeFolder}
200
+ onManageAccess={onManageAccess}
201
+ onDeleteFolder={onDeleteFolder}
202
+ />
203
+ </OutlineTreeMenuItem>
204
+ ))}
205
+ </OutlineTreeSub>
206
+ </OutlineTreeCollapsibleContentRail>
207
+ ) : null}
208
+ </Collapsible>
209
+ )
210
+ }
@@ -3,7 +3,9 @@
3
3
  /**
4
4
  * Inline product wordmarks — "Exxat" letters are gray (#273441) on light,
5
5
  * soft grey (#A8B2BA) on dark/HC; product name letters (One/Prism) use
6
- * brand pink (#E31B79) by default. The circular mark + gradient are unchanged.
6
+ * brand pink (#E31B79) by default.
7
+ *
8
+ * **Circular mark** (`ExxatProductMark`): always the Exxat One mark; wordmarks stay per-product.
7
9
  *
8
10
  * `variant="mutedSuffix"` (sidebar / switcher): in **dark** mode only, the full wordmark
9
11
  * uses one `muted-foreground`. In **light** mode the original pink + grey wordmark is kept.
@@ -168,12 +170,16 @@ function ExxatOneLogo({
168
170
  function ExxatOneMark({ className, ...props }: React.ComponentProps<"svg">) {
169
171
  const ready = useBrowserPaintReady()
170
172
  const paint0 = useMarkGradientId("one-mark")
171
- const sharedClass = cn("block shrink-0", className)
173
+ const sharedClass = cn(
174
+ "box-border block aspect-square size-7 shrink-0 flex-none object-contain",
175
+ className,
176
+ )
172
177
 
173
178
  if (!ready) {
174
179
  return (
175
180
  <svg
176
181
  viewBox="0 8.25 147 147"
182
+ preserveAspectRatio="xMidYMid meet"
177
183
  fill="none"
178
184
  xmlns="http://www.w3.org/2000/svg"
179
185
  data-product-logo-mark
@@ -188,6 +194,7 @@ function ExxatOneMark({ className, ...props }: React.ComponentProps<"svg">) {
188
194
  return (
189
195
  <svg
190
196
  viewBox="0 8.25 147 147"
197
+ preserveAspectRatio="xMidYMid meet"
191
198
  fill="none"
192
199
  xmlns="http://www.w3.org/2000/svg"
193
200
  data-product-logo-mark
@@ -229,81 +236,13 @@ function ExxatOneMark({ className, ...props }: React.ComponentProps<"svg">) {
229
236
  )
230
237
  }
231
238
 
232
- function ExxatPrismMark({ className, ...props }: React.ComponentProps<"svg">) {
233
- const ready = useBrowserPaintReady()
234
- const paint0 = useMarkGradientId("prism-mark")
235
- const sharedClass = cn("block shrink-0", className)
236
-
237
- if (!ready) {
238
- return (
239
- <svg
240
- viewBox="0 8.25 147 147"
241
- fill="none"
242
- xmlns="http://www.w3.org/2000/svg"
243
- data-product-logo-mark
244
- className={sharedClass}
245
- aria-hidden
246
- suppressHydrationWarning
247
- {...props}
248
- />
249
- )
250
- }
251
-
252
- return (
253
- <svg
254
- viewBox="0 8.25 147 147"
255
- fill="none"
256
- xmlns="http://www.w3.org/2000/svg"
257
- data-product-logo-mark
258
- className={sharedClass}
259
- aria-hidden
260
- suppressHydrationWarning
261
- {...props}
262
- >
263
- <path
264
- d="M73.4939 155.238C114.084 155.238 146.988 122.334 146.988 81.7439C146.988 41.1544 114.084 8.25 73.4939 8.25C32.9044 8.25 0 41.1544 0 81.7439C0 122.334 32.9044 155.238 73.4939 155.238Z"
265
- fill={`url(#${paint0})`}
266
- />
267
- <path
268
- d="M0.490234 89.3652C3.79023 115.675 23.9702 136.725 49.8502 141.355L84.4302 110.265V98.6852H71.5502L84.4302 87.1052V75.5252H71.5502L84.4302 63.9452V52.3652H41.6602L0.490234 89.3652Z"
269
- fill="#BE1E6D"
270
- />
271
- <path d="M84.4397 110.265H41.6597L48.3497 98.6851H84.4397V110.265Z" fill="white" />
272
- <path d="M84.4397 63.935H48.3497L41.6597 52.355H84.4397V63.935Z" fill="white" />
273
- <path d="M84.44 87.0951H55.04L58.38 81.3051L55.04 75.5151H84.44V87.0951Z" fill="white" />
274
- <path d="M32.3198 75.5151H55.0398L48.3498 63.9351H32.3198V75.5151Z" fill="white" />
275
- <path d="M32.3198 98.6852H48.3498L55.0398 87.0952H32.3198V98.6852Z" fill="white" />
276
- <defs>
277
- <linearGradient
278
- id={paint0}
279
- x1="23.38"
280
- y1="125.015"
281
- x2="96.57"
282
- y2="39.8551"
283
- gradientUnits="userSpaceOnUse"
284
- >
285
- <stop offset="0.04" stopColor="#E21C79" />
286
- <stop offset="0.65" stopColor="#E21E7B" />
287
- <stop offset="0.73" stopColor="#E42880" />
288
- <stop offset="0.88" stopColor="#E9448E" />
289
- <stop offset="1" stopColor="#EF609D" />
290
- </linearGradient>
291
- </defs>
292
- </svg>
293
- )
294
- }
295
-
296
239
  export interface ExxatProductMarkProps {
297
240
  product: Product
298
241
  className?: string
299
242
  }
300
243
 
301
- export function ExxatProductMark({ product, className }: ExxatProductMarkProps) {
302
- return product === "exxat-prism" ? (
303
- <ExxatPrismMark className={className} />
304
- ) : (
305
- <ExxatOneMark className={className} />
306
- )
244
+ export function ExxatProductMark({ product: _product, className }: ExxatProductMarkProps) {
245
+ return <ExxatOneMark className={className} />
307
246
  }
308
247
 
309
248
  function ExxatPrismLogo({
@@ -102,7 +102,7 @@ export function FolderDetailsShell({
102
102
 
103
103
  return (
104
104
  <div className="flex h-full min-h-0 flex-col overflow-hidden bg-card">
105
- <header className="shrink-0 border-b border-border/60 bg-muted/10 px-4 pb-4 pt-4">
105
+ <header className="shrink-0 border-b border-border/60 bg-card px-4 pb-4 pt-4">
106
106
  <div className="flex items-start justify-between gap-3">
107
107
  <div className="flex min-w-0 flex-1 items-start gap-3">
108
108
  <OsFolderGlyph