command for UI review, and settings to use primitives.

This commit is contained in:
sean-eskerium
2025-10-08 18:38:12 -04:00
parent 0727245c9d
commit 5b839a1465
3 changed files with 495 additions and 83 deletions

View File

@@ -0,0 +1,314 @@
---
description: Analyze UI components for reusability, Radix usage, primitives, and styling consistency
argument-hint: <feature path, component path, or directory>
allowed-tools: Read, Grep, Glob, Write
thinking: auto
---
# UI Consistency Review for Archon
**Review scope**: $ARGUMENTS
I'll analyze the UI components and generate a detailed report on consistency, reusability, and adherence to the Archon design system.
## Analysis Framework
### Design System Standards
**Archon uses:**
- **Primitives**: `/src/features/ui/primitives/` - Reusable Radix components with glassmorphism styling
- **Card Variants**:
- Base glass card
- Edge-lit cards: `<Card edgePosition="top" edgeColor="cyan|pink|blue|...">`
- Outer glow cards
- Inner glow cards
- **Navigation**: PillNavigation component for all pill-style navigation
- **Glassmorphism**: `backdrop-blur-sm` (minimal), frosted glass backgrounds
- **Colors**: Semantic colors (Primary blue #3b82f6, Success, Warning, Error) + accents
### Scoring Criteria
**1. Reusability (1-10)**
- 10: Uses shared primitives, no hardcoded styles
- 7-9: Mostly reusable, minor hardcoding
- 4-6: Mix of primitives and custom code
- 1-3: Completely custom, duplicates existing patterns
**2. Radix Component Usage (1-10)**
- 10: Uses Radix primitives for ALL interactive elements (Select, Checkbox, Switch, Tabs, Dialog, etc.)
- 7-9: Mostly Radix, few native HTML elements
- 4-6: Mix of Radix and native elements
- 1-3: Primarily native HTML elements
**3. Primitives Usage (1-10)**
- 10: Uses Card, Button, Input primitives with proper props
- 7-9: Uses most primitives, some custom styling
- 4-6: Mix of primitives and manual styling
- 1-3: Hardcoded styling, doesn't use primitives
**4. Styling Consistency (1-10)**
- 10: Matches design system exactly (colors, blur, edge-lit patterns)
- 7-9: Close match, minor deviations
- 4-6: Significant inconsistencies
- 1-3: Completely different styling approach
## Review Process
### Step 1: Identify Components
Scan the provided path for:
- React components (`.tsx` files)
- Component usage patterns
- Imports from primitives vs manual styling
### Step 2: Analyze Each Component
For each component, check:
**Primitives Usage:**
```tsx
// GOOD - Uses Card primitive with props
<Card edgePosition="top" edgeColor="cyan">...</Card>
// BAD - Hardcoded edge glow
<div className="relative overflow-hidden rounded-xl">
<div className="absolute inset-x-0 top-0 h-[2px] bg-cyan-500..." />
<div className="absolute inset-x-0 top-0 h-8 bg-gradient-to-b..." />
...
</div>
```
**Radix Usage:**
```tsx
// GOOD - Radix Select primitive
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/features/ui/primitives/select';
// BAD - Native HTML
<select><option>...</option></select>
```
**Reusable Patterns:**
```tsx
// GOOD - Shared PillNavigation component
<PillNavigation items={...} colorVariant="orange" />
// BAD - Custom hardcoded pill navigation
<div className="backdrop-blur-sm bg-white/40...">
{items.map(item => <button className="px-6 py-3...">...)}
</div>
```
### Step 3: Generate Scores
Calculate scores for each component based on:
- Count of primitive vs hardcoded elements
- Radix usage vs native HTML
- Styling duplication vs reuse
- Pattern consistency
### Step 4: Identify Issues
Common anti-patterns to flag:
**Hardcoded Edge-Lit Cards:**
```tsx
// BAD - Manual implementation (like KnowledgeCard currently)
<div className="pointer-events-none absolute inset-x-0 top-0">
<div className="h-[2px] bg-cyan-500..." />
<div className="h-8 bg-gradient-to-b..." />
</div>
// GOOD - Use Card primitive
<Card edgePosition="top" edgeColor="cyan">
```
**Native HTML Form Elements:**
```tsx
// BAD
<select>, <input type="checkbox">, <input type="radio">
// GOOD
<Select />, <Checkbox />, <RadioGroup />
```
**Duplicated Pill Navigation:**
```tsx
// BAD - Creating custom pill nav each time
// GOOD - Use PillNavigation component
```
### Step 5: Write Resolution Steps
For each issue, provide:
- What to change
- Why it matters
- Specific code example of the fix
- Impact on consistency
## Report Format
Generate `ui-consistency-review-[feature].md`:
```markdown
# UI Consistency Review
**Date**: [Today's date]
**Scope**: [Path reviewed]
**Components Analyzed**: [Count]
---
## Overall Scores
| Category | Score | Assessment |
|----------|-------|------------|
| Reusability | X/10 | [Good/Needs Work/Poor] |
| Radix Usage | X/10 | [Good/Needs Work/Poor] |
| Primitives Usage | X/10 | [Good/Needs Work/Poor] |
| Styling Consistency | X/10 | [Good/Needs Work/Poor] |
**Overall Grade**: [A-F] - [Summary]
---
## Component-by-Component Analysis
### [ComponentName.tsx]
**Scores:**
- Reusability: X/10
- Radix Usage: X/10
- Primitives Usage: X/10
- Styling Consistency: X/10
**Issues Found:**
1. **[Issue Type]** - [Description]
- Location: `[file:line]`
- Current: `[code snippet]`
- Should be: `[corrected code]`
- Impact: [Why this matters]
**Standalone vs Primitive:**
[This component SHOULD/SHOULD NOT be standalone because...]
---
## Critical Issues (Must Fix)
### 1. [Issue Title]
- **File**: `[path:line]`
- **Problem**: [Description]
- **Why**: [Impact on consistency/maintainability]
- **Fix**:
```tsx
// Current
[bad code]
// Should be
[good code]
```
---
## Recommendations
### Immediate Actions
1. **[Action]** - [Why]
2. **[Action]** - [Why]
### Pattern Improvements
1. **[Pattern]** - [Benefit]
2. **[Pattern]** - [Benefit]
### Refactoring Priorities
1. **High Priority**: [Components that break consistency]
2. **Medium Priority**: [Components that could use primitives]
3. **Low Priority**: [Minor inconsistencies]
---
## Design System Compliance
**Primitives Used Correctly:**
- [List of components using primitives properly]
**Missing Primitive Usage:**
- [List of components that should use primitives]
**Radix Compliance:**
- [List of components using Radix properly]
- [List of components using native HTML instead of Radix]
**Styling Patterns:**
- Edge-lit cards: [X using primitive, Y hardcoded]
- Pill navigation: [X using component, Y custom]
- Glass effects: [X using blur tokens, Y custom values]
---
## Next Steps
1. [Most important fix]
2. [Second priority]
3. [Third priority]
**Estimated Effort**: [X hours for full refactor]
```
## What to Scan
Based on the argument:
**If directory path** (e.g., `src/features/knowledge`):
- Scan all `.tsx` files recursively
- Analyze each component
- Aggregate scores
**If single file** (e.g., `KnowledgeCard.tsx`):
- Deep analysis of that component
- Check all its dependencies
- Compare to similar components
**If feature name** (e.g., `projects`):
- Find feature directory
- Scan all components
- Check consistency within feature
## Red Flags to Auto-Detect
Use grep/glob to find:
```bash
# Hardcoded edge-lit implementations
grep -r "absolute inset-x-0 top-0" [path]
# Native HTML form elements
grep -r "<select>\|<option>\|<input type=\"checkbox\"" [path]
# Hardcoded pill navigation
grep -r "backdrop-blur-sm bg-white/40.*rounded-full" [path]
# Manual glassmorphism
grep -r "bg-gradient-to-b from-white/\|from-purple-100/" [path]
# Hardcoded colors instead of semantic tokens
grep -r "#[0-9a-fA-F]{6}" [path]
```
---
## Key Questions to Answer
1. **Does this component duplicate existing primitives?**
2. **Should this be refactored to use Card with edgePosition/edgeColor?**
3. **Are there native HTML elements that should be Radix?**
4. **Is the glassmorphism consistent with the design system?**
5. **Can multiple components be consolidated into one reusable primitive?**
---
Start the review now and save the report to `ui-consistency-review-[feature].md` in the project root.

View File

@@ -1,5 +1,6 @@
import { Settings, Palette, Key, Database, Code, Globe } from "lucide-react";
import { Settings, Palette, Key, Database, Code, Globe, Moon, FileText, Flame, Monitor } from "lucide-react";
import { CollapsibleSettingsCard } from "@/components/ui/CollapsibleSettingsCard";
import { Card } from "@/features/ui/primitives/card";
import { Switch } from "@/features/ui/primitives/switch";
import { Input } from "@/features/ui/primitives/input";
import { Label } from "@/features/ui/primitives/label";
@@ -15,148 +16,218 @@ export const SettingsLayoutExample = () => {
{/* Bento Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Features Section */}
<CollapsibleSettingsCard
title="Feature Toggles"
title="Features"
icon={Palette}
accentColor="purple"
defaultExpanded={true}
>
<div className="space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="projects-toggle">Enable Projects</Label>
<Switch id="projects-toggle" defaultChecked />
<div className="grid grid-cols-2 gap-4">
{/* Dark Mode */}
<div className="flex items-center gap-4 p-4 rounded-xl bg-gradient-to-br from-purple-500/10 to-purple-600/5 backdrop-blur-sm border border-purple-500/20 shadow-lg">
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-800 dark:text-white text-sm">Dark Mode</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Switch between themes
</p>
</div>
<div className="flex-shrink-0">
<Switch size="lg" defaultChecked color="purple" iconOn={<Moon className="w-5 h-5" />} />
</div>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="style-toggle">Style Guide</Label>
<Switch id="style-toggle" defaultChecked />
{/* Projects */}
<div className="flex items-center gap-4 p-4 rounded-xl bg-gradient-to-br from-blue-500/10 to-blue-600/5 backdrop-blur-sm border border-blue-500/20 shadow-lg">
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-800 dark:text-white text-sm">Projects</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Enable Projects functionality
</p>
</div>
<div className="flex-shrink-0">
<Switch size="lg" defaultChecked color="blue" icon={<FileText className="w-5 h-5" />} />
</div>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="dark-mode">Dark Mode</Label>
<Switch id="dark-mode" defaultChecked />
{/* Style Guide */}
<div className="flex items-center gap-4 p-4 rounded-xl bg-gradient-to-br from-cyan-500/10 to-cyan-600/5 backdrop-blur-sm border border-cyan-500/20 shadow-lg">
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-800 dark:text-white text-sm">Style Guide</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Show UI components
</p>
</div>
<div className="flex-shrink-0">
<Switch size="lg" defaultChecked color="cyan" icon={<Palette className="w-5 h-5" />} />
</div>
</div>
{/* Pydantic Logfire */}
<div className="flex items-center gap-4 p-4 rounded-xl bg-gradient-to-br from-orange-500/10 to-orange-600/5 backdrop-blur-sm border border-orange-500/20 shadow-lg">
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-800 dark:text-white text-sm">Pydantic Logfire</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Logging platform
</p>
</div>
<div className="flex-shrink-0">
<Switch size="lg" color="orange" icon={<Flame className="w-5 h-5" />} />
</div>
</div>
{/* Disconnect Screen */}
<div className="flex items-center gap-4 p-4 rounded-xl bg-gradient-to-br from-green-500/10 to-green-600/5 backdrop-blur-sm border border-green-500/20 shadow-lg">
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-800 dark:text-white text-sm">Disconnect Screen</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
Show when disconnected
</p>
</div>
<div className="flex-shrink-0">
<Switch size="lg" defaultChecked color="green" icon={<Monitor className="w-5 h-5" />} />
</div>
</div>
</div>
</CollapsibleSettingsCard>
<CollapsibleSettingsCard title="API Keys" icon={Key} accentColor="cyan" defaultExpanded={true}>
<div className="space-y-4">
<div>
<Label htmlFor="openai-key">OpenAI API Key</Label>
<Input
id="openai-key"
type="password"
placeholder="sk-..."
className="mt-1"
defaultValue="sk-example-key-hidden"
/>
{/* API Keys Section */}
<CollapsibleSettingsCard title="API Keys" icon={Key} accentColor="pink" defaultExpanded={true}>
<Card edgePosition="top" edgeColor="pink">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6">
Manage your API keys and credentials for various services used by Archon.
</p>
<div className="space-y-4">
<div>
<Label htmlFor="openai-key" className="text-xs font-medium text-gray-600 dark:text-gray-400">
OPENAI_API_KEY
</Label>
<Input
id="openai-key"
type="password"
placeholder="Enter new value (encrypted)"
className="mt-2"
defaultValue="••••••••••••••••••"
/>
</div>
<div>
<Label htmlFor="google-key" className="text-xs font-medium text-gray-600 dark:text-gray-400">
GOOGLE_API_KEY
</Label>
<Input
id="google-key"
type="password"
placeholder="Enter new value (encrypted)"
className="mt-2"
defaultValue="••••••••••••••••"
/>
</div>
</div>
<div>
<Label htmlFor="anthropic-key">Anthropic API Key</Label>
<Input
id="anthropic-key"
type="password"
placeholder="sk-ant-..."
className="mt-1"
defaultValue="sk-ant-example-key"
/>
</div>
</div>
</Card>
</CollapsibleSettingsCard>
{/* Database Settings */}
<CollapsibleSettingsCard
title="Database Settings"
icon={Database}
accentColor="blue"
defaultExpanded={false}
>
<div className="space-y-4">
<Card edgePosition="top" edgeColor="blue">
<div>
<Label htmlFor="db-url">Database URL</Label>
<Label htmlFor="db-url" className="text-sm font-medium">Database URL</Label>
<Input
id="db-url"
placeholder="postgresql://..."
className="mt-1"
className="mt-2"
defaultValue="postgresql://localhost:5432/archon"
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="auto-backup">Auto Backup</Label>
<div className="flex items-center justify-between mt-4">
<Label htmlFor="auto-backup" className="text-sm font-medium">Auto Backup</Label>
<Switch id="auto-backup" />
</div>
</div>
</Card>
</CollapsibleSettingsCard>
{/* Code Extraction */}
<CollapsibleSettingsCard
title="Code Extraction"
icon={Code}
accentColor="green"
defaultExpanded={false}
>
<div className="space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="extract-code">Extract Code Examples</Label>
<Card edgePosition="top" edgeColor="green">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
Configure how code blocks are extracted from crawled documents.
</p>
<div className="flex items-center justify-between mb-4">
<Label htmlFor="extract-code" className="text-sm font-medium">Extract Code Examples</Label>
<Switch id="extract-code" defaultChecked />
</div>
<div>
<Label htmlFor="max-examples">Max Examples per Source</Label>
<Label htmlFor="max-examples" className="text-sm font-medium">Max Examples per Source</Label>
<Input
id="max-examples"
type="number"
placeholder="50"
className="mt-1"
className="mt-2"
defaultValue="50"
/>
</div>
</div>
</Card>
</CollapsibleSettingsCard>
{/* RAG Configuration */}
<CollapsibleSettingsCard
title="RAG Configuration"
icon={Settings}
accentColor="orange"
defaultExpanded={true}
>
<div className="space-y-4">
<Card edgePosition="top" edgeColor="orange">
<div>
<Label htmlFor="match-count">Match Count</Label>
<Label htmlFor="match-count" className="text-sm font-medium">Match Count</Label>
<Input
id="match-count"
type="number"
placeholder="5"
className="mt-1"
className="mt-2"
defaultValue="5"
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="rerank">Enable Reranking</Label>
<div className="flex items-center justify-between mt-4">
<Label htmlFor="rerank" className="text-sm font-medium">Enable Reranking</Label>
<Switch id="rerank" defaultChecked />
</div>
</div>
</Card>
</CollapsibleSettingsCard>
{/* Crawling Settings */}
<CollapsibleSettingsCard
title="Crawling Settings"
icon={Globe}
accentColor="pink"
defaultExpanded={false}
>
<div className="space-y-4">
<Card edgePosition="top" edgeColor="pink">
<div>
<Label htmlFor="max-depth">Max Crawl Depth</Label>
<Label htmlFor="max-depth" className="text-sm font-medium">Max Crawl Depth</Label>
<Input
id="max-depth"
type="number"
placeholder="3"
className="mt-1"
className="mt-2"
defaultValue="3"
/>
</div>
<div className="flex items-center justify-between">
<Label htmlFor="follow-links">Follow External Links</Label>
<div className="flex items-center justify-between mt-4">
<Label htmlFor="follow-links" className="text-sm font-medium">Follow External Links</Label>
<Switch id="follow-links" />
</div>
</div>
</Card>
</CollapsibleSettingsCard>
</div>
</div>
);
};
};

