@toolr/ui-design 0.1.8 → 0.1.9

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 (100) hide show
  1. package/ai-manifest.json +35 -20
  2. package/components/composites/dashboard-list-item.tsx +172 -0
  3. package/components/composites/dashboard-panel.tsx +218 -0
  4. package/components/content/info-panel-primitives.tsx +9 -8
  5. package/components/diagrams/diagram-utils.tsx +2 -1
  6. package/components/hooks/use-dropdown-portal.ts +39 -0
  7. package/components/lib/accent-context.ts +10 -0
  8. package/components/lib/{ai-tools.tsx → coding-agents.tsx} +23 -8
  9. package/components/lib/custom-icons.tsx +37 -0
  10. package/components/lib/git-providers.tsx +39 -0
  11. package/components/lib/theme-engine.ts +59 -10
  12. package/components/lib/toolr-brand.tsx +23 -9
  13. package/components/sections/captured-issues/captured-issues-panel.tsx +17 -8
  14. package/components/sections/{ai-tools-paths/tools-paths-panel.tsx → coding-agent-paths/agent-paths-panel.tsx} +70 -62
  15. package/components/sections/coding-agent-paths/index.ts +37 -0
  16. package/components/sections/{ai-tools-paths → coding-agent-paths}/types.ts +28 -28
  17. package/components/sections/coding-agent-paths/use-agent-paths.ts +159 -0
  18. package/components/sections/golden-snapshots/file-diff-viewer.tsx +10 -9
  19. package/components/sections/golden-snapshots/golden-sync-panel.tsx +12 -3
  20. package/components/sections/golden-snapshots/snapshot-manager.tsx +9 -7
  21. package/components/sections/golden-snapshots/status-overview.tsx +8 -8
  22. package/components/sections/golden-snapshots/version-manager.tsx +6 -6
  23. package/components/sections/prompt-editor/file-type-tabbed-prompt-editor.tsx +3 -3
  24. package/components/sections/prompt-editor/index.ts +1 -1
  25. package/components/sections/prompt-editor/simulator-prompt-editor.tsx +13 -5
  26. package/components/sections/prompt-editor/tabbed-prompt-editor.tsx +18 -10
  27. package/components/sections/prompt-editor/types.ts +2 -2
  28. package/components/sections/report-bug/report-bug-form.tsx +12 -4
  29. package/components/sections/report-bug/screenshot-uploader.tsx +11 -3
  30. package/components/sections/snapshot-browser/snapshot-browser-panel.tsx +12 -4
  31. package/components/sections/snapshot-browser/snapshot-tree.tsx +5 -4
  32. package/components/sections/snapshot-browser/types.ts +1 -1
  33. package/components/sections/snippets-editor/snippets-editor.tsx +16 -9
  34. package/components/settings/SettingsHeader.tsx +2 -2
  35. package/components/settings/SettingsPanel.tsx +11 -3
  36. package/components/settings/SettingsTreeNav.tsx +15 -9
  37. package/components/ui/action-dialog.tsx +24 -30
  38. package/components/ui/ai-action-button.tsx +10 -7
  39. package/components/ui/ai-execution-action-buttons.tsx +13 -5
  40. package/components/ui/badge.tsx +7 -4
  41. package/components/ui/bottom-panel-header.tsx +9 -5
  42. package/components/ui/breadcrumb.tsx +9 -1
  43. package/components/ui/{extension-list-card.tsx → capability-list-card.tsx} +13 -5
  44. package/components/ui/checkbox.tsx +6 -3
  45. package/components/ui/collapsible-section.tsx +38 -29
  46. package/components/ui/confirm-badge.tsx +7 -4
  47. package/components/ui/cookie-consent.tsx +13 -7
  48. package/components/ui/detail-section.tsx +24 -16
  49. package/components/ui/detail-view-wrapper.tsx +30 -22
  50. package/components/ui/editor-placeholder-card.tsx +28 -24
  51. package/components/ui/editor-toolbar.tsx +7 -4
  52. package/components/ui/execution-details-panel.tsx +10 -5
  53. package/components/ui/file-structure-section.tsx +3 -3
  54. package/components/ui/file-tree.tsx +3 -1
  55. package/components/ui/files-panel.tsx +147 -27
  56. package/components/ui/filter-dropdown.tsx +84 -74
  57. package/components/ui/form-actions.tsx +14 -6
  58. package/components/ui/frontmatter-form-header.tsx +10 -2
  59. package/components/ui/icon-button.tsx +22 -9
  60. package/components/ui/input.tsx +7 -4
  61. package/components/ui/label.tsx +5 -5
  62. package/components/ui/layout-tab-bar.tsx +7 -5
  63. package/components/ui/modal.tsx +18 -4
  64. package/components/ui/nav-card.tsx +6 -3
  65. package/components/ui/navigation-bar.tsx +37 -9
  66. package/components/ui/number-input.tsx +8 -4
  67. package/components/ui/project-explorer.tsx +666 -0
  68. package/components/ui/registry-browser.tsx +12 -1
  69. package/components/ui/registry-card.tsx +49 -42
  70. package/components/ui/registry-detail.tsx +34 -11
  71. package/components/ui/resizable-textarea.tsx +18 -11
  72. package/components/ui/scope-badge.tsx +18 -11
  73. package/components/ui/segmented-toggle.tsx +5 -2
  74. package/components/ui/select.tsx +12 -9
  75. package/components/ui/selection-grid.tsx +36 -37
  76. package/components/ui/setting-row.tsx +2 -2
  77. package/components/ui/settings-card.tsx +10 -3
  78. package/components/ui/settings-info-box.tsx +9 -5
  79. package/components/ui/settings-section-title.tsx +14 -2
  80. package/components/ui/snapshot-card.tsx +10 -2
  81. package/components/ui/snippets-panel.tsx +4 -2
  82. package/components/ui/sort-dropdown.tsx +39 -29
  83. package/components/ui/status-card.tsx +9 -1
  84. package/components/ui/tab-bar.tsx +12 -9
  85. package/components/ui/toggle.tsx +13 -7
  86. package/components/ui/tooltip.tsx +9 -1
  87. package/dist/content.js +8 -8
  88. package/dist/diagrams.d.ts +0 -1
  89. package/dist/index.d.ts +421 -182
  90. package/dist/index.js +2984 -1691
  91. package/dist/tokens/primitives.css +28 -6
  92. package/dist/tokens/semantic.css +15 -15
  93. package/dist/tokens/theme.css +23 -0
  94. package/index.ts +25 -11
  95. package/package.json +1 -1
  96. package/tokens/primitives.css +28 -6
  97. package/tokens/semantic.css +15 -15
  98. package/tokens/theme.css +23 -0
  99. package/components/sections/ai-tools-paths/index.ts +0 -37
  100. package/components/sections/ai-tools-paths/use-tools-paths.ts +0 -159
