* feat: redesign ClawHub marketplace with modern utility store theme Update styles.css and index.tsx for new modern design Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * style: polish marketplace UI with modern design updates Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * fix: resolve 500 errors in TanStack Router loaders Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * fix: resolve SSR error bubbling in TanStack Router Ensure loader errors don't escape SSR and hydrate correctly. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: handle errors in Package API calls to prevent SSR and HMR errors Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: update branding to OpenClaw's black, white, and red color scheme Implement new color scheme across dark, light themes and interactive elements Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: use Vite's native tsconfig paths Replace deprecated plugin with native option and remove unused import. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * fix: add defensive checks in fetchPluginCatalog Ensure proper handling of undefined and unexpected API responses. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * fix: add defensive checks to PluginsIndex for SSR errors Handle undefined loader data in PluginsIndex component. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * refactor: optimize skill detail page layout Redesign skill detail page to maximize space, remove sidebar, create metadata bar, and add responsive breakpoints. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * fix: add global overflow protection to detail pages Add overflow prevention for text elements and links. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: highlight parent tabs with activePathPrefixes Add activePathPrefixes to NavItem and update navigation to highlight parent tabs. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: add user preferences customization section Add 'usePreferences' hook and new Switch component; enhance settings page with Customization section. Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * feat: optimize layout and create DESIGN.md Fix orphan cards, enforce equal card heights, add branding accents, improve visual hierarchy, add responsive breakpoints, create design document Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> * Update src/routes/plugins/index.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update src/components/layout/Container.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --------- Co-authored-by: v0 <v0[bot]@users.noreply.github.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
7.9 KiB
7.9 KiB
ClawHub Design System
This document outlines the design rules, patterns, and guidelines for the ClawHub platform to ensure consistency, accessibility, and maintainability across all components.
Color System
Brand Palette (OpenClaw)
ClawHub uses a strict 3-5 color palette based on the OpenClaw brand:
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--accent |
#dc2626 |
#dc2626 |
Primary actions, interactive elements, emphasis |
--accent-deep |
#b91c1c |
#ef4444 |
Hover states, secondary emphasis |
--ink |
#0a0a0a |
#fafafa |
Primary text |
--ink-soft |
#525252 |
#a1a1a1 |
Secondary text, descriptions |
--surface |
#ffffff |
#121212 |
Card backgrounds, elevated surfaces |
--bg |
#fafafa |
#0a0a0a |
Page background |
Rules
- Never exceed 5 colors without explicit design approval
- Never use purple/violet prominently unless explicitly requested
- Always override text color when changing background color to ensure contrast
- Use semantic tokens (
--accent,--ink,--surface) instead of raw colors
Typography
Font Stack
--font-sans: 'Geist', system-ui, sans-serif;
--font-mono: 'Geist Mono', monospace;
--font-display: 'Geist', system-ui, sans-serif;
Scale
| Token | Size | Usage |
|---|---|---|
--fs-xs |
0.75rem (12px) | Labels, badges, metadata |
--fs-sm |
0.875rem (14px) | Body text, descriptions |
--fs-base |
1rem (16px) | Default body text |
--fs-md |
1.125rem (18px) | Subheadings |
--fs-lg |
1.25rem (20px) | Section titles |
--fs-xl |
1.5rem (24px) | Page headings |
Rules
- Maximum 2 font families per page
- Line height 1.4-1.6 for body text (use
leading-relaxed) - Never use decorative fonts for body text
- Minimum font size: 14px for readability
- Use
text-balanceortext-prettyfor titles
Layout
Method Priority
Use this hierarchy for layout decisions:
- Flexbox - Default for most layouts
- CSS Grid - Only for complex 2D layouts (cards, galleries)
- Never use floats or absolute positioning unless absolutely necessary
Spacing Scale
--space-1: 0.25rem /* 4px */
--space-2: 0.5rem /* 8px */
--space-3: 0.75rem /* 12px */
--space-4: 1rem /* 16px */
--space-5: 1.5rem /* 24px */
--space-6: 2rem /* 32px */
Grid Patterns
Auto-fit Grid (Recommended for Cards)
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
- Automatically adjusts columns based on container width
- Prevents orphan items on partial rows
- Maintains consistent card widths
Fixed Grid (When exact columns needed)
/* 3-column at desktop, 2 at tablet, 1 at mobile */
grid-template-columns: repeat(3, minmax(0, 1fr));
@media (max-width: 860px) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 520px) {
grid-template-columns: 1fr;
}
Container Widths
| Size | Max Width | Usage |
|---|---|---|
| Default | --page-max (1200px) |
Standard pages |
| Narrow | --page-narrow (720px) |
Reading content, forms |
| Wide | Full width | Dashboards, data tables |
Components
Cards
.card {
padding: var(--space-4);
border: 1px solid var(--line);
border-radius: var(--r-md);
background: var(--surface);
}
Rules:
- Always use
display: flex; flex-direction: column;for consistent height - Add
flex: 1to content area for equal-height cards in grids - Include hover state with
border-colorand subtlebox-shadow
Buttons
| Variant | Usage |
|---|---|
primary |
Main actions (Submit, Save, Download) |
secondary |
Alternative actions |
ghost |
Tertiary actions, navigation |
destructive |
Delete, remove, dangerous actions |
Rules:
- Always include visible focus state
- Minimum touch target: 44x44px on mobile
- Include
aria-labelwhen icon-only
Form Controls
- Labels above inputs (not inline)
- Error states use
--status-error-fg - Focus rings use
--accentwith 0.2 opacity - Minimum input height: 40px
Responsive Breakpoints
/* Mobile first - base styles for mobile */
@media (min-width: 520px) {
/* Small tablets, large phones */
}
@media (min-width: 640px) {
/* Tablets */
}
@media (min-width: 860px) {
/* Small desktops, landscape tablets */
}
@media (min-width: 1024px) {
/* Desktops */
}
@media (min-width: 1280px) {
/* Large desktops */
}
Rules
- Mobile-first approach - Base styles target mobile
- Progressive enhancement - Add complexity as viewport increases
- Test intermediate breakpoints - Avoid jarring layout jumps
- Never hide critical content on mobile
Accessibility
Color Contrast
- Normal text: Minimum 4.5:1 ratio
- Large text (18px+): Minimum 3:1 ratio
- Interactive elements: Minimum 3:1 ratio
Focus States
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 2px;
}
Screen Readers
- Use
sr-onlyclass for visually hidden but accessible text - Always include
alttext for images (emptyalt=""for decorative) - Use semantic HTML elements (
main,nav,article,section) - Proper heading hierarchy (h1 > h2 > h3, no skipping)
Motion
/* Respect user preference */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Animation
Timing
--transition-fast: 150ms;
--transition-base: 200ms;
--transition-slow: 300ms;
Easing
- Use
easeorease-outfor most transitions - Use
ease-in-outfor enter/exit animations - Never use
linearexcept for continuous animations
Rules
- Subtle by default - Avoid flashy animations
- Purpose-driven - Animation should provide feedback
- Respect preferences - Support
prefers-reduced-motion - Performance - Use
transformandopacityonly
Icons
Usage
- Use Lucide icons consistently
- Standard sizes: 14px, 16px, 20px, 24px
- Include
aria-hidden="true"for decorative icons - Never use emojis as icons
Placement
- Left of labels in buttons and navigation
- Right of labels for external links or dropdowns
- Centered when used alone with
aria-label
Dark Mode
Implementation
[data-theme="dark"] {
/* Dark mode overrides */
}
Rules
- Never use pure white (
#ffffff) on dark backgrounds - Reduce shadow intensity in dark mode
- Adjust image brightness if needed
- Test contrast ratios in both modes
Performance
CSS
- Use CSS custom properties for theming
- Avoid deeply nested selectors (max 3 levels)
- Use
will-changesparingly - Prefer
transformovertop/leftfor animations
Images
- Always specify
widthandheightattributes - Use
loading="lazy"for below-fold images - Use appropriate formats (WebP with fallbacks)
- Include placeholder or skeleton states
Code Style
CSS Class Naming
/* Component */
.component-name { }
/* Component modifier */
.component-name.variant { }
/* Component child */
.component-name-child { }
/* State */
.component-name.is-active { }
.component-name[data-state="open"] { }
File Organization
src/
components/
ui/ # Primitive components (Button, Input, Card)
layout/ # Layout components (Container, Header)
styles.css # Global styles and design tokens
lib/
theme.ts # Theme utilities
preferences.ts # User preference management
Checklist
Before shipping any UI changes, verify:
- Color contrast meets WCAG AA standards
- Focus states are visible
- Layout works at all breakpoints
- Animations respect
prefers-reduced-motion - Text is readable at default browser zoom
- Interactive elements have 44px minimum touch target
- Semantic HTML is used appropriately
- Dark mode has been tested