跳到主要内容
知仓学习社ZHICANG

skillshare-ui-website-style

>-

不碰外部(只输出文字)无严重或高危命中runkids/skillshare

它会碰到什么

扫了多少2 个文本文件,18 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

Enforce the skillshare design system across the two frontends. $ARGUMENTS is the file or area being worked on.

Companion skill: For UX design decisions beyond token/component usage — layout strategy, information hierarchy, interaction patterns, micro-copy, or when designing a new page from scratch — also invoke /ui-ux-pro-max for higher-level design guidance. This skill handles what components and tokens to use; /ui-ux-pro-max handles how to design the experience.

The project has two distinct design systems sharing semantic color names but with different visual treatments:

| Aspect | UI Dashboard (ui/) | Website (website/) |

|--------|---------------------|----------------------|

| Stack | React 19 + Vite + Tailwind CSS v4 | Docusaurus 3 + custom CSS |

| Font body | DM Sans | IBM Plex Sans |

| Font heading | DM Sans | Inter |

| Font mono | SFMono-Regular, Menlo | JetBrains Mono |

| Border-radius | Clean: 4px/8px/12px/pill | Wobbly: 255px 15px 225px 15px / ... |

| Shadows | Subtle blur: 0 1px 3px rgba(...) | Hard offset: 4px 4px 0px 0px #2d2d2d |

| Background | Flat #f7f6f3 | Dot grid on #fdfbf7 |

| Philosophy | skillshare-inspired minimal | Hand-drawn sketchy organic |


UI Dashboard (ui/)

Reference implementation: ui/src/pages/LogPage.tsx

> For the full human-readable style guide (design philosophy, visual rules, anti-patterns), see references/STYLE_GUIDE.md bundled with this skill.

Design Tokens

Defined in ui/src/index.css (@theme) and ui/src/design.ts:

// ui/src/design.ts
import { radius, shadows, palette } from '../design';

radius.sm   // '4px'  — badges, chips
radius.md   // '8px'  — cards, containers
radius.lg   // '12px' — modals, panels
radius.btn  // '9999px' — pill buttons (skillshare style)
radius.full // '9999px' — avatars

shadows.sm / .md / .lg / .hover / .active / .accent / .blue
palette.accent / .info / .success / .warning / .danger

Color Tokens (Tailwind classes)

| Role | Class | When |

|------|-------|------|

| Primary text | text-pencil | Titles, names, values |

| Secondary | text-pencil-light | Descriptions, timestamps, labels |

| Tertiary | text-muted-dark | Hints, placeholders |

| Success | text-success | Passed, synced, clean |

| Warning | text-warning | Dirty, behind, partial |

| Danger | text-danger | Failed, blocked, critical |

| Info / Blue | text-blue | Links, info badges, repo URLs |

| Background | bg-surface | Cards, inputs |

| Page bg | bg-paper | Root background |

| Borders | border-muted | Default borders |

Rule: Max one accent color per visual region. Don't double up — if a row has a colored dot, skip the colored badge (or vice versa).

Typography

  • Body: DM Sans (via --font-hand)
  • font-mono: timestamps, file paths, durations, code, hashes
  • uppercase tracking-wider: command names, stat labels
  • Size: text-2xl > text-xl > text-base > text-sm > text-xs

Page Structure (mandatory order)

Every page follows this layout:

<div className="space-y-5 animate-fade-in">
  <PageHeader icon={<Icon />} title="..." subtitle="..." actions={<>...</>} />

  {/* Toolbar: tabs + filters */}
  <div className="flex flex-wrap items-end gap-3">
    <SegmentedControl ... />
    <Select ... />
  </div>

  {/* Summary line or stat cards */}
  <SummaryLine ... />

  {/* Content: table, card list, or card grid */}
  {empty ? <EmptyState ... /> : <ContentArea />}

  {/* Dialogs (rendered at bottom, portal via DialogShell) */}
  <ConfirmDialog ... />
</div>

Component Library

| Component | File | API |

|-----------|------|-----|

| Card | Card.tsx | variant="default\|accent\|outlined", hover, overflow, tilt?, padding="none\|sm\|md" — accent uses thicker border for emphasis (no stripe) |

