Skill

Owner: Friday · Team: Dev Team · Source: ~/.openclaw/dev-shared/skills/frontend-component/SKILL.md

Build or edit React components/pages in silver-castle apps/web — placement, naming, sc-token styling, variant maps, icons, RTL, toasts, lazy routes, and the exact verification gates.


Playbook (mirrored from disk)

Frontend Component

Placement

  • Domain UI → src/features/<domain>/PascalCase.tsx (named export).
  • Reusable primitive → src/components/ui/ (check it doesn’t already exist!).
  • Page → src/pages/<role>/Foo.tsx (default export, THIN: fetch + layout; real UI in features/).

Styling

  • Tailwind utilities reading --sc-* tokens only (bg-sc-navy, text-sc-primary,
    rounded-sc-card…) — NEVER raw colors. Explicit px sizes as text-[13px].
  • Variants = plain map + concat (the house pattern — no cva/clsx):
    const variantCls: Record<Variant, string> = {...}
    className={`${base} ${variantCls[variant]} ${className}`}
  • Prebaked .sc-* classes (.sc-page, .sc-toast) are fine too.

Rules

  • Hebrew UI strings inline; layout must survive RTL (dir=rtl is global).
  • Icons: Lucide only, strokeWidth={1.5}, explicit size 14–18.
  • Every user action → toast: useToast().show(msg) / .celebrate(msg) (Hebrew copy).
  • Data: trpc.<domain>.<proc>.useQuery/useMutation; invalidate after mutations via
    trpc.useContext() (v10 — NOT useUtils). Loading: <div className="sc-page">טוען…</div>;
    errors: inline bg-sc-danger-bg text-sc-danger border-sc-danger div; empty: <EmptyState>.
  • New route → src/app/routes.tsx, lazy(() => import(...)) wrapped in the L() helper;
    guard with RequireAuth/RequireRole/RequireAction layout routes.

Gates (run both — vite build does NOT typecheck)

cd ~/silver-castle/apps/web && npx tsc -p tsconfig.app.json --noEmit   # bare tsc = NO-OP
cd ~/silver-castle && npm run build

No web test suite exists — final truth is built UI, looked at.