@toolr/ui-design 0.1.0

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 (112) hide show
  1. package/README.md +63 -0
  2. package/components/content/info-panel-primitives.tsx +297 -0
  3. package/components/diagrams/diagram-utils.tsx +908 -0
  4. package/components/hooks/use-click-outside.ts +27 -0
  5. package/components/hooks/use-dropdown-max-height.ts +20 -0
  6. package/components/hooks/use-navigation-history.ts +94 -0
  7. package/components/lib/ai-tools.tsx +44 -0
  8. package/components/lib/cn.ts +6 -0
  9. package/components/lib/form-colors.ts +32 -0
  10. package/components/lib/theme-engine.ts +97 -0
  11. package/components/lib/toolr-brand.tsx +31 -0
  12. package/components/sections/ai-tools-paths/index.ts +37 -0
  13. package/components/sections/ai-tools-paths/tools-paths-panel.tsx +212 -0
  14. package/components/sections/ai-tools-paths/types.ts +111 -0
  15. package/components/sections/ai-tools-paths/use-tools-paths.ts +159 -0
  16. package/components/sections/captured-issues/captured-issues-panel.tsx +214 -0
  17. package/components/sections/captured-issues/index.ts +38 -0
  18. package/components/sections/captured-issues/types.ts +113 -0
  19. package/components/sections/captured-issues/use-captured-issues.ts +111 -0
  20. package/components/sections/golden-snapshots/file-diff-viewer.tsx +420 -0
  21. package/components/sections/golden-snapshots/golden-sync-panel.tsx +223 -0
  22. package/components/sections/golden-snapshots/index.ts +145 -0
  23. package/components/sections/golden-snapshots/snapshot-manager.tsx +200 -0
  24. package/components/sections/golden-snapshots/status-overview.tsx +305 -0
  25. package/components/sections/golden-snapshots/types.ts +288 -0
  26. package/components/sections/golden-snapshots/use-golden-sync.ts +477 -0
  27. package/components/sections/golden-snapshots/version-manager.tsx +186 -0
  28. package/components/sections/prompt-editor/file-type-tabbed-prompt-editor.tsx +210 -0
  29. package/components/sections/prompt-editor/index.ts +121 -0
  30. package/components/sections/prompt-editor/simulator-prompt-editor.tsx +276 -0
  31. package/components/sections/prompt-editor/tabbed-prompt-editor.tsx +514 -0
  32. package/components/sections/prompt-editor/types.ts +101 -0
  33. package/components/sections/prompt-editor/use-prompt-editor.ts +131 -0
  34. package/components/sections/report-bug/error-logger.ts +392 -0
  35. package/components/sections/report-bug/index.ts +59 -0
  36. package/components/sections/report-bug/issue-reporter-api.ts +83 -0
  37. package/components/sections/report-bug/report-bug-form.tsx +282 -0
  38. package/components/sections/report-bug/screenshot-uploader.tsx +228 -0
  39. package/components/sections/report-bug/use-report-bug.ts +170 -0
  40. package/components/sections/snapshot-browser/index.ts +53 -0
  41. package/components/sections/snapshot-browser/snapshot-browser-panel.tsx +147 -0
  42. package/components/sections/snapshot-browser/snapshot-tree.tsx +451 -0
  43. package/components/sections/snapshot-browser/types.ts +106 -0
  44. package/components/sections/snapshot-browser/use-snapshot-browser.ts +125 -0
  45. package/components/sections/snippets-editor/index.ts +31 -0
  46. package/components/sections/snippets-editor/snippets-editor.tsx +381 -0
  47. package/components/sections/snippets-editor/types.ts +48 -0
  48. package/components/sections/snippets-editor/use-snippets-editor.ts +217 -0
  49. package/components/ui/action-dialog.tsx +309 -0
  50. package/components/ui/ai-action-button.tsx +137 -0
  51. package/components/ui/ai-execution-action-buttons.tsx +106 -0
  52. package/components/ui/badge.tsx +67 -0
  53. package/components/ui/bottom-panel-header.tsx +240 -0
  54. package/components/ui/breadcrumb.tsx +168 -0
  55. package/components/ui/checkbox.tsx +102 -0
  56. package/components/ui/collapsible-section.tsx +100 -0
  57. package/components/ui/confirm-badge.tsx +71 -0
  58. package/components/ui/detail-section.tsx +67 -0
  59. package/components/ui/detail-view-wrapper.tsx +55 -0
  60. package/components/ui/editor-placeholder-card.tsx +197 -0
  61. package/components/ui/editor-toolbar.tsx +123 -0
  62. package/components/ui/execution-details-panel.tsx +93 -0
  63. package/components/ui/extension-list-card.tsx +105 -0
  64. package/components/ui/file-structure-section.tsx +373 -0
  65. package/components/ui/file-tree.tsx +171 -0
  66. package/components/ui/files-panel.tsx +251 -0
  67. package/components/ui/filter-dropdown.tsx +173 -0
  68. package/components/ui/form-actions.tsx +127 -0
  69. package/components/ui/frontmatter-form-header.tsx +80 -0
  70. package/components/ui/icon-button.tsx +388 -0
  71. package/components/ui/input.tsx +211 -0
  72. package/components/ui/label.tsx +159 -0
  73. package/components/ui/layout-tab-bar.tsx +289 -0
  74. package/components/ui/modal.tsx +194 -0
  75. package/components/ui/nav-card.tsx +81 -0
  76. package/components/ui/navigation-bar.tsx +285 -0
  77. package/components/ui/number-input.tsx +165 -0
  78. package/components/ui/registry-browser.tsx +261 -0
  79. package/components/ui/registry-card.tsx +710 -0
  80. package/components/ui/registry-detail.tsx +224 -0
  81. package/components/ui/resizable-textarea.tsx +290 -0
  82. package/components/ui/scope-badge.tsx +67 -0
  83. package/components/ui/segmented-toggle.tsx +133 -0
  84. package/components/ui/select.tsx +172 -0
  85. package/components/ui/selection-grid.tsx +313 -0
  86. package/components/ui/setting-row.tsx +97 -0
  87. package/components/ui/snapshot-card.tsx +107 -0
  88. package/components/ui/snippets-panel.tsx +161 -0
  89. package/components/ui/sort-dropdown.tsx +109 -0
  90. package/components/ui/status-card.tsx +96 -0
  91. package/components/ui/tab-bar.tsx +340 -0
  92. package/components/ui/toggle.tsx +142 -0
  93. package/components/ui/tooltip.tsx +326 -0
  94. package/dist/content.d.ts +110 -0
  95. package/dist/content.js +195 -0
  96. package/dist/diagrams.d.ts +371 -0
  97. package/dist/diagrams.js +702 -0
  98. package/dist/index.d.ts +2714 -0
  99. package/dist/index.js +11220 -0
  100. package/dist/preset.d.ts +24 -0
  101. package/dist/preset.js +17 -0
  102. package/dist/tokens/tokens/primitives.css +45 -0
  103. package/dist/tokens/tokens/semantic.css +46 -0
  104. package/dist/tokens/tokens/theme.css +11 -0
  105. package/dist/tokens/tokens/tokens.json +65 -0
  106. package/index.ts +123 -0
  107. package/package.json +63 -0
  108. package/tailwind-preset.ts +22 -0
  109. package/tokens/primitives.css +45 -0
  110. package/tokens/semantic.css +46 -0
  111. package/tokens/theme.css +11 -0
  112. package/tokens/tokens.json +65 -0
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # @toolr/ui-design
2
+
3
+ Shared UI design system for toolr applications. Provides components, design tokens, and a Tailwind preset.
4
+
5
+ ## Setup
6
+
7
+ ```jsonc
8
+ // package.json — path is relative to your app
9
+ { "@toolr/ui-design": "file:../../shared/ui-design" }
10
+ ```
11
+
12
+ ```css
13
+ /* app CSS entry point */
14
+ @import "@toolr/ui-design/tokens";
15
+ ```
16
+
17
+ ```ts
18
+ // tailwind.config.ts
19
+ import { toolrPreset } from '@toolr/ui-design/preset'
20
+ export default { presets: [toolrPreset] }
21
+ ```
22
+
23
+ ## Exports
24
+
25
+ | Path | Content |
26
+ |------|---------|
27
+ | `@toolr/ui-design` | All components, hooks, types, utilities |
28
+ | `@toolr/ui-design/tokens` | CSS design tokens (semantic + primitives + keyframes) |
29
+ | `@toolr/ui-design/preset` | Tailwind preset (Inter font, extended breakpoints) |
30
+ | `@toolr/ui-design/content` | Info panel primitives |
31
+ | `@toolr/ui-design/diagrams` | Diagram utilities |
32
+
33
+ Always import components from the barrel export (`@toolr/ui-design`), not from deep paths.
34
+
35
+ ## Claude Code Skills
36
+
37
+ Two skills ship with this package for Claude Code agents:
38
+
39
+ ### `ui-playground` — Building the design system
40
+
41
+ For working on components and playground pages inside this repo. Triggers when editing files in `components/ui/`, `playground/src/pages/`, or `index.ts`.
42
+
43
+ ### `ui-consumer` — Using the design system in apps
44
+
45
+ For consuming apps that import `@toolr/ui-design`. Covers setup, import patterns, FormColor, cn(), icons, tooltips, modals, sections, tokens, and common mistakes.
46
+
47
+ To make `ui-consumer` available in a consuming app, symlink it into the app's `.shared/.claude/skills/` directory:
48
+
49
+ ```bash
50
+ # From the monorepo root (adjust relative path as needed)
51
+ ln -s ../../../../shared/ui-design/.claude/skills/ui-consumer <app>/.shared/.claude/skills/ui-consumer
52
+ ```
53
+
54
+ Currently symlinked in: **configr** (`configr/.shared/.claude/skills/ui-consumer`).
55
+
56
+ ## Playground
57
+
58
+ Interactive component playground with live preview, prop controls, and code generation.
59
+
60
+ ```bash
61
+ # Start (requires tmux session toolr-shared-uidesign)
62
+ cd playground && npm run dev -- --port 6100
63
+ ```
@@ -0,0 +1,297 @@
1
+ /**
2
+ * InfoPanelPrimitives — Shared building blocks for info panel content.
3
+ *
4
+ * Grid variant: 14px body text, CSS Grid definition lists, border-left callouts,
5
+ * no gray boxes, generous spacing. Designed for scannability.
6
+ */
7
+
8
+ import type { ReactNode } from 'react'
9
+
10
+ // ─── Paragraph ──────────────────────────────────────────────────────
11
+
12
+ export function P({ children }: { children: ReactNode }) {
13
+ return <p className="text-sm text-neutral-400 leading-relaxed mb-5">{children}</p>
14
+ }
15
+
16
+ // ─── Section Header ─────────────────────────────────────────────────
17
+
18
+ export function SectionHeader({ color, children }: { color?: string; children: ReactNode }) {
19
+ const textColor = color ? `text-${color}-500/70` : 'text-neutral-500'
20
+ return (
21
+ <p className={`${textColor} text-xs uppercase font-semibold pb-0.5 border-b border-neutral-700/50 mb-2.5`} style={{ letterSpacing: '0.8px' }}>
22
+ {children}
23
+ </p>
24
+ )
25
+ }
26
+
27
+ // ─── Definition List (CSS Grid two-column) ──────────────────────────
28
+
29
+ export function DL({ children }: { children: ReactNode }) {
30
+ return (
31
+ <div className="mb-5">
32
+ <div className="grid grid-cols-[auto_1fr] gap-x-4">{children}</div>
33
+ </div>
34
+ )
35
+ }
36
+
37
+ export function DLRow({ term, children, even }: { term: ReactNode; children: ReactNode; even?: boolean }) {
38
+ const bg = even ? 'bg-white/[0.015]' : ''
39
+ return (
40
+ <>
41
+ <div className={`py-2 border-b border-neutral-800/60 ${bg} font-semibold text-sm whitespace-nowrap`}>
42
+ {term}
43
+ </div>
44
+ <div className={`py-2 border-b border-neutral-800/60 ${bg} text-sm text-neutral-400`}>{children}</div>
45
+ </>
46
+ )
47
+ }
48
+
49
+ // ─── Unordered List ─────────────────────────────────────────────────
50
+
51
+ export function UL({ children }: { children: ReactNode }) {
52
+ return <ul className="text-sm text-neutral-400 space-y-2 mb-5">{children}</ul>
53
+ }
54
+
55
+ export function LI({ color, children }: { color: string; children: ReactNode }) {
56
+ return (
57
+ <li className="flex items-start gap-2">
58
+ <span className={`text-${color}-400 shrink-0`} style={{ marginTop: '3px', fontSize: '18px', lineHeight: '14px' }}>&#x2022;</span>
59
+ <span>{children}</span>
60
+ </li>
61
+ )
62
+ }
63
+
64
+ // ─── Ordered List ───────────────────────────────────────────────────
65
+
66
+ export function OL({ children }: { children: ReactNode }) {
67
+ return <div className="space-y-2 mb-5">{children}</div>
68
+ }
69
+
70
+ export function OLI({ n, color, children }: { n: number; color: string; children: ReactNode }) {
71
+ return (
72
+ <div className="flex items-start gap-2.5 text-sm">
73
+ <span className={`text-${color}-400 shrink-0 w-4 text-right font-bold`}>{n}.</span>
74
+ <span className="text-neutral-400">{children}</span>
75
+ </div>
76
+ )
77
+ }
78
+
79
+ // ─── Callout ────────────────────────────────────────────────────────
80
+
81
+ /** Literal class strings so Tailwind's scanner can detect them. */
82
+ const CALLOUT_COLORS: Record<string, { borderL: string; borderY: string; bg: string; text: string; codeText: string; dimText: string }> = {
83
+ amber: { borderL: 'border-amber-500/40', borderY: 'border-y-amber-500/15', bg: 'bg-amber-500/5', text: 'text-amber-400', codeText: 'text-amber-300/80', dimText: 'text-amber-400/60' },
84
+ blue: { borderL: 'border-blue-500/40', borderY: 'border-y-blue-500/15', bg: 'bg-blue-500/5', text: 'text-blue-400', codeText: 'text-blue-300/80', dimText: 'text-blue-400/60' },
85
+ cyan: { borderL: 'border-cyan-500/40', borderY: 'border-y-cyan-500/15', bg: 'bg-cyan-500/5', text: 'text-cyan-400', codeText: 'text-cyan-300/80', dimText: 'text-cyan-400/60' },
86
+ emerald: { borderL: 'border-emerald-500/40', borderY: 'border-y-emerald-500/15', bg: 'bg-emerald-500/5', text: 'text-emerald-400', codeText: 'text-emerald-300/80', dimText: 'text-emerald-400/60' },
87
+ fuchsia: { borderL: 'border-fuchsia-500/40', borderY: 'border-y-fuchsia-500/15', bg: 'bg-fuchsia-500/5', text: 'text-fuchsia-400', codeText: 'text-fuchsia-300/80', dimText: 'text-fuchsia-400/60' },
88
+ green: { borderL: 'border-green-500/40', borderY: 'border-y-green-500/15', bg: 'bg-green-500/5', text: 'text-green-400', codeText: 'text-green-300/80', dimText: 'text-green-400/60' },
89
+ indigo: { borderL: 'border-indigo-500/40', borderY: 'border-y-indigo-500/15', bg: 'bg-indigo-500/5', text: 'text-indigo-400', codeText: 'text-indigo-300/80', dimText: 'text-indigo-400/60' },
90
+ lime: { borderL: 'border-lime-500/40', borderY: 'border-y-lime-500/15', bg: 'bg-lime-500/5', text: 'text-lime-400', codeText: 'text-lime-300/80', dimText: 'text-lime-400/60' },
91
+ orange: { borderL: 'border-orange-500/40', borderY: 'border-y-orange-500/15', bg: 'bg-orange-500/5', text: 'text-orange-400', codeText: 'text-orange-300/80', dimText: 'text-orange-400/60' },
92
+ pink: { borderL: 'border-pink-500/40', borderY: 'border-y-pink-500/15', bg: 'bg-pink-500/5', text: 'text-pink-400', codeText: 'text-pink-300/80', dimText: 'text-pink-400/60' },
93
+ purple: { borderL: 'border-purple-500/40', borderY: 'border-y-purple-500/15', bg: 'bg-purple-500/5', text: 'text-purple-400', codeText: 'text-purple-300/80', dimText: 'text-purple-400/60' },
94
+ red: { borderL: 'border-red-500/40', borderY: 'border-y-red-500/15', bg: 'bg-red-500/5', text: 'text-red-400', codeText: 'text-red-300/80', dimText: 'text-red-400/60' },
95
+ rose: { borderL: 'border-rose-500/40', borderY: 'border-y-rose-500/15', bg: 'bg-rose-500/5', text: 'text-rose-400', codeText: 'text-rose-300/80', dimText: 'text-rose-400/60' },
96
+ sky: { borderL: 'border-sky-500/40', borderY: 'border-y-sky-500/15', bg: 'bg-sky-500/5', text: 'text-sky-400', codeText: 'text-sky-300/80', dimText: 'text-sky-400/60' },
97
+ teal: { borderL: 'border-teal-500/40', borderY: 'border-y-teal-500/15', bg: 'bg-teal-500/5', text: 'text-teal-400', codeText: 'text-teal-300/80', dimText: 'text-teal-400/60' },
98
+ violet: { borderL: 'border-violet-500/40', borderY: 'border-y-violet-500/15', bg: 'bg-violet-500/5', text: 'text-violet-400', codeText: 'text-violet-300/80', dimText: 'text-violet-400/60' },
99
+ }
100
+
101
+ export function getCalloutColors(color: string) {
102
+ return CALLOUT_COLORS[color] ?? CALLOUT_COLORS.blue
103
+ }
104
+
105
+ export function Callout({ color, children }: { color: string; children: ReactNode }) {
106
+ const c = CALLOUT_COLORS[color] ?? CALLOUT_COLORS.blue
107
+ return (
108
+ <div className={`border-l-4 ${c.borderL} border-y ${c.borderY} ${c.bg} px-3 py-2.5 rounded-r mb-5 text-sm text-neutral-400`}>
109
+ {children}
110
+ </div>
111
+ )
112
+ }
113
+
114
+ export function CalloutCode({ color, children }: { color: string; children: ReactNode }) {
115
+ const c = CALLOUT_COLORS[color] ?? CALLOUT_COLORS.blue
116
+ return (
117
+ <code className={`block bg-neutral-800/80 px-2 py-1 rounded mt-1.5 text-[13px] ${c.codeText}`}>
118
+ {children}
119
+ </code>
120
+ )
121
+ }
122
+
123
+ export function CalloutDim({ children }: { children: ReactNode }) {
124
+ return <p className="text-neutral-500 mt-1.5">{children}</p>
125
+ }
126
+
127
+ // ─── Code Block ─────────────────────────────────────────────────────
128
+
129
+ export function CodeBlock({ children }: { children: ReactNode }) {
130
+ return (
131
+ <div className="bg-neutral-900/60 rounded-md p-3 font-mono text-xs text-neutral-400 mb-5 whitespace-pre overflow-x-auto leading-normal">{children}</div>
132
+ )
133
+ }
134
+
135
+ // ─── Inline Code ────────────────────────────────────────────────────
136
+
137
+ export function CK({ color, children }: { color?: string; children: ReactNode }) {
138
+ const textColor = color ? `text-${color}-400` : ''
139
+ return (
140
+ <code className={`bg-neutral-800/80 px-1.5 py-px rounded text-[0.9em] ${textColor}`}>{children}</code>
141
+ )
142
+ }
143
+
144
+ // ─── External Link ──────────────────────────────────────────────────
145
+
146
+ export function ExternalLink({ href, children }: { href: string; children: ReactNode }) {
147
+ return (
148
+ <a href={href} target="_blank" rel="noopener noreferrer" className="underline cursor-pointer">
149
+ {children}
150
+ </a>
151
+ )
152
+ }
153
+
154
+ // ─── Location List (colored-dot items in CSS Grid) ──────────────────
155
+
156
+ export function LocationList({ children }: { children: ReactNode }) {
157
+ return (
158
+ <div className="mb-5">
159
+ <div className="grid grid-cols-[auto_1fr] gap-x-4">{children}</div>
160
+ </div>
161
+ )
162
+ }
163
+
164
+ export function LocationItem({
165
+ color,
166
+ label,
167
+ children,
168
+ even,
169
+ }: {
170
+ color: string
171
+ label: string
172
+ children: ReactNode
173
+ even?: boolean
174
+ }) {
175
+ const bg = even ? 'bg-white/[0.015]' : ''
176
+ return (
177
+ <>
178
+ <div className={`py-2 border-b border-neutral-800/60 ${bg} flex items-center gap-1.5`}>
179
+ <span
180
+ className={`w-2 h-2 rounded-full bg-${color}-500/50 border border-${color}-500 shrink-0`}
181
+ />
182
+ <span className={`text-${color}-400 text-sm font-semibold`}>{label}</span>
183
+ </div>
184
+ <div className={`py-2 border-b border-neutral-800/60 ${bg} text-sm text-neutral-400`}>{children}</div>
185
+ </>
186
+ )
187
+ }
188
+
189
+ // ─── TitledLI — Bullet item with colored title + description ────────
190
+
191
+ export function TitledLI({ color, title, children }: { color: string; title: string; children: ReactNode }) {
192
+ return (
193
+ <li className="flex items-start gap-2 text-sm text-neutral-400">
194
+ <span className={`text-${color}-400 shrink-0`} style={{ marginTop: '3px', fontSize: '18px', lineHeight: '14px' }}>&#x2022;</span>
195
+ <span>
196
+ <span className={`text-${color}-300 font-semibold`}>{title}</span>
197
+ {' '}&mdash; {children}
198
+ </span>
199
+ </li>
200
+ )
201
+ }
202
+
203
+ // ─── CalloutDialog — Conversation exchange inside a Callout ─────────
204
+
205
+ export function CalloutDialog({ color, lines }: { color: string; lines: { speaker: string; text: string }[] }) {
206
+ return (
207
+ <div className="bg-neutral-800/80 rounded px-2 py-1 mt-1.5 flex flex-col gap-0.5 text-[13px]">
208
+ {lines.map((line, idx) => (
209
+ <div key={idx}>
210
+ <span className={`text-${color}-300 font-semibold mr-1`}>{line.speaker}:</span>
211
+ <span className="text-neutral-400">{line.text}</span>
212
+ </div>
213
+ ))}
214
+ </div>
215
+ )
216
+ }
217
+
218
+ // ─── TagGrid — Flex-wrapped CK pills ────────────────────────────────
219
+
220
+ export function TagGrid({ color, tags }: { color: string; tags: string[] }) {
221
+ return (
222
+ <div className="flex flex-wrap gap-1.5 mb-5">
223
+ {tags.map((tag) => <CK key={tag} color={color}>{tag}</CK>)}
224
+ </div>
225
+ )
226
+ }
227
+
228
+ // ─── StatusBadge — Colored circle indicator row (use inside DL) ─────
229
+
230
+ export function StatusBadge({ value, badgeColor, label, children, even }: {
231
+ value: string
232
+ badgeColor: string
233
+ label: string
234
+ children: ReactNode
235
+ even?: boolean
236
+ }) {
237
+ return (
238
+ <DLRow
239
+ term={
240
+ <span className="flex items-center gap-1.5">
241
+ <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`}>{value}</span>
242
+ <span className={`text-${badgeColor}-400 font-semibold`}>{label}</span>
243
+ </span>
244
+ }
245
+ even={even}
246
+ >
247
+ {children}
248
+ </DLRow>
249
+ )
250
+ }
251
+
252
+ // ─── BulletGridRow — Bullet item in grid layout (use inside DL) ─────
253
+
254
+ export function BulletGridRow({ color, term, children, even }: {
255
+ color: string
256
+ term: string
257
+ children: ReactNode
258
+ even?: boolean
259
+ }) {
260
+ return (
261
+ <DLRow
262
+ term={
263
+ <span className="flex items-center gap-1.5">
264
+ <span className={`text-${color}-400`} style={{ fontSize: '18px', lineHeight: '14px' }}>&#x2022;</span>
265
+ <span className={`text-${color}-400 font-semibold`}>{term}</span>
266
+ </span>
267
+ }
268
+ even={even}
269
+ >
270
+ {children}
271
+ </DLRow>
272
+ )
273
+ }
274
+
275
+ // ─── NumberGridRow — Numbered item in grid layout (use inside DL) ───
276
+
277
+ export function NumberGridRow({ color, n, term, children, even }: {
278
+ color: string
279
+ n: number
280
+ term: string
281
+ children: ReactNode
282
+ even?: boolean
283
+ }) {
284
+ return (
285
+ <DLRow
286
+ term={
287
+ <span className="flex items-center gap-1.5">
288
+ <span className={`text-${color}-400 font-bold w-4 text-right shrink-0`}>{n}.</span>
289
+ <span className={`text-${color}-400 font-semibold`}>{term}</span>
290
+ </span>
291
+ }
292
+ even={even}
293
+ >
294
+ {children}
295
+ </DLRow>
296
+ )
297
+ }