| Button | Button.tsx | variant="primary\|secondary\|danger\|ghost\|link", size="sm\|md\|lg", loading? |

| Badge | Badge.tsx | variant="default\|success\|warning\|danger\|info\|accent", size="sm\|md", dot? |

| PageHeader | PageHeader.tsx | icon, title, subtitle?, actions?, backTo? (styled back arrow) |

| EmptyState | EmptyState.tsx | icon (LucideIcon), title, description?, action? |

| ConfirmDialog | ConfirmDialog.tsx | open, onConfirm, onCancel, title, message, variant="default\|danger" |

| DialogShell | DialogShell.tsx | open, onClose, maxWidth, preventClose (backdrop blur + dialog-in animation) |

| Input | Input.tsx | label? + standard input props (re-exports Checkbox, Select) |

| Textarea | Input.tsx | label? + standard textarea props |

| Select | Select.tsx | label?, value, onChange, options[], size="sm\|md" |

| Checkbox | Checkbox.tsx | label, checked, onChange, indeterminate?, disabled?, size="sm\|md" |

| Spinner | Spinner.tsx | size="sm\|md\|lg" — use instead of <RefreshCw className="animate-spin"> |

| Tooltip | Tooltip.tsx | content: string, side="top\|bottom" — portal-based, 200ms delay |

| SegmentedControl | SegmentedControl.tsx | value, onChange, options[], connected?, colorFn? |

| Pagination | Pagination.tsx | page, totalPages, onPageChange, rangeText?, pageSize? |

| StatusBadge | StatusBadge.tsx | Status display |

| Skeleton / PageSkeleton | Skeleton.tsx | Shimmer animation loading states |

| Toast / useToast | Toast.tsx | toast(message, 'success'\|'error') — exit animation, progress bar, hover pause |

| FilterTagInput | FilterTagInput.tsx | Tag-based filter input |

| IconButton | IconButton.tsx | Icon-only button with aria-label |

Stats Patterns (choose one)

| Pattern | When |

|---------|------|

| Inline summary text | 1-3 stats: "42 ops · 3 errors · last: 2m ago" |

| Stat card grid | Dashboard overview KPIs only |

Status Patterns (choose one per element)

| Pattern | Markup | When |

|---------|--------|------|

| Colored dot | w-2 h-2 rounded-full | Table rows, list items, audit findings/rules |

| Badge | <Badge variant="..."> | Standalone labels |

List Patterns

| Pattern | When |

|---------|------|

| Table | Uniform rows, sortable columns, many items |

| Card list (vertical) | Mixed content per row, expandable |

| Card grid | Visual overview, few fields per item |

Button Variants

| Variant | When |

|---------|------|

| danger | Permanent destructive: clear log, empty trash, delete forever |

| secondary | Reversible removal: uninstall, remove, restore |

| ghost | Cancel, clear filter, reset |

| primary | Positive action: save, sync, install, run |

Separator

Always: border-dashed border-pencil-light/30 (unified opacity, not /20 or /40)

Animations

| Context | Value |

|---------|-------|

| Card rotation | rotate(+-0.15deg) via :nth-child(odd/even) |

| Standalone accent | Max rotate(+-0.3deg) |

| Hover | transition-all duration-150 |

| Page entry | animate-fade-in (0.2s ease-out) |

Keyboard Shortcuts

Registered in KeyboardShortcutsModal.tsx and useGlobalShortcuts.ts:

  • ? — shortcuts modal
  • / — focus search
  • g d/s/t/l — go to Dashboard/Skills/Targets/Log
  • r — refresh page
  • Only fire when no <input> / <textarea> focused
  • Chord timeout: 500ms
  • New shortcuts must be added to KeyboardShortcutsModal
  • Never override browser-native shortcuts (Cmd+C, etc.)

Accessibility

| Concern | Requirement |

|---------|-------------|

| Focus ring | focus:ring-2 focus:ring-blue/20 |

| Touch target | Min 44x44px |

| Color contrast | 4.5:1 (WCAG AA) |

| Icon buttons | aria-label required |

| Modals | role="dialog" + aria-modal="true" + useFocusTrap |

| Select | role="combobox" + aria-expanded + role="listbox/option" |

