Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .compliance/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,19 @@ ignore_paths:
- ".github/**"
- ".storybook/**"
- ".devcontainer/**"

# Suppress database-related rules for the showcase app.
# The showcase uses a minimal SQLite DB for demo/testing purposes only;
# it is not a production system and does not require tenant isolation,
# role separation, or MFA enforcement.
suppressions:
- rule: CON-DVO-002
paths:
- "packages/showcase/src/database/**"
- "packages/showcase/src/types/**"
reason: "Showcase DB is for testing/demo only, not a production system"
- rule: CON-PFM-001
paths:
- "packages/showcase/src/database/**"
- "packages/showcase/src/types/**"
reason: "Showcase DB is for testing/demo only, no tenant isolation needed"
58 changes: 0 additions & 58 deletions .cursor/rules/coding.mdc

This file was deleted.

105 changes: 29 additions & 76 deletions .cursor/rules/components.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ description: Component implementation
globs:
alwaysApply: false
---
# Implementation Instructions – UIKit Components
# Implementation Instructions – UI-Kit Components

These rules are **mandatory** for every developer or AI agent implementing components, layouts, hooks or utilities inside the `ui-kit` package. They guarantee a coherent, theme‑friendly codebase and align with the chapters in *planning.md* and the DoD in *project\_plan.md*.
These rules are **mandatory** for every developer or AI agent implementing components, layouts, hooks or utilities inside the `ui-kit` package.

---

Expand All @@ -14,16 +14,18 @@ These rules are **mandatory** for every developer or AI agent implementing compo
```
ui-kit/src/
components/
primitives/ # unconstrained building blocks (Button, Input…)
primitives/ # building blocks (Button, Input…)
form/
data-display/
feedback/
navigation/
overlay/ # Modal, ConfirmModal, Drawer

layout/ # page shells & navigation wrappers
hooks/ # non-UI hooks (useDebounce, useBreakpoint…)
providers/ # React context providers (ThemeProvider…)
theme/ # CSS variables, Tailwind preset, DaisyUI patch
styles/ # globals.css (CSS variables, Tailwind base)
theme/ # TOKENS.md, theme utilities
utils/ # helpers (cn, useToast,…)
```

Expand All @@ -32,55 +34,41 @@ ui-kit/src/

* `index.ts` (re-export)
* `<Component>.tsx`
* `<Component>.stories.mdx`
* `<Component>.stories.tsx` (or `.mdx`)
* `<Component>.test.tsx`
* optional `types.ts` or sub-components.

---

## 2 Styling & theme contract

### 2.1 DaisyUI token bridge
### 2.1 CSS variables (Shadcn-native)

`ui-kit/src/theme/theme.css` defines:
All design tokens are defined in `styles/globals.css` using Shadcn conventions:
- `:root` block for light mode (raw HSL channels, e.g. `--primary: 222 47% 31%`)
- `.dark` block for dark mode
- Tailwind config wraps them with `hsl()` (e.g. `primary: "hsl(var(--primary))"`)

```css
:root {
/* DaisyUI HSL tokens → Shadcn variables */
--primary: hsl(var(--p)); /* primary */
--background: hsl(var(--b1)); /* base-100 */
--foreground: hsl(var(--bc)); /* base-content */
--border: hsl(var(--b2)); /* base-200 */
}
.dark {
--primary: hsl(var(--pf));
--background: hsl(var(--n));
--foreground: hsl(var(--nc));
--border: hsl(var(--b3));
}
```
Standard tokens: `--background`, `--foreground`, `--primary`, `--secondary`, `--accent`, `--destructive`, `--muted`, `--card`, `--popover`, `--border-color`, `--input`, `--ring`.

Status tokens: `--success`, `--warning`, `--error`, `--info` (each with `-foreground` counterpart).

### 2.2 Tailwind usage rules

* Use **utility classes** only inside `ui-kit`. Never emit Tailwind classes from public API.
* Prefer semantic wrapper props over styling props.
Example:

```tsx
<Button intent="danger" size="sm" />
```
* Use `clsx` + `tailwind-merge` helper from `ui-kit/utils/classMerge.ts` to compose class strings.
* Use `cn()` helper (clsx + tailwind-merge) to compose class strings.
* Use Tailwind color utilities that reference CSS vars: `bg-primary`, `text-foreground`, `border-border`, etc.

### 2.3 No inline colours

* Never hardcode colours like `bg-red-500`; always reference `bg-[hsl(var(--primary))]` or DaisyUI utility (`btn-error`).
* Never hard-code colours like `bg-red-500`; always use semantic tokens (`bg-primary`, `bg-destructive`, `bg-success`, etc.).

---

## 3 Component pattern (wrapper around Shadcn)

```tsx
// src/components/primitives/Button/Button.tsx
import { Button as ShadButton } from '@/components/ui/button';
import { cn } from '@/utils/cn';

Expand All @@ -95,8 +83,8 @@ export function Button({ intent = 'default', size = 'md', className, ...rest }:
{...rest}
className={cn(
'transition-colors',
intent === 'primary' && 'bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] hover:brightness-110',
intent === 'danger' && 'bg-error text-error-content',
intent === 'primary' && 'bg-primary text-primary-foreground hover:brightness-110',
intent === 'danger' && 'bg-destructive text-destructive-foreground',
size === 'sm' && 'px-2 py-1 text-sm',
className,
)}
Expand All @@ -110,45 +98,14 @@ export function Button({ intent = 'default', size = 'md', className, ...rest }:

---

## 4 Storybook MDX template

```mdx
import { Button } from '@/components/primitives/Button';

# Button

Basic usage of `Button`.

<Button intent="primary">Primary</Button>

<Canvas>
<Story name="Variants" args={{ intent: 'default' }}>
{({ intent }) => <Button intent={intent}>Button</Button>}
</Story>
</Canvas>