View File

@@ -21,8 +21,8 @@ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
export const Card = React.forwardRef<HTMLDivElement, CardProps>(
({
className,
blur = 'xl', // Default to standard glass (3px blur - subtle)
transparency = 'light', // Default to subtle transparency (3%)
blur = 'xl',
transparency = 'light',
glassTint = 'none',
glowColor = 'none',
edgePosition = 'none',
@@ -33,42 +33,69 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
}, ref) => {
const glowVariant = glassCard.variants[glowColor] || glassCard.variants.none;
const hasEdge = edgePosition !== 'none';
const isHorizontalEdge = edgePosition === 'top' || edgePosition === 'bottom';
const edgeColorConfig = hasEdge ? glassCard.edgeLit.color[edgeColor] : null;
// Edge color mappings
const edgeColors = {
purple: { solid: 'bg-purple-500', gradient: 'from-purple-500/40', border: 'border-purple-500/30' },
blue: { solid: 'bg-blue-500', gradient: 'from-blue-500/40', border: 'border-blue-500/30' },
cyan: { solid: 'bg-cyan-500', gradient: 'from-cyan-500/40', border: 'border-cyan-500/30' },
green: { solid: 'bg-green-500', gradient: 'from-green-500/40', border: 'border-green-500/30' },
orange: { solid: 'bg-orange-500', gradient: 'from-orange-500/40', border: 'border-orange-500/30' },
pink: { solid: 'bg-pink-500', gradient: 'from-pink-500/40', border: 'border-pink-500/30' },
red: { solid: 'bg-red-500', gradient: 'from-red-500/40', border: 'border-red-500/30' },
};
const edgeStyle = edgeColors[edgeColor];
// Tint backgrounds for edge-lit cards
const tintBackgrounds = {
purple: 'bg-gradient-to-br from-purple-500/15 to-purple-600/5',
blue: 'bg-gradient-to-br from-blue-500/15 to-blue-600/5',
cyan: 'bg-gradient-to-br from-cyan-500/15 to-cyan-600/5',
green: 'bg-gradient-to-br from-green-500/15 to-green-600/5',
orange: 'bg-gradient-to-br from-orange-500/15 to-orange-600/5',
pink: 'bg-gradient-to-br from-pink-500/15 to-pink-600/5',
red: 'bg-gradient-to-br from-red-500/15 to-red-600/5',
};
if (hasEdge && edgePosition === 'top') {
// Edge-lit card with actual div elements (not pseudo-elements)
return (
<div
ref={ref}
className={cn(
"relative rounded-xl overflow-hidden",
edgeStyle.border,
className
)}
{...props}
>
{/* Top edge light bar */}
<div className={cn("absolute inset-x-0 top-0 h-[3px] pointer-events-none z-10", edgeStyle.solid)} />
{/* Glow bleeding into card */}
<div className={cn("absolute inset-x-0 top-0 h-16 bg-gradient-to-b to-transparent blur-lg pointer-events-none z-10", edgeStyle.gradient)} />
{/* Content with tinted background */}
<div className={cn("backdrop-blur-sm", tintBackgrounds[edgeColor], glassCard.sizes[size])}>
{children}
</div>
</div>
);
}
// Standard card (no edge-lit)
return (
<div
ref={ref}
className={cn(
// Base glass effect
glassCard.base,
// Backdrop blur intensity - consistent glass effect
glassCard.blur[blur],
// Apply background with proper transparency
glassTint !== 'none'
? glassCard.tints[glassTint][transparency]
: glassCard.transparency[transparency],
// Size
glassCard.sizes[size],
// Glow effects (border, shadow, hover) - only if no edge-lit
!hasEdge && glowVariant.border,
!hasEdge && glowVariant.glow,
!hasEdge && glowVariant.hover,
// Edge-lit effects
hasEdge && glassCard.edgeLit.position[edgePosition],
hasEdge && edgeColorConfig ? edgeColorConfig.glow : false,
hasEdge && edgeColorConfig ? (
isHorizontalEdge
? edgeColorConfig.gradient.horizontal
: edgeColorConfig.gradient.vertical
) : false,
// User overrides
className
)}
{...props}