Card Overflow Gotcha

Card.tsx has overflow-hidden by default for border-radius clipping. Absolute-positioned children (dropdowns, tooltips) get clipped. Fix: pass overflow prop or add className="!overflow-visible".

Data Fetching Pattern

Pages use @tanstack/react-query:

const { data, isPending } = useQuery({
  queryKey: queryKeys.someKey(...),
  queryFn: () => api.someEndpoint(...),
  staleTime: staleTimes.someCategory,
});
  • Query keys: ui/src/lib/queryKeys.ts
  • API client: ui/src/api/client.ts
  • App context: ui/src/context/AppContext.tsx provides { isProjectMode, projectRoot }

Website (website/)

Docusaurus with hand-drawn "sketchy organic" design in website/src/css/custom.css.

Key Differences from UI Dashboard

  • Wobbly borders: border-radius: var(--radius-wobbly) (not clean px values)
  • Hard shadows: 4px 4px 0px 0px #2d2d2d (no blur)
  • Dot grid bg: radial-gradient(var(--color-muted) 1px, transparent 1px) on body
  • Post-it yellow: --color-postit: #fff9c4 for highlights
  • Dashed borders everywhere: navbar, sidebar, tables, pagination, code blocks
  • Button hover: transform: translate(2px, 2px) + shadow shrinks (press-down feel)
  • Links: wavy underline (text-decoration-style: wavy)
  • Dark mode: amber/gold primary (#e8a84c) instead of blue

CSS Variables

See website/src/css/custom.css for full list. Key additions beyond shared palette:

  • --radius-wobbly[-sm|-md|-btn] — hand-drawn border-radius
  • --color-postit[-dark] — yellow highlight
  • --shadow-md: 4px 4px 0px 0px #2d2d2d — hard offset
  • --card-bg, --card-border, --install-bg — component-specific

Docusaurus Classes

  • .button--primary — green bg, pencil border, hard shadow
  • .button--secondary — dashed border, no fill
  • .markdown h2 — dashed bottom border
  • .admonition — wobbly border-radius, left stripe
  • .menu__link--active — post-it yellow background
  • .target-badge — wobbly border for target grid
  • Code blocks get box-shadow: 4px 4px 0px 0px #101827

Homepage Components (website/src/pages/index.tsx)

  • CARD_ROTATIONS array for random hand-drawn tilt
  • WavyDivider — SVG dashed wavy line between sections
  • InstallTabs — tabbed install commands with copy button
  • Hero has hand-drawn SVG connector + underline

Anti-Patterns (Both Systems)

| Don't | Do Instead |

|-------|------------|

| Emojis as status icons | Colored dots, badges, or semantic icons |

| Stat cards for 1-3 values | Inline summary text |

| Left-border colored stripes (border-l-*) | Colored dots or badges — never use left stripe for emphasis or status |

| Stripe + badge for same status | Pick one per element |

| Mixed separator opacity (/20, /40) | Always border-pencil-light/30 |

| window.confirm() | <ConfirmDialog> component |

| Custom empty-state markup | <EmptyState> component |

| Inline styles for design tokens | Use Tailwind classes or design.ts exports |

| overflow-visible on Card without overflow prop | Pass overflow prop to Card |

| Dropdowns inside flex-wrap title rows | Put dropdowns on their own row |

Checklist Before Submitting

  • [ ] Uses existing components (Card, Badge, Button, etc.) — no custom markup for solved patterns
  • [ ] Page follows PageHeader → Toolbar → Summary → Content structure
  • [ ] Color tokens from Tailwind (text-pencil, not hardcoded #141312)
  • [ ] Separator is border-dashed border-pencil-light/30
  • [ ] Empty states use <EmptyState>
  • [ ] Destructive actions use <ConfirmDialog>
  • [ ] All icon buttons have aria-label
  • [ ] New shortcuts registered in KeyboardShortcutsModal
  • [ ] animate-fade-in on root container
  • [ ] Dark mode works (check both themes)

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。

它属于哪个仓库

星标★ 2,665
本站分层T1
该仓技能数9
原文件路径.skillshare/skills/skillshare-ui-website-style/SKILL.md

同一个仓库里的其他技能

看这个仓库的全部 9 个技能