<ArgsTable of={Button} />
```
## 4 Storybook stories

* Each story **must** include a Canvas demo and an ArgsTable.
* Add `parameters = { a11y: { disable: false } }` if you need to tweak axe rules.

---

## 5 Unit + a11y tests

```tsx
// src/core/Button/Button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
it('renders with text', () => {
render(<Button>Foo</Button>);
expect(screen.getByRole('button', { name: 'Foo' })).toBeInTheDocument();
});
});
```
## 5 Unit + a11y tests

* All tests go in `__tests__` or `<Component>.test.tsx`.
* Coverage target per sprint (see roadmap).
Expand All @@ -166,18 +123,16 @@ describe('Button', () => {

## 7 Layouts

Layout components extend `MainLayout` via props: `collapsed`, `fixed`, `dense`.

* Use CSS grid: `grid-cols-[200px_1fr]` for default, `grid-cols-[1fr]` when collapsed.
* Use CSS grid for sidebar layouts.
* TopBar height fixed at `h-14`.
* Breadcrumb slot uses `<slot name="breadcrumb" />` pattern for flexibility.
* Breadcrumb slot pattern for flexibility.

---

## 8 Theme tokens & designtoken docs
## 8 Theme tokens & design-token docs

* Update `theme/TOKENS.md` whenever adding a new CSS var.
* Run CI step `tokens-check` (script provided in Sprint 1.5) – it fails if variable doc missing.
* Run CI step `tokens-check` – it fails if variable doc missing.

---

Expand All @@ -193,11 +148,9 @@ Layout components extend `MainLayout` via props: `collapsed`, `fixed`, `dense`.
### Checklist for new component PRs

1. Component & wrapper written under correct folder.
2. Tailwind classes refer to CSS vars / DaisyUI tokens.
3. Storybook MDX with ArgsTable.
4. Vitest unit test + axecore pass.
2. Tailwind classes use semantic CSS variable tokens (no hardcoded colours).
3. Storybook story with ArgsTable.
4. Vitest unit test + axe-core pass.
5. Added export to `index.ts`.
6. Changeset file committed.
7. PR passes lint, test, build in CI.

> PR reviewers should tick all checklist items before merge.
7 changes: 6 additions & 1 deletion .cursor/rules/state_mgmt_rules.mdc
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
---
description: State management patterns for the ui-kit and consuming apps
globs:
alwaysApply: true
---
# Cursor Rule File – State Management

- **Local UI state:** `useState`, `useReducer` only; no derived data in state.
- **Global session:** Zustand store; strictly side-effect-free actions.
- **Remote data:** TanStack Query; disable refetchOnWindowFocus if not needed.
- No direct fetch in components; use query hooks.
- Forms handled by React Hook Form + Zod; no uncontrolled input hacks.
- ESLint custom rule enforces named effects & cleanup.
- ESLint custom rule enforces named effects & cleanup.
14 changes: 8 additions & 6 deletions .cursor/rules/styling_rules.mdc
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
---
description:
description: Tailwind and Shadcn styling conventions for the ui-kit
globs:
alwaysApply: true
---
# Cursor Rule File – Tailwind, Shadcn, DaisyUI
# Cursor Rule File – Tailwind & Shadcn Styling

- Tailwind classes **only inside ui-kit**; no classes in consuming apps.
- Always use shadcn ui components with the shadcn CLI (npx shadcn@latest <command>)
- Never override Shadcn component CSS directly; extend via wrapper props.
- Colours/spacings via CSS vars mapped to DaisyUI tokens.
- Use `@apply` sparingly inside `theme.css`, never in JSX.
- Dark-mode via `class="dark"`; avoid media mode.
- No custom global CSS unless a new token/utility is required.
- Colours and spacings via CSS variables defined in `globals.css` (`:root` and `.dark` selectors).
- Status colours use semantic tokens: `--success`, `--warning`, `--error`, `--info` (with `-foreground` counterparts).
- Use `@apply` sparingly inside `globals.css`, never in JSX.
- Dark mode via `class="dark"` on `<html>`; avoid media-query mode.
- No custom global CSS unless a new token/utility is required.
- No DaisyUI classes or tokens — the project uses Shadcn-native theming only.
53 changes: 53 additions & 0 deletions .cursor/skills/add-component/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: add-component
description: Add a new UI component to the ui-kit package following project conventions. Use when creating a new component, wrapping a Shadcn primitive, or adding a feedback/layout/form component.
---

# Add Component to UI Kit

## Directory Structure

Create under `packages/ui-kit/src/components/<category>/<ComponentName>/`:

```
ComponentName/
├── index.ts # Re-exports
├── ComponentName.tsx # Implementation
├── ComponentName.test.tsx # Tests
└── ComponentName.stories.tsx # (optional) Storybook story
```

Categories: `primitives`, `form`, `feedback`, `data-display`, `layout`, `ui`, `brand`.

## Implementation Checklist

1. **Create component file** (`ComponentName.tsx`):

- Named export only (no default exports)
- Export prop interface with JSDoc
- Use `cn()` from `../../../lib/utils` for class merging
- Use Shadcn CSS variables (e.g. `bg-primary`, `text-foreground`) -- never hardcoded colors
- Wrap Shadcn primitives from `../../ui/` when applicable

2. **Create barrel export** (`index.ts`):

```typescript
export { ComponentName } from "./ComponentName";
export type { ComponentNameProps } from "./ComponentName";
```

3. **Register in parent barrel** -- add `export * from './ComponentName';` to the category's `index.ts`

4. **Write tests** (`ComponentName.test.tsx`):

- Render test, prop tests, accessibility check with axe-core if applicable
- Use `vitest` + `@testing-library/react`

5. **Verify**: Run `pnpm lint && pnpm test && pnpm build` from workspace root

## Key Conventions

- No `import React from 'react'` -- use `import * as React from 'react'` only if needed
- Colors via CSS variables only: `bg-background`, `text-muted-foreground`, `border-input`
- No DaisyUI classes -- this project uses Shadcn-native theming
- Tailwind classes only inside ui-kit, never exposed via public API
Loading