@toolr/ui-design 0.1.3 → 0.1.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.
Files changed (46) hide show
  1. package/README.md +0 -7
  2. package/components/content/info-panel-primitives.tsx +3 -3
  3. package/components/lib/ai-tools.tsx +1 -1
  4. package/components/lib/theme-engine.ts +10 -0
  5. package/components/sections/captured-issues/captured-issues-panel.tsx +1 -1
  6. package/components/sections/golden-snapshots/file-diff-viewer.tsx +2 -2
  7. package/components/sections/golden-snapshots/snapshot-manager.tsx +3 -3
  8. package/components/sections/golden-snapshots/status-overview.tsx +4 -4
  9. package/components/sections/golden-snapshots/version-manager.tsx +3 -3
  10. package/components/sections/prompt-editor/tabbed-prompt-editor.tsx +3 -3
  11. package/components/sections/report-bug/screenshot-uploader.tsx +2 -2
  12. package/components/sections/snapshot-browser/snapshot-tree.tsx +1 -1
  13. package/components/sections/snippets-editor/snippets-editor.tsx +5 -5
  14. package/components/ui/action-dialog.tsx +1 -1
  15. package/components/ui/badge.tsx +4 -4
  16. package/components/ui/breadcrumb.tsx +1 -1
  17. package/components/ui/file-structure-section.tsx +4 -4
  18. package/components/ui/files-panel.tsx +5 -5
  19. package/components/ui/filter-dropdown.tsx +2 -2
  20. package/components/ui/frontmatter-form-header.tsx +2 -2
  21. package/components/ui/input.tsx +3 -3
  22. package/components/ui/label.tsx +4 -4
  23. package/components/ui/modal.tsx +1 -1
  24. package/components/ui/nav-card.tsx +17 -10
  25. package/components/ui/navigation-bar.tsx +1 -1
  26. package/components/ui/number-input.tsx +1 -1
  27. package/components/ui/registry-browser.tsx +2 -2
  28. package/components/ui/registry-card.tsx +7 -7
  29. package/components/ui/registry-detail.tsx +2 -2
  30. package/components/ui/segmented-toggle.tsx +2 -2
  31. package/components/ui/select.tsx +2 -2
  32. package/components/ui/selection-grid.tsx +7 -19
  33. package/components/ui/snapshot-card.tsx +2 -2
  34. package/components/ui/snippets-panel.tsx +9 -9
  35. package/components/ui/tab-bar.tsx +1 -1
  36. package/dist/content.js +3 -3
  37. package/dist/index.d.ts +23 -3
  38. package/dist/index.js +92 -92
  39. package/dist/tokens/primitives.css +10 -0
  40. package/dist/tokens/semantic.css +3 -0
  41. package/package.json +1 -7
  42. package/tokens/primitives.css +10 -0
  43. package/tokens/semantic.css +3 -0
  44. package/dist/preset.d.ts +0 -24
  45. package/dist/preset.js +0 -17
  46. package/tailwind-preset.ts +0 -22
@@ -412,7 +412,7 @@ export function RegistryCard(props: RegistryCardProps) {
412
412
  <Tooltip key={`pkg-${key}`} content={{ description: `${count} ${count === 1 ? label : labelPlural}` }} position="top">
413
413
  <span className="flex items-center gap-0.5">
414
414
  <Icon className={`w-3 h-3 ${color}`} />
415
- <span className="text-[10px] text-neutral-500">{count}</span>
415
+ <span className="text-xss text-neutral-500">{count}</span>
416
416
  </span>
417
417
  </Tooltip>
418
418
  )]
