|
| 1 | +# UI Guidelines & Design System |
| 2 | + |
| 3 | +This document outlines the UI components, styling conventions, design tokens, and best practices for developing HackLM Migrate interfaces. |
| 4 | + |
| 5 | +## 1. Design Tokens and Theming |
| 6 | + |
| 7 | +We use **Tailwind CSS v4** for our styling foundation. Core tokens are stored as CSS variables in `src/styles/global.css`. |
| 8 | + |
| 9 | +### Colors |
| 10 | +- **Background (`bg-background`)**: `#fbfbfb` (Light) / `#111111` (Dark) |
| 11 | +- **Accent (`text-accent`, `bg-accent`)**: `#fb631b` (Primary brand color) / Hover: `#e85310` |
| 12 | +- **Grid / Borders (`border-grid`)**: `#e2e2e2` (Light) / `#2a2a2a` (Dark) |
| 13 | +- **Text (`text-muted`, `text-faint`)**: `#666666`, `#999999` (Light) / `#888888`, `#555555` (Dark) |
| 14 | + |
| 15 | +### Typography |
| 16 | +- **Sans-Serif (`font-sans`)**: `Inter`, default for all regular UI text. |
| 17 | +- **Monospace (`font-mono`)**: `JetBrains Mono`, used for code blocks, badges, and technical readouts. |
| 18 | + |
| 19 | +### Sizing and Spacing |
| 20 | +- **Border Radius (`rounded-sm`)**: Default small radius is `4px` (`--radius-sm`). |
| 21 | +- **Icons**: Handled by `lucide-react`. Standard sizes used are usually `16px` for inline actions and `24px` for larger UI elements. |
| 22 | + |
| 23 | +### Dark Mode |
| 24 | +Dark mode is class-based. It triggers when an ancestor has the `.dark` class (applied via `@custom-variant dark (&:where(.dark, .dark *));`). |
| 25 | +Semantic tokens (like `--color-background`) automatically flip when in dark mode, making it easy to support both modes without writing `dark:` utility classes everywhere. |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## 2. Core Components |
| 30 | + |
| 31 | +### `HacklmIcon` & `HacklmLogo` |
| 32 | +- **Location**: `src/components/HacklmIcon.tsx` |
| 33 | +- **Usage**: Use this for displaying the brand logo. It dynamically selects the best resolution (`16`, `48`, `128`) based on the requested `size` prop and resolves the path for extension contexts using `chrome.runtime.getURL`. |
| 34 | +- **Example**: `<HacklmLogo size={24} />` |
| 35 | + |
| 36 | +### `MarkdownContent` |
| 37 | +- **Location**: `src/components/MarkdownContent.tsx` |
| 38 | +- **Usage**: Used to render extracted chat messages. Relies on `@tailwindcss/typography` (`prose`). |
| 39 | +- **Styling Details**: |
| 40 | + - Overrides standard `code` and `pre` tags to utilize `.bg-gray-100` and `font-mono`. |
| 41 | + - Enforces `break-all` on links to prevent layout overflows. |
| 42 | + - Horizontal scrolling enabled on tables and code blocks to keep chat bubbles contained. |
| 43 | + |
| 44 | +### `FloatingDial` |
| 45 | +- **Location**: `src/content-scripts/FloatingDial.tsx` |
| 46 | +- **Usage**: The draggable primary Speed-Dial FAB injected into host pages. |
| 47 | +- **Styling Details**: |
| 48 | + - Because content scripts run in host pages (which might have conflicting CSS), `FloatingDial` leans heavily on **inline styles** for layout positioning and animations to guarantee isolation. |
| 49 | + - Features high `z-index` (`2147483646` / `2147483647`) to sit above all host content. |
| 50 | + |
| 51 | +--- |
| 52 | + |
| 53 | +## 3. Styling Rules & Best Practices |
| 54 | + |
| 55 | +1. **Host Page Isolation (Content Scripts)**: |
| 56 | + When building UI injected directly into host pages (like `FloatingDial`), prefer robust inline styles or completely reset shadow-DOM constraints. Relying purely on global Tailwind classes might lead to styles being overridden or bleeding into the host site's CSS. |
| 57 | +2. **Extension Pages (Popup / Options)**: |
| 58 | + For dedicated extension pages, use standard Tailwind utility classes enthusiastically. |
| 59 | +3. **Accessibility**: |
| 60 | + Use `lucide-react` icons with appropriate `aria-label` or `title` hints. Ensure interactive elements show visual changes on `hover`, `focus`, and `active` states (e.g., dial buttons have hover background tweaks). |
| 61 | +4. **Animations**: |
| 62 | + Keep micro-interactions fast and subtle. For example, the `FloatingDial` uses a `0.15s ease` transition for background changes and a staggered entrance animation for child actions. |
| 63 | +5. **No Placeholders**: |
| 64 | + Ensure content behaves well when empty. `FloatingDial`'s restore modal gracefully renders an "Empty Vault" state natively. |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## 4. Component-Driven UI with Storybook |
| 69 | + |
| 70 | +We use [Storybook](https://storybook.js.org/) to develop and test components in isolation. This is especially useful for components like `HacklmIcon` and `MarkdownContent` which can be verified outside the browser extension environment. |
| 71 | + |
| 72 | +### Running Storybook |
| 73 | +To start the local Storybook server: |
| 74 | + |
| 75 | +```bash |
| 76 | +npm run storybook |
| 77 | +``` |
| 78 | + |
| 79 | +This will spin up a local server (typically at `http://localhost:6006` or `http://localhost:6007`) where you can interact with the documented components, toggle dark mode, and verify Tailwind styling. |
| 80 | + |
| 81 | +### Writing Stories |
| 82 | +When creating new reusable UI components in `src/components`, consider adding a `.stories.tsx` file alongside them. See `src/components/HacklmIcon.stories.tsx` or `src/components/MarkdownContent.stories.tsx` for examples. |
0 commit comments