@@ -3,6 +3,7 @@ import { RefreshCw } from 'lucide-react'
3
3
  import { IconButton, type IconName, type ActionItem, iconMap } from './icon-button.tsx'
4
4
  import { Badge, type BadgeColor } from './badge.tsx'
5
5
  import { Tooltip } from './tooltip.tsx'
6
+ import type { FormColor } from '../lib/form-colors.ts'
6
7
 
7
8
  /** Status banner configuration for outdated/info messages */
8
9
  export interface StatusBanner {
@@ -59,11 +60,12 @@ export interface BottomPanelHeaderProps<T extends string = string> {
59
60
  statusBanner?: StatusBanner
60
61
  /** Callback when collapse button is clicked */
61
62
  onCollapse?: () => void
63
+ accentColor?: FormColor
62
64
  }
63
65
 
64
66
  // Default styling classes
65
67
  const DEFAULT_ACTIVE_TEXT = 'text-neutral-300'
66
- const DEFAULT_INACTIVE_CLASSES = 'border-transparent text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800/30'
68
+ const DEFAULT_INACTIVE_CLASSES = 'border-transparent text-neutral-500 hover:text-neutral-300 hover:bg-neutral-960/30'
67
69
 
68
70
  // Layout mode: full → compact banner → compact tabs
69
71
  type LayoutMode = 'full' | 'compact-banner' | 'compact-all'
@@ -93,6 +95,7 @@ export function BottomPanelHeader<T extends string = string>({
93
95
  customLeftContent,
94
96
  statusBanner,
95
97
  onCollapse,
98
+ accentColor: _accentColor,
96
99
  }: BottomPanelHeaderProps<T>) {
97
100
  const containerRef = useRef<HTMLDivElement>(null)
98
101
  const actionsRef = useRef<HTMLDivElement>(null)
@@ -140,7 +143,7 @@ export function BottomPanelHeader<T extends string = string>({
140
143
  return (
141
144
  <div
142
145
  ref={containerRef}
143
- className={`flex-shrink-0 h-[41px] flex justify-between bg-neutral-900 border-b border-neutral-800 ${className}`}
146
+ className={`flex-shrink-0 h-[41px] flex justify-between bg-neutral-980 border-b border-neutral-960 ${className}`}
144
147
  >
145
148
  {/* Tabs or custom content - left aligned */}
146
149
  <div className="flex flex-shrink-0">
@@ -156,7 +159,7 @@ export function BottomPanelHeader<T extends string = string>({
156
159
  ? tab.activeBorderClass || 'border-current'
157
160
  : ''
158
161
  const baseClasses = isActive
159
- ? `${textClass} ${borderClass} bg-neutral-800/50`
162
+ ? `${textClass} ${borderClass} bg-neutral-960/50`
160
163
  : DEFAULT_INACTIVE_CLASSES
161
164
  const tabButton = (
162
165
  <button
@@ -170,7 +173,7 @@ export function BottomPanelHeader<T extends string = string>({
170
173
  {TabIcon && <TabIcon className="w-[18px] h-[18px]" />}
171
174
  {tab.count !== undefined && (
172
175
  <span className="absolute -top-1.5 -right-2">
173
- <Badge value={tab.count} color={tab.countColor} size="xss" />
176
+ <Badge value={tab.count} accentColor={tab.countColor} size="xss" />
174
177
  </span>
175
178
  )}
176
179
  </span>
@@ -185,7 +188,7 @@ export function BottomPanelHeader<T extends string = string>({
185
188
  <span>{tab.label}</span>
186
189
  )}
187
190
  {tab.count !== undefined && (
188
- <Badge value={tab.count} color={tab.countColor} size="xss" />
191
+ <Badge value={tab.count} accentColor={tab.countColor} size="xss" />
189
192
  )}
190
193
  </>
191
194
  )}
@@ -231,6 +234,7 @@ export function BottomPanelHeader<T extends string = string>({
231
234
  icon="panel-bottom-close"
232
235
  onClick={onCollapse}
233
236
  size="sm"
237
+ accentColor="neutral"
234
238
  tooltip={{ description: 'Collapse panel' }}
235
239
  />
236
240
  )}
@@ -3,6 +3,8 @@
3
3
  import { ChevronRight } from 'lucide-react'
4
4
  import { iconMap, type IconName } from './icon-button.tsx'
5
5
  import { ACCENT_NAV, type AccentColor } from '../lib/form-colors.ts'
6
+ import type { FormColor } from '../lib/form-colors.ts'
7
+ import { AccentColorProvider, useAccentColor } from '../lib/accent-context.ts'
6
8
  import { cn } from '../lib/cn.ts'
7
9
 
8
10
  export interface BreadcrumbSegment {
@@ -20,6 +22,7 @@ export interface BreadcrumbProps {
20
22
  /** 'box' (default) wraps in a bordered container; 'plain' renders inline with no background */
21
23
  variant?: 'box' | 'plain'
22
24
  className?: string
25
+ accentColor?: FormColor
23
26
  }
24
27
 
25
28
  const sizeConfig = {
@@ -62,15 +65,19 @@ export function Breadcrumb({
62
65
  size = 'sm',
63
66
  variant = 'box',
64
67
  className,
68
+ accentColor,
65
69
  }: BreadcrumbProps) {
70
+ const contextAccent = useAccentColor()
71
+ const effectiveColor = accentColor ?? contextAccent ?? 'blue'
66
72
  const s = sizeConfig[size]
67
73
  const isBox = variant === 'box'
68
74
 
69
75
  return (
76
+ <AccentColorProvider value={effectiveColor}>
70
77
  <nav className={cn('flex items-center min-w-0', className)}>
71
78
  <div className={cn(
72
79
  'flex items-center gap-1',
73
- isBox && [s.px, s.py, 'bg-neutral-800/50 border border-neutral-700/50 rounded-lg'],
80
+ isBox && [s.px, s.py, 'bg-neutral-960/50 border border-neutral-700/50 rounded-lg'],
74
81
  )}>
75
82
  {segments.map((segment, index) => {
76
83
  const isLast = index === segments.length - 1
@@ -116,5 +123,6 @@ export function Breadcrumb({
116
123
  })}
117
124
  </div>
118
125
  </nav>
126
+ </AccentColorProvider>
119
127
  )
120
128
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ExtensionListCard — Standardized card for extension list view items.
2
+ * CapabilityListCard — Standardized card for capability list view items.
3
3
  *
4
4
  * Used across apps for skill, command, hook, agent, plugin, MCP server,
5
5
  * Gemini extension, and marketplace cards.
@@ -14,8 +14,10 @@
14
14
 
15
15
  import { memo, useState, useRef, useCallback, useEffect, type ReactNode, type ElementType } from 'react'
16
16
  import { cn } from '../lib/cn.ts'
17
+ import type { FormColor } from '../lib/form-colors.ts'
18
+ import { useAccentColor, AccentColorProvider } from '../lib/accent-context.ts'
17
19
 
18
- export interface ExtensionListCardProps {
20
+ export interface CapabilityListCardProps {
19
21
  /** Lucide icon component */
20
22
  icon: ElementType
21
23
  /** Tailwind color class for icon (e.g. 'text-teal-400') */
@@ -38,9 +40,10 @@ export interface ExtensionListCardProps {
38
40
  isInactive?: boolean
39
41
  /** Test ID for E2E testing */
40
42
  testId?: string
43
+ accentColor?: FormColor
41
44
  }
42
45
 
43
- export const ExtensionListCard = memo(function ExtensionListCard({
46
+ export const CapabilityListCard = memo(function CapabilityListCard({
44
47
  icon: Icon,
45
48
  iconColor,
46
49
  borderColor,
@@ -52,7 +55,10 @@ export const ExtensionListCard = memo(function ExtensionListCard({
52
55
  metadata,
53
56
  isInactive,
54
57
  testId,
55
- }: ExtensionListCardProps) {
58
+ accentColor: accentColorProp,
59
+ }: CapabilityListCardProps) {
60
+ const contextAccent = useAccentColor()
61
+ const effectiveColor = accentColorProp ?? contextAccent ?? 'blue'
56
62
  const [isHovered, setIsHovered] = useState(false)
57
63
  const hoverTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined)
58
64
  useEffect(() => () => clearTimeout(hoverTimerRef.current), [])
@@ -65,9 +71,10 @@ export const ExtensionListCard = memo(function ExtensionListCard({
65
71
  }, [])
66
72
 
67
73
  return (
74
+ <AccentColorProvider value={effectiveColor}>
68
75
  <div
69
76
  className={cn(
70
- 'relative flex flex-col p-3 bg-neutral-800/50 rounded-lg border border-neutral-700/50 border-l-4 hover:bg-neutral-800 transition-colors',
77
+ 'relative flex flex-col p-3 bg-neutral-960/50 rounded-lg border border-neutral-700/50 border-l-4 hover:bg-neutral-960 transition-colors',
71
78
  borderColor,
72
79
  isInactive && 'opacity-60',
73
80
  isHovered ? 'h-auto z-10' : 'h-full',
@@ -101,5 +108,6 @@ export const ExtensionListCard = memo(function ExtensionListCard({
101
108
  </div>
102
109
  )}
103
110
  </div>
111
+ </AccentColorProvider>
104
112
  )
105
113
  })
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { Check } from 'lucide-react'
11
11
  import { type AccentColor } from '../lib/form-colors.ts'
12
+ import { useAccentColor } from '../lib/accent-context.ts'
12
13
  import { cn } from '../lib/cn.ts'
13
14
 
14
15
  export type CheckboxSize = 'xss' | 'xs' | 'sm' | 'md' | 'lg'
@@ -48,7 +49,7 @@ export interface CheckboxProps {
48
49
  onChange: (checked: boolean) => void
49
50
  disabled?: boolean
50
51
  size?: CheckboxSize
51
- color?: CheckboxColor
52
+ accentColor?: CheckboxColor
52
53
  variant?: CheckboxVariant
53
54
  className?: string
54
55
  /** Accessible label — required for screen readers */
@@ -62,14 +63,16 @@ export function Checkbox({
62
63
  onChange,
63
64
  disabled = false,
64
65
  size = 'sm',
65
- color = 'blue',
66
+ accentColor,
66
67
  variant = 'outline',
67
68
  className,
68
69
  'aria-label': ariaLabel,
69
70
  testId,
70
71
  }: CheckboxProps) {
72
+ const contextAccent = useAccentColor()
73
+ const effectiveColor = accentColor ?? contextAccent ?? 'blue'
71
74
  const s = CHECKBOX_SIZES[size]
72
- const c = CHECKBOX_COLORS[color]
75
+ const c = CHECKBOX_COLORS[effectiveColor]
73
76
  return (
74
77
  <button
75
78
  type="button"
@@ -3,6 +3,9 @@ import { ChevronRight } from 'lucide-react'
3
3
  import { iconMap, type IconName } from './icon-button.tsx'
4
4
  import { Badge, type BadgeColor } from './badge.tsx'
5
5
  import { cn } from '../lib/cn.ts'
6
+ import { useAccentColor } from '../lib/accent-context.ts'
7
+ import { AccentColorProvider } from '../lib/accent-context.ts'
8
+ import type { FormColor } from '../lib/form-colors.ts'
6
9
 
7
10
  export interface CollapsibleSectionProps {
8
11
  title: string
@@ -13,6 +16,7 @@ export interface CollapsibleSectionProps {
13
16
  badgeColor?: BadgeColor
14
17
  children: React.ReactNode
15
18
  className?: string
19
+ accentColor?: FormColor
16
20
  }
17
21
 
18
22
  export function CollapsibleSection({
@@ -24,40 +28,45 @@ export function CollapsibleSection({
24
28
  badgeColor,
25
29
  children,
26
30
  className,
31
+ accentColor,
27
32
  }: CollapsibleSectionProps) {
33
+ const contextAccent = useAccentColor()
34
+ const effectiveColor = accentColor ?? contextAccent ?? 'blue'
28
35
  const [open, setOpen] = useState(defaultOpen)
29
36
  const Icon = icon ? iconMap[icon] : undefined
30
37
 
31
38
  return (
32
- <div className={cn('border-b border-neutral-700', className)}>
33
- <button
34
- type="button"
35
- aria-expanded={open}
36
- onClick={() => setOpen(!open)}
37
- className="flex w-full items-center gap-2 py-2.5 px-1 text-left hover:bg-neutral-700/30 transition-colors cursor-pointer"
38
- >
39
- <ChevronRight
40
- className={cn(
41
- 'w-3.5 h-3.5 text-neutral-500 transition-transform duration-150',
42
- open && 'rotate-90',
39
+ <AccentColorProvider value={effectiveColor}>
40
+ <div className={cn('border-b border-neutral-700', className)}>
41
+ <button
42
+ type="button"
43
+ aria-expanded={open}
44
+ onClick={() => setOpen(!open)}
45
+ className="flex w-full items-center gap-2 py-2.5 px-1 text-left hover:bg-neutral-700/30 transition-colors cursor-pointer"
46
+ >
47
+ <ChevronRight
48
+ className={cn(
49
+ 'w-3.5 h-3.5 text-neutral-500 transition-transform duration-150',
50
+ open && 'rotate-90',
51
+ )}
52
+ />
53
+ {Icon && (
54
+ <span
55
+ className="flex items-center justify-center w-5 h-5 rounded bg-neutral-700/60"
56
+ style={iconColor ? { color: iconColor } : undefined}
57
+ >
58
+ <Icon className="w-3.5 h-3.5" />
59
+ </span>
43
60
  )}
44
- />
45
- {Icon && (
46
- <span
47
- className="flex items-center justify-center w-5 h-5 rounded bg-neutral-700/60"
48
- style={iconColor ? { color: iconColor } : undefined}
49
- >
50
- <Icon className="w-3.5 h-3.5" />
51
- </span>
52
- )}
53
- <span className="text-md font-medium text-neutral-200">{title}</span>
54
- {badge !== undefined && (
55
- <span className="ml-auto">
56
- <Badge value={badge} color={badgeColor} size="xss" />
57
- </span>
58
- )}
59
- </button>
60
- {open && <div className="pb-3 pl-7 pr-2">{children}</div>}
61
- </div>
61
+ <span className="text-md font-medium text-neutral-200">{title}</span>
62
+ {badge !== undefined && (
63
+ <span className="ml-auto">
64
+ <Badge value={badge} accentColor={badgeColor} size="xss" />
65
+ </span>
66
+ )}
67
+ </button>
68
+ {open && <div className="pb-3 pl-7 pr-2">{children}</div>}
69
+ </div>
70
+ </AccentColorProvider>
62
71
  )
63
72
  }
@@ -14,12 +14,13 @@
14
14
  import { memo } from 'react'
15
15
  import { Check } from 'lucide-react'
16
16
  import { FORM_COLORS, type AccentColor } from '../lib/form-colors.ts'
17
+ import { useAccentColor } from '../lib/accent-context.ts'
17
18
  import { cn } from '../lib/cn.ts'
18
19
 
19
20
  export type ConfirmBadgeColor = AccentColor
20
21
 
21
22
  export interface ConfirmBadgeProps {
22
- color?: ConfirmBadgeColor
23
+ accentColor?: ConfirmBadgeColor
23
24
  size?: 'xss' | 'xs' | 'sm' | 'md' | 'lg'
24
25
  className?: string
25
26
  testId?: string
@@ -42,18 +43,20 @@ const iconSizeClasses = {
42
43
  }
43
44
 
44
45
  export const ConfirmBadge = memo(function ConfirmBadge({
45
- color = 'neutral',
46
+ accentColor,
46
47
  size = 'sm',
47
48
  className,
48
49
  testId,
49
50
  }: ConfirmBadgeProps) {
51
+ const contextAccent = useAccentColor()
52
+ const effectiveColor = accentColor ?? contextAccent ?? 'neutral'
50
53
  return (
51
54
  <span
52
55
  data-testid={testId}
53
56
  className={cn(
54
57
  'inline-flex items-center justify-center border',
55
- FORM_COLORS[color].border,
56
- FORM_COLORS[color].accent,
58
+ FORM_COLORS[effectiveColor].border,
59
+ FORM_COLORS[effectiveColor].accent,
57
60
  sizeClasses[size],
58
61
  className,
59
62
  )}
@@ -1,5 +1,7 @@
1
1
  import { useState, useEffect } from 'react'
2
2
  import { IconButton } from './icon-button.tsx'
3
+ import { useAccentColor } from '../lib/accent-context.ts'
4
+ import type { FormColor } from '../lib/form-colors.ts'
3
5
 
4
6
  export type ConsentChoice = 'accepted' | 'declined' | 'essential'
5
7
 
@@ -7,7 +9,7 @@ export interface CookieConsentProps {
7
9
  /** localStorage key used to persist the choice */
8
10
  storageKey: string
9
11
  /** Accent color for the "Accept All" button (default: 'cyan') */
10
- accentColor?: string
12
+ accentColor?: FormColor
11
13
  /** Heading text (default: 'We value your privacy') */
12
14
  heading?: string
13
15
  /** Description text */
@@ -30,15 +32,19 @@ const ACCENT_BUTTON_CLASSES: Record<string, string> = {
30
32
  teal: 'bg-teal-600 border-teal-500 hover:bg-teal-500',
31
33
  violet: 'bg-violet-600 border-violet-500 hover:bg-violet-500',
32
34
  sky: 'bg-sky-600 border-sky-500 hover:bg-sky-500',
35
+ yellow: 'bg-yellow-600 border-yellow-500 hover:bg-yellow-500',
36
+ neutral: 'bg-neutral-600 border-neutral-500 hover:bg-neutral-500',
33
37
  }
34
38
 
35
39
  export function CookieConsent({
36
40
  storageKey,
37
- accentColor = 'cyan',
41
+ accentColor,
38
42
  heading = 'We value your privacy',
39
43
  description = 'This site uses only essential cookies for functionality. No tracking or analytics.',
40
44
  onConsent,
41
45
  }: CookieConsentProps) {
46
+ const contextAccent = useAccentColor()
47
+ const effectiveColor = accentColor ?? contextAccent ?? 'cyan'
42
48
  const [isVisible, setIsVisible] = useState(false)
43
49
 
44
50
  useEffect(() => {
@@ -55,7 +61,7 @@ export function CookieConsent({
55
61
  if (!isVisible) return null
56
62
 
57
63
  return (
58
- <div className="fixed bottom-0 left-0 right-0 z-50 p-4 bg-neutral-900 border-t border-neutral-700/50">
64
+ <div className="fixed bottom-0 left-0 right-0 z-50 p-4 bg-neutral-980 border-t border-neutral-700/50">
59
65
  <div className="max-w-6xl mx-auto flex flex-col sm:flex-row items-start sm:items-center gap-4">
60
66
  <div className="flex-grow">
61
67
  <p className="text-md text-neutral-200 mb-1">{heading}</p>
@@ -65,19 +71,19 @@ export function CookieConsent({
65
71
  <div className="flex items-center gap-2 flex-shrink-0">
66
72
  <button
67
73
  onClick={() => handleConsent('declined')}
68
- className="px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-neutral-400 border border-transparent hover:text-neutral-200 hover:border-neutral-600 hover:bg-neutral-800 transition-colors"
74
+ className="px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-neutral-400 border border-transparent hover:text-neutral-200 hover:border-neutral-600 hover:bg-neutral-960 transition-colors"
69
75
  >
70
76
  Decline
71
77
  </button>
72
78
  <button
73
79
  onClick={() => handleConsent('essential')}
74
- className="px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-neutral-400 border border-transparent hover:text-neutral-200 hover:border-neutral-600 hover:bg-neutral-800 transition-colors"
80
+ className="px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-neutral-400 border border-transparent hover:text-neutral-200 hover:border-neutral-600 hover:bg-neutral-960 transition-colors"
75
81
  >
76
82
  Essential Only
77
83
  </button>
78
84
  <button
79
85
  onClick={() => handleConsent('accepted')}
80
- className={`px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-white border transition-colors ${ACCENT_BUTTON_CLASSES[accentColor] ?? ACCENT_BUTTON_CLASSES.cyan}`}
86
+ className={`px-3 py-1.5 text-md h-[26px] inline-flex items-center justify-center font-medium rounded-md cursor-pointer text-white border transition-colors ${ACCENT_BUTTON_CLASSES[effectiveColor] ?? ACCENT_BUTTON_CLASSES.cyan}`}
81
87
  >
82
88
  Accept All
83
89
  </button>
@@ -85,7 +91,7 @@ export function CookieConsent({
85
91
 
86
92
  <IconButton
87
93
  icon="x"
88
- color="neutral"
94
+ accentColor="neutral"
89
95
  size="xs"
90
96
  tooltip={{ description: 'Dismiss' }}
91
97
  tooltipPosition="top"
@@ -9,6 +9,9 @@
9
9
 
10
10
  import { iconMap, type IconName } from './icon-button.tsx'
11
11
  import { cn } from '../lib/cn.ts'
12
+ import { useAccentColor } from '../lib/accent-context.ts'
13
+ import { AccentColorProvider } from '../lib/accent-context.ts'
14
+ import type { FormColor } from '../lib/form-colors.ts'
12
15
 
13
16
  export interface DetailRow {
14
17
  label: string
@@ -24,27 +27,32 @@ export interface DetailSectionProps {
24
27
  /** Detail rows to display */
25
28
  rows: DetailRow[]
26
29
  className?: string
30
+ accentColor?: FormColor
27
31
  }
28
32
 
29
- export function DetailSection({ title, icon, rows, className }: DetailSectionProps) {
33
+ export function DetailSection({ title, icon, rows, className, accentColor }: DetailSectionProps) {
34
+ const contextAccent = useAccentColor()
35
+ const effectiveColor = accentColor ?? contextAccent ?? 'blue'
30
36
  const Icon = icon ? iconMap[icon] : undefined
31
37
 
32
38
  return (
33
- <div className={className}>
34
- <div className="flex items-center gap-2 mb-3">
35
- {Icon && <Icon className="w-4 h-4 text-neutral-500" />}
36
- <span className="text-md font-medium text-neutral-400">{title}</span>
39
+ <AccentColorProvider value={effectiveColor}>
40
+ <div className={className}>
41
+ <div className="flex items-center gap-2 mb-3">
42
+ {Icon && <Icon className="w-4 h-4 text-neutral-500" />}
43
+ <span className="text-md font-medium text-neutral-400">{title}</span>
44
+ </div>
45
+ <div className="space-y-2">
46
+ {rows.map((row) => (
47
+ <div key={row.label} className="flex items-start gap-3">
48
+ <span className="text-sm text-neutral-500 w-24 shrink-0">{row.label}:</span>
49
+ <span className={cn('text-sm text-neutral-400', row.mono && 'font-mono')}>
50
+ {row.value}
51
+ </span>
52
+ </div>
53
+ ))}
54
+ </div>
37
55
  </div>
38
- <div className="space-y-2">
39
- {rows.map((row) => (
40
- <div key={row.label} className="flex items-start gap-3">
41
- <span className="text-sm text-neutral-500 w-24 shrink-0">{row.label}:</span>
42
- <span className={cn('text-sm text-neutral-400', row.mono && 'font-mono')}>
43
- {row.value}
44
- </span>
45
- </div>
46
- ))}
47
- </div>
48
- </div>
56
+ </AccentColorProvider>
49
57
  )
50
58
  }
@@ -1,4 +1,6 @@
1
1
  import { type ReactNode } from 'react'
2
+ import { useAccentColor, AccentColorProvider } from '../lib/accent-context.ts'
3
+ import type { FormColor } from '../lib/form-colors.ts'
2
4
 
3
5
  export interface DetailViewWrapperProps {
4
6
  /** Main editor content */
@@ -12,6 +14,7 @@ export interface DetailViewWrapperProps {
12
14
  /** Optional right sidebar */
13
15
  rightSidebar?: ReactNode
14
16
  showRightSidebar?: boolean
17
+ accentColor?: FormColor
15
18
  }
16
19
 
17
20
  export function DetailViewWrapper({
@@ -20,36 +23,41 @@ export function DetailViewWrapper({
20
23
  bottomPanel,
21
24
  rightSidebar,
22
25
  showRightSidebar = false,
26
+ accentColor,
23
27
  }: DetailViewWrapperProps) {
28
+ const contextAccent = useAccentColor()
29
+ const effectiveColor = accentColor ?? contextAccent ?? 'blue'
24
30
 
25
31
  return (
26
- <div className="flex-1 flex flex-col overflow-hidden min-h-0">
27
- {actions && (
28
- <div className="flex items-center justify-end border-b border-neutral-800 bg-neutral-950/50 px-2 h-[36px]">
29
- <div className="flex items-center gap-1">{actions}</div>
30
- </div>
31
- )}
32
+ <AccentColorProvider value={effectiveColor}>
33
+ <div className="flex-1 flex flex-col overflow-hidden min-h-0">
34
+ {actions && (
35
+ <div className="flex items-center justify-end border-b border-neutral-960 bg-neutral-990/50 px-2 h-[36px]">
36
+ <div className="flex items-center gap-1">{actions}</div>
37
+ </div>
38
+ )}
32
39
 
33
- {/* Main content area */}
34
- <div className="flex-1 flex overflow-hidden min-h-0">
35
- <div className="flex-1 flex flex-col min-w-0 overflow-hidden">
36
- {editorContent && (
37
- <div className="flex-1 flex flex-col overflow-hidden">{editorContent}</div>
40
+ {/* Main content area */}
41
+ <div className="flex-1 flex overflow-hidden min-h-0">
42
+ <div className="flex-1 flex flex-col min-w-0 overflow-hidden">
43
+ {editorContent && (
44
+ <div className="flex-1 flex flex-col overflow-hidden">{editorContent}</div>
45
+ )}
46
+ </div>
47
+
48
+ {/* Optional right sidebar */}
49
+ {showRightSidebar && rightSidebar && (
50
+ <div className="w-[300px] border-l border-neutral-960 overflow-hidden flex-shrink-0">
51
+ {rightSidebar}
52
+ </div>
38
53
  )}
39
54
  </div>
40
55
 
41
- {/* Optional right sidebar */}
42
- {showRightSidebar && rightSidebar && (
43
- <div className="w-[300px] border-l border-neutral-800 overflow-hidden flex-shrink-0">
44
- {rightSidebar}
45
- </div>
56
+ {/* Optional bottom panel */}
57
+ {bottomPanel && (
58
+ <div className="border-t border-neutral-960">{bottomPanel}</div>
46
59
  )}
47
60
  </div>
48
-
49
- {/* Optional bottom panel */}
50
- {bottomPanel && (
51
- <div className="border-t border-neutral-800">{bottomPanel}</div>
52
- )}
53
- </div>
61
+ </AccentColorProvider>
54
62
  )
55
63
  }