--- paths: - "apps/sim/**/*.tsx" - "apps/sim/**/*.css" --- # Styling Rules ## Tailwind 1. **No inline styles** - Use Tailwind classes 2. **No duplicate dark classes** - Skip `dark:` when value matches light mode 3. **Exact values** - `text-[14px]`, `h-[26px]` 4. **Transitions** - `transition-colors` for interactive states ## Conditional Classes ```typescript import { cn } from '@sim/emcn'
``` ## CSS Variables For dynamic values (widths, heights) synced with stores: ```typescript // In store setWidth: (width) => { set({ width }) document.documentElement.style.setProperty('--sidebar-width', `${width}px`) } // In component ``` ## Text Scale Custom font sizes (`apps/sim/tailwind.config.ts`): `text-micro`=10px, `text-xs`=11px, `text-caption`=12px, `text-small`=13px, `text-base`=15px. `text-sm` is Tailwind default 14px. Field titles use `text-small` (13px); hints/errors use `text-caption` (12px). Icons default `size-[14px]`. Equal h/w → `size-*` (`size-[14px]`, `size-4`), never `h-N w-N`. ## Color Tokens Value text `--text-body`; muted/placeholder/labels `--text-muted`; icons `--text-icon`; borders `--border-1` (fields) / `--border` (dividers); surfaces `--surface-5` (light) / `--surface-4` (dark); active row `--surface-active`; error `--text-error`. No focus rings on chip surfaces. ## Chip Components (consumer usage) `ChipInput`, `ChipTextarea`, `ChipModal*` own their full chrome. Consumers describe intent through PROPS; they never re-style the chrome. The canonical chrome lives in `apps/sim/components/emcn/components/chip/chip-chrome.ts` (all tokens are re-exported from the `@sim/emcn` barrel — no subpath import needed) — never hand-roll `rounded-lg`/`border`/`bg-[var(--surface-5)]`/`h-[30px]`/`px-2`/`text-sm`/focus rings. ### Props over className - **Errors** → `error` prop. Never `className={cn(err && 'border-[var(--text-error)]')}`. - **Leading icon** → `icon` prop (rendered 14px in `--text-icon`). - **Trailing buttons** (reveal/copy/fetch) → `endAdornment`. - **Inner-input styling** (e.g. `font-mono`, number-spinner reset) → `inputClassName` (ChipInput only). See `app/workspace/[workspaceId]/settings/components/billing/components/usage-limit-field/usage-limit-field.tsx:117`. - **`ChipModalField` controls take NO className.** Pass `title`/`value`/`onChange`/`error`/`hint`/`required`/`flush`. The field owns label, control, and error/hint rendering. See `app/workspace/[workspaceId]/skills/components/skill-modal/skill-modal.tsx:170`. ### What className MAY carry Layout/sizing ONLY: `flex-1`, `w-full`, `w-[Npx]`, `min-w-0`, `max-w-*`, margins, `truncate`. Example: ``/`