@@ -469,7 +469,7 @@ export function RegistryCard(props: RegistryCardProps) {
469
469
  ...(props.stars != null && props.stars > 0 ? [(
470
470
  <CardClickable key="stars" onClick={() => props.onSortBy?.('stars')}>
471
471
  <Tooltip content={{ description: `${props.stars.toLocaleString()} stars \u00b7 Click to sort` }} position="top">
472
- <span className="flex items-center gap-1 text-[10px] text-amber-400/80">
472
+ <span className="flex items-center gap-1 text-xss text-amber-400/80">
473
473
  <Star className="w-3 h-3" />
474
474
  {formatCount(props.stars)}
475
475
  </span>
@@ -479,7 +479,7 @@ export function RegistryCard(props: RegistryCardProps) {
479
479
  ...(props.downloads != null && props.downloads > 0 ? [(
480
480
  <CardClickable key="downloads" onClick={() => props.onSortBy?.('downloads')}>
481
481
  <Tooltip content={{ description: `${props.downloads.toLocaleString()} downloads \u00b7 Click to sort` }} position="top">
482
- <span className="flex items-center gap-1 text-[10px] text-emerald-400/80">
482
+ <span className="flex items-center gap-1 text-xss text-emerald-400/80">
483
483
  <Download className="w-3 h-3" />
484
484
  {formatCount(props.downloads)}
485
485
  </span>
@@ -581,7 +581,7 @@ export function RegistryCard(props: RegistryCardProps) {
581
581
  if (props.installs != null && props.installs > 0) {
582
582
  bottomStats = [(
583
583
  <Tooltip key="installs" content={{ description: `${props.installs.toLocaleString()} installs` }} position="top">
584
- <span className="flex items-center gap-1 text-[10px] text-neutral-500">
584
+ <span className="flex items-center gap-1 text-xss text-neutral-500">
585
585
  <Download className="w-3 h-3" />
586
586
  {props.installs.toLocaleString()}
587
587
  </span>
@@ -642,7 +642,7 @@ export function RegistryCard(props: RegistryCardProps) {
642
642
 
643
643
  {/* Error/warning message */}
644
644
  {errorMessage && (
645
- <p className={`text-[11px] mb-2 break-all ${flash === 'warning' ? 'text-amber-400' : 'text-red-400'}`}>{errorMessage}</p>
645
+ <p className={`text-xss mb-2 break-all ${flash === 'warning' ? 'text-amber-400' : 'text-red-400'}`}>{errorMessage}</p>
646
646
  )}
647
647
 
648
648
  {/* Bottom row */}
@@ -650,7 +650,7 @@ export function RegistryCard(props: RegistryCardProps) {
650
650
  const dateNode = updatedAt ? (
651
651
  <Tooltip content={{ description: onDateClick ? `Last updated ${formatFullDate(updatedAt)} \u00b7 Click to sort by date` : `Last updated ${formatFullDate(updatedAt)}` }} position="top">
652
652
  <span
653
- className={`flex items-center gap-1 text-[10px] text-neutral-500 whitespace-nowrap${onDateClick ? ' cursor-pointer hover:brightness-125 transition-all' : ''}`}
653
+ className={`flex items-center gap-1 text-xss text-neutral-500 whitespace-nowrap${onDateClick ? ' cursor-pointer hover:brightness-125 transition-all' : ''}`}
654
654
  onClick={onDateClick ? (e: MouseEvent) => { e.stopPropagation(); onDateClick() } : undefined}
655
655
  >
656
656
  <Clock className="w-3 h-3" />
@@ -690,7 +690,7 @@ export function RegistryCard(props: RegistryCardProps) {
690
690
  // Basic fallback: just install on confirm
691
691
  return (
692
692
  <div onClick={(e) => e.stopPropagation()}>
693
- <div className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center" onClick={() => setShowScopeConfirm(false)}>
693
+ <div className="fixed inset-0 bg-[var(--background)]/50 z-50 flex items-center justify-center" onClick={() => setShowScopeConfirm(false)}>
694
694
  <div className="bg-neutral-800 border border-neutral-700 rounded-lg p-4 max-w-sm" onClick={(e) => e.stopPropagation()}>
695
695
  <h3 className="text-sm font-medium text-neutral-200 mb-2">{ALREADY_AT_USER}</h3>
696
696
  <p className="text-xs text-neutral-400 mb-4">
@@ -122,7 +122,7 @@ function CompatibleWithSection({ tools }: { tools: string[] }) {
122
122
  {tools.map((tool) => (
123
123
  <div key={tool} className="flex flex-col items-center gap-1">
124
124
  <AiToolIcon tool={tool} size={18} />
125
- <span className="text-[10px] text-neutral-400">{AI_TOOL_NAMES[tool as AiToolKey] ?? tool}</span>
125
+ <span className="text-xss text-neutral-400">{AI_TOOL_NAMES[tool as AiToolKey] ?? tool}</span>
126
126
  </div>
127
127
  ))}
128
128
  </div>
@@ -162,7 +162,7 @@ export function RegistryDetail({
162
162
  <div className="min-w-0">
163
163
  <div className="flex items-center gap-3 flex-wrap">
164
164
  <Icon className={`w-6 h-6 shrink-0 ${iconColor}`} />
165
- <h2 className="text-xl font-semibold text-neutral-200">{title}</h2>
165
+ <h2 className="text-lg font-semibold text-neutral-200">{title}</h2>
166
166
  {labels && labels.length > 0 && labels.map((labelProps, i) => (
167
167
  <Label key={i} size="lg" {...labelProps} />
168
168
  ))}
@@ -34,8 +34,8 @@ const ICON_SIZE_CLASSES = {
34
34
 
35
35
  /** Text label button sizes — horizontal padding instead of fixed width */
36
36
  const TEXT_SIZE_CLASSES = {
37
- xss: 'h-[18px] px-1.5 text-[9px]',
38
- xs: 'h-6 px-2 text-[10px]',
37
+ xss: 'h-[18px] px-1.5 text-xss',
38
+ xs: 'h-6 px-2 text-xss',
39
39
  sm: 'h-7 px-2.5 text-xs',
40
40
  md: 'h-8 px-3 text-xs',
41
41
  lg: 'h-9 px-3.5 text-sm',
@@ -29,7 +29,7 @@ const VARIANT_CLASSES = {
29
29
  }
30
30
 
31
31
  const SIZE_CLASSES = {
32
- xss: 'h-[18px] px-1.5 text-[10px]',
32
+ xss: 'h-[18px] px-1.5 text-xss',
33
33
  xs: 'h-6 px-2 text-xs',
34
34
  sm: 'h-7 px-2 text-xs',
35
35
  md: 'h-8 px-3 text-sm',
@@ -154,7 +154,7 @@ export function Select<T extends string | number = string>({
154
154
  onPointerEnter={() => setHighlightIdx(idx)}
155
155
  className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs text-left transition-colors cursor-pointer ${
156
156
  isHighlighted
157
- ? 'bg-neutral-600 text-neutral-200'
157
+ ? `${FORM_COLORS[color].selectedBg} text-neutral-200`
158
158
  : isSelected ? `${FORM_COLORS[color].selectedBg} text-neutral-200` : `text-neutral-400 ${v.hoverBg}`
159
159
  }`}
160
160
  >
@@ -6,7 +6,7 @@ import {
6
6
  } from 'lucide-react'
7
7
  import type { LucideIcon } from 'lucide-react'
8
8
  import type { IconName } from './icon-button.tsx'
9
- import { ConfirmBadge, type ConfirmBadgeColor } from './confirm-badge.tsx'
9
+ import type { ConfirmBadgeColor } from './confirm-badge.tsx'
10
10
  import { cn } from '../lib/cn.ts'
11
11
  import { AiToolIcon, AI_TOOL_NAMES, type AiToolKey } from '../lib/ai-tools.tsx'
12
12
 
@@ -233,23 +233,17 @@ function GridCard({ item, selected, onClick }: CardProps) {
233
233
  className={cn(
234
234
  'relative p-3 rounded-lg text-center transition-all border-2 flex flex-col items-center',
235
235
  item.disabled
236
- ? 'opacity-30 cursor-not-allowed border-neutral-800 bg-black'
236
+ ? 'opacity-30 cursor-not-allowed border-neutral-800 bg-[var(--background)]'
237
237
  : selected
238
238
  ? 'cursor-pointer'
239
- : 'bg-neutral-800/50 border-neutral-700 hover:bg-neutral-800 hover:border-neutral-600 cursor-pointer',
239
+ : 'bg-neutral-800/50 border-neutral-700 hover:bg-[var(--surface-hover)] hover:border-neutral-600 cursor-pointer',
240
240
  )}
241
241
  style={
242
242
  selected && !item.disabled
243
- ? { borderColor: color, backgroundColor: `${color}15` }
243
+ ? { borderColor: color }
244
244
  : undefined
245
245
  }
246
246
  >
247
- {selected && !item.disabled && (
248
- <span className="absolute top-1 right-1">
249
- <ConfirmBadge color={item.badgeColor || 'blue'} size="xs" />
250
- </span>
251
- )}
252
-
253
247
  {Icon && (
254
248
  <Icon
255
249
  className="w-7 h-7 mb-1"
@@ -278,23 +272,17 @@ function ListCard({ item, selected, onClick }: CardProps) {
278
272
  className={cn(
279
273
  'relative p-3 rounded-lg transition-all border-2 flex items-center gap-3 text-left',
280
274
  item.disabled
281
- ? 'opacity-30 cursor-not-allowed border-neutral-800 bg-black'
275
+ ? 'opacity-30 cursor-not-allowed border-neutral-800 bg-[var(--background)]'
282
276
  : selected
283
277
  ? 'cursor-pointer'
284
- : 'bg-neutral-800/50 border-neutral-700 hover:bg-neutral-800 hover:border-neutral-600 cursor-pointer',
278
+ : 'bg-neutral-800/50 border-neutral-700 hover:bg-[var(--surface-hover)] hover:border-neutral-600 cursor-pointer',
285
279
  )}
286
280
  style={
287
281
  selected && !item.disabled
288
- ? { borderColor: color, backgroundColor: `${color}15` }
282
+ ? { borderColor: color }
289
283
  : undefined
290
284
  }
291
285
  >
292
- {selected && !item.disabled && (
293
- <span className="absolute top-1 right-1">
294
- <ConfirmBadge color={item.badgeColor || 'blue'} size="xs" />
295
- </span>
296
- )}
297
-
298
286
  {Icon && (
299
287
  <Icon
300
288
  className="w-5 h-5 flex-shrink-0"
@@ -59,7 +59,7 @@ export function SnapshotCard({
59
59
  </div>
60
60
 
61
61
  {timestamp && (
62
- <p className="mt-1 text-[10px] text-neutral-500">{timestamp}</p>
62
+ <p className="mt-1 text-xss text-neutral-500">{timestamp}</p>
63
63
  )}
64
64
 
65
65
  {description && (
@@ -70,7 +70,7 @@ export function SnapshotCard({
70
70
  <div className="mt-3 grid grid-cols-2 gap-x-4 gap-y-2">
71
71
  {stats.map((stat) => (
72
72
  <div key={stat.label}>
73
- <p className="text-[10px] text-neutral-500">{stat.label}</p>
73
+ <p className="text-xss text-neutral-500">{stat.label}</p>
74
74
  <p className="text-xs font-medium text-neutral-200">{stat.value}</p>
75
75
  </div>
76
76
  ))}
@@ -63,12 +63,12 @@ export function SnippetsPanel({
63
63
  return (
64
64
  <div className={cn('flex flex-col bg-neutral-800 rounded-lg overflow-hidden', className)}>
65
65
  <div className="flex items-center justify-between px-3 py-2 border-b border-neutral-700">
66
- <span className="text-[11px] font-semibold uppercase tracking-wider text-neutral-500">Snippets</span>
67
- <span className="text-[10px] text-neutral-500">{snippets.length} snippets</span>
66
+ <span className="text-xss font-semibold uppercase tracking-wider text-neutral-500">Snippets</span>
67
+ <span className="text-xss text-neutral-500">{snippets.length} snippets</span>
68
68
  </div>
69
69
  {showSearch && (
70
70
  <div className="px-2 py-2 border-b border-neutral-700">
71
- <div className="flex items-center gap-1.5 px-2 py-1 bg-black border border-neutral-700 rounded text-xs">
71
+ <div className="flex items-center gap-1.5 px-2 py-1 bg-[var(--background)] border border-neutral-700 rounded text-xs">
72
72
  <Search className="w-3 h-3 text-neutral-500 shrink-0" />
73
73
  <input
74
74
  type="text"
@@ -90,7 +90,7 @@ export function SnippetsPanel({
90
90
  />
91
91
  ))}
92
92
  {filteredSnippets.length === 0 && (
93
- <p className="text-[11px] text-neutral-500 text-center py-4">No snippets found</p>
93
+ <p className="text-xss text-neutral-500 text-center py-4">No snippets found</p>
94
94
  )}
95
95
  </div>
96
96
  </div>
@@ -113,7 +113,7 @@ function SnippetCard({ snippet, onInsert, onCopy }: SnippetCardProps) {
113
113
  <span className="text-xs font-medium text-neutral-200 truncate">{snippet.label}</span>
114
114
  {snippet.language && (
115
115
  <span
116
- className="px-1.5 py-0.5 text-[9px] font-medium rounded shrink-0"
116
+ className="px-1.5 py-0.5 text-xss font-medium rounded shrink-0"
117
117
  style={{ color: langColor, backgroundColor: `${langColor}20` }}
118
118
  >
119
119
  {snippet.language}
@@ -140,17 +140,17 @@ function SnippetCard({ snippet, onInsert, onCopy }: SnippetCardProps) {
140
140
  </div>
141
141
  </div>
142
142
  {snippet.description && (
143
- <p className="px-2.5 pb-1.5 text-[11px] text-neutral-400 leading-relaxed">{snippet.description}</p>
143
+ <p className="px-2.5 pb-1.5 text-xss text-neutral-400 leading-relaxed">{snippet.description}</p>
144
144
  )}
145
- <div className="mx-2.5 mb-2 rounded bg-black border border-neutral-700 overflow-hidden">
146
- <pre className="p-2 text-[11px] text-neutral-400 leading-relaxed overflow-x-auto max-h-24">
145
+ <div className="mx-2.5 mb-2 rounded bg-[var(--background)] border border-neutral-700 overflow-hidden">
146
+ <pre className="p-2 text-xss text-neutral-400 leading-relaxed overflow-x-auto max-h-24">
147
147
  <code>{snippet.code}</code>
148
148
  </pre>
149
149
  </div>
150
150
  {snippet.tags && snippet.tags.length > 0 && (
151
151
  <div className="flex flex-wrap gap-1 px-2.5 pb-2">
152
152
  {snippet.tags.map((tag) => (
153
- <span key={tag} className="px-1.5 py-0.5 text-[9px] rounded bg-neutral-700 text-neutral-500">
153
+ <span key={tag} className="px-1.5 py-0.5 text-xss rounded bg-neutral-700 text-neutral-500">
154
154
  {tag}
155
155
  </span>
156
156
  ))}
@@ -54,7 +54,7 @@ export interface TabBarProps {
54
54
  }
55
55
 
56
56
  const sizeConfig = {
57
- xss: { text: 'text-[10px]', icon: 'w-2.5 h-2.5', px: 'px-1.5', py: 'py-1', close: 'w-2.5 h-2.5', badgeSize: 'xss' as const, gap: 'gap-1' },
57
+ xss: { text: 'text-xss', icon: 'w-2.5 h-2.5', px: 'px-1.5', py: 'py-1', close: 'w-2.5 h-2.5', badgeSize: 'xss' as const, gap: 'gap-1' },
58
58
  xs: { text: 'text-xs', icon: 'w-3 h-3', px: 'px-2', py: 'py-1', close: 'w-3 h-3', badgeSize: 'xs' as const, gap: 'gap-1' },
59
59
  sm: { text: 'text-sm', icon: 'w-3.5 h-3.5', px: 'px-3', py: 'py-1.5', close: 'w-3 h-3', badgeSize: 'sm' as const, gap: 'gap-1.5' },
60
60
  md: { text: 'text-base', icon: 'w-4 h-4', px: 'px-4', py: 'py-2', close: 'w-3.5 h-3.5', badgeSize: 'md' as const, gap: 'gap-2' },
package/dist/content.js CHANGED
@@ -65,7 +65,7 @@ function Callout({ color, children }) {
65
65
  }
66
66
  function CalloutCode({ color, children }) {
67
67
  const c = CALLOUT_COLORS[color] ?? CALLOUT_COLORS.blue;
68
- return /* @__PURE__ */ jsx("code", { className: `block bg-neutral-800/80 px-2 py-1 rounded mt-1.5 text-[13px] ${c.codeText}`, children });
68
+ return /* @__PURE__ */ jsx("code", { className: `block bg-neutral-800/80 px-2 py-1 rounded mt-1.5 text-sm ${c.codeText}`, children });
69
69
  }
70
70
  function CalloutDim({ children }) {
71
71
  return /* @__PURE__ */ jsx("p", { className: "text-neutral-500 mt-1.5", children });
@@ -115,7 +115,7 @@ function TitledLI({ color, title, children }) {
115
115
  ] });
116
116
  }
117
117
  function CalloutDialog({ color, lines }) {
118
- return /* @__PURE__ */ jsx("div", { className: "bg-neutral-800/80 rounded px-2 py-1 mt-1.5 flex flex-col gap-0.5 text-[13px]", children: lines.map((line, idx) => /* @__PURE__ */ jsxs("div", { children: [
118
+ return /* @__PURE__ */ jsx("div", { className: "bg-neutral-800/80 rounded px-2 py-1 mt-1.5 flex flex-col gap-0.5 text-sm", children: lines.map((line, idx) => /* @__PURE__ */ jsxs("div", { children: [
119
119
  /* @__PURE__ */ jsxs("span", { className: `text-${color}-300 font-semibold mr-1`, children: [
120
120
  line.speaker,
121
121
  ":"
@@ -131,7 +131,7 @@ function StatusBadge({ value, badgeColor, label, children, even }) {
131
131
  DLRow,
132
132
  {
133
133
  term: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
134
- /* @__PURE__ */ jsx("span", { className: `inline-flex items-center justify-center w-5 h-5 rounded-full bg-${badgeColor}-500/20 text-${badgeColor}-400 text-[11px] font-bold shrink-0`, children: value }),
134
+ /* @__PURE__ */ jsx("span", { className: `inline-flex items-center justify-center w-5 h-5 rounded-full bg-${badgeColor}-500/20 text-${badgeColor}-400 text-xss font-bold shrink-0`, children: value }),
135
135
  /* @__PURE__ */ jsx("span", { className: `text-${badgeColor}-400 font-semibold`, children: label })
136
136
  ] }),
137
137
  even,
package/dist/index.d.ts CHANGED
@@ -31,6 +31,16 @@ declare const DEFAULT_DIMS: Record<SurfaceKey, number>;
31
31
  declare const DEFAULT_OUTLINE = 30;
32
32
  declare function generateScale(theme: ThemeId, hue: number | null, maxSat: number, dims?: Record<SurfaceKey, number>, outline?: number): Record<ScaleKey, string>;
33
33
  declare function isLightTheme(themeId: ThemeId): boolean;
34
+ /**
35
+ * Apply a theme to the document by setting CSS custom properties on the root element.
36
+ *
37
+ * IMPORTANT — body background: Portal-based components (Select, Tooltip) render at
38
+ * document.body via createPortal. Their backgrounds use --popover which is semi-transparent
39
+ * (rgba(0,0,0,0.8)). If <body> has no background-color, the browser default (white) bleeds
40
+ * through, making dropdowns/tooltips appear gray instead of dark.
41
+ *
42
+ * Consuming apps MUST set: body { background-color: var(--background); }
43
+ */
34
44
  declare function applyTheme(themeId: ThemeId, accentHue: number | null, dims?: Record<SurfaceKey, number>, outline?: number, root?: HTMLElement): void;
35
45
 
36
46
  type ToolrAppId = 'toolr' | 'configr' | 'reviewr' | 'vibr' | 'learnr' | 'planr' | 'seedr';
@@ -2577,14 +2587,24 @@ interface NavCardProps {
2577
2587
  title: string;
2578
2588
  description?: string;
2579
2589
  icon?: IconName;
2590
+ /** Custom icon component. Takes precedence over icon name. */
2591
+ IconComponent?: React.ComponentType<{
2592
+ className?: string;
2593
+ }>;
2580
2594
  iconColor?: string;
2581
- badge?: number | string;
2582
- badgeColor?: BadgeColor;
2595
+ label?: {
2596
+ text: string;
2597
+ color: LabelColor;
2598
+ tooltip: {
2599
+ description: string;
2600
+ };
2601
+ };
2602
+ stats?: string;
2583
2603
  onClick?: () => void;
2584
2604
  disabled?: boolean;
2585
2605
  className?: string;
2586
2606
  }
2587
- declare function NavCard({ title, description, icon, iconColor, badge, badgeColor, onClick, disabled, className, }: NavCardProps): react_jsx_runtime.JSX.Element;
2607
+ declare function NavCard({ title, description, icon, IconComponent, iconColor, label, stats, onClick, disabled, className, }: NavCardProps): react_jsx_runtime.JSX.Element;
2588
2608
 
2589
2609
  interface ExtensionListCardProps {
2590
2610
  /** Lucide icon component */