Skip to content
Draft
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
9 changes: 7 additions & 2 deletions backend/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,16 @@ This requirement also means that we MUST NOT have copies of details in long term

### Agent-Specific Documentation

- [Code Quality Rules](docs/agent/code_quality_rules.md) - Exception handling, complexity, and formatting rules
The `docs/agent/` folder contains documentation for AI agents. See [docs/agent/ABOUT.md](docs/agent/ABOUT.md) for the full structure.

When working on frontend issues, see:
**Permanent guidelines (always relevant):**

- [Code Quality Rules](docs/agent/code_quality_rules.md) - Exception handling, complexity, and formatting rules
- [Frontend Design System](docs/agent/frontend_design_system.md) - GOV.UK styling and build pipeline
- [GOV.UK Components](docs/agent/govuk_components.md) - Component usage and HTML examples
- [Frontend Testing](docs/agent/frontend_testing.md) - Playwright MCP debugging workflows
- [Migration Notes](docs/agent/migration_notes.md) - Bootstrap to GOV.UK conversion guide

**Active development folders** contain specs for current work (e.g., `547-component-redesign/`).

**Historical specs** are in `docs/agent/history/` - consult these only when you need context about past architectural decisions.
152 changes: 152 additions & 0 deletions backend/docs/agent/547-component-redesign/button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
Redesign the button component in our design system to match the following Figma specification from the OpenDLP UI kit. The button system has 4 variants (Primary, Secondary, Tertiary, Icon-only), each with Default and Hover states, plus a Focus ring treatment. Implement this as a reusable component (React + CSS/Tailwind or CSS variables — adapt to whatever framework the project uses).

---

### DESIGN TOKENS (Color Palette)

Use CSS custom properties (or your framework's equivalent) for these semantic tokens:

- `--color-brand-400`: #90003F (primary button default bg, focus ring border)
- `--color-brand-600`: #720046 (primary button hover bg)
- `--color-neutral-50`: #F7F7F8 (page/section background)
- `--color-neutral-200`: #E1E2E5 (hover bg for secondary, tertiary, and icon-only buttons)
- `--color-neutrals-700`: #2F3442 (secondary button border, secondary/tertiary text & icon color)
- `--color-white`: #FFFFFF (primary button text/icon color, secondary button default bg)

---

### SHARED BUTTON ANATOMY

Every button (except icon-only) is composed of three optional slots arranged horizontally:

1. **Leading icon** (optional) — 16×16px, instance-swappable (e.g., "edit" pencil icon)
2. **Label** — text content
3. **Trailing icon** (optional) — 16×16px, instance-swappable (e.g., "chevron_forward" rotated −90° to form a dropdown caret)

Layout:
- Flow: Horizontal (flexbox row), vertically centered
- Gap between slots: 8px
- Width: Hug content (auto), or can be set to Fixed
- Height: Hug content, resolves to 40px with the given padding + 16px line-height

---

### TYPOGRAPHY (all button labels)

- Font family: Lato
- Font weight: 600 (SemiBold)
- Font size: 14px
- Line height: 16px
- Letter spacing: 0.4px

---

### VARIANT 1: PRIMARY BUTTON

**Default state:**
- Background: brand-400 (#90003F)
- Border: none
- Border radius: 4px
- Padding: 12px top, 16px right, 12px bottom, 16px left
- Text color: white (#FFFFFF)
- Icon color: white (#FFFFFF)

**Hover state:**
- Background: brand-600 (#720046)
- All other properties same as default

---

### VARIANT 2: SECONDARY BUTTON

**Default state:**
- Background: white (#FFFFFF)
- Border: 1px solid neutrals-700 (#2F3442), inner alignment
- Border radius: 4px
- Padding: 12px top, 16px right, 12px bottom, 16px left
- Text color: neutrals-700 (#2F3442)
- Icon color: neutrals-700 (#2F3442)

**Hover state:**
- Background: neutral-200 (#E1E2E5)
- Border: 1px solid neutrals-700 (#2F3442)
- All other properties same as default

---

### VARIANT 3: TERTIARY (GHOST) BUTTON

**Default state:**
- Background: transparent (none)
- Border: none
- Border radius: 4px
- Padding: 12px top, 16px right, 12px bottom, 16px left
- Text color: neutrals-700 (#2F3442)
- Icon color: neutrals-700 (#2F3442)

**Hover state:**
- Background: neutral-200 (#E1E2E5)
- All other properties same as default

---

### VARIANT 4: ICON-ONLY BUTTON

**Default state:**
- Background: transparent (none)
- Border: none
- Border radius: 4px
- Padding: 12px top, 8px right, 12px bottom, 8px left
- Contains only a single 16×16px icon (e.g., "edit" pencil), no label, no trailing icon
- Icon color: neutrals-700 (#2F3442)
- Resolves to 40×40px (square)

**Hover state:**
- Background: neutral-200 (#E1E2E5)
- All other properties same as default

---

### FOCUS RING (applies to all variants on focus/focus-visible)

When focused, the button is wrapped in a visual focus indicator:
- Outer container padding around the button: 4px
- Border: 2px solid brand-400 (#90003F)
- Border radius: 8px (larger than the button's 4px to accommodate the offset)
- Total focused element height: ~48px (40px button + 4px padding top/bottom)

Implementation: Use a `box-shadow` or `outline` with offset, or a pseudo-element wrapper. Prefer `outline` + `outline-offset` for accessibility:
- `outline: 2px solid #90003F`
- `outline-offset: 4px`
- `border-radius: 8px` (use a pseudo-element if outline-radius isn't supported)

---

### COMPONENT API (Props)

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `variant` | `"primary" \| "secondary" \| "tertiary" \| "icon"` | `"primary"` | Visual style variant |
| `children` / `label` | `string` | — | Button label text (not used for icon variant) |
| `leadingIcon` | `ReactNode \| IconName` | `undefined` | Optional 16×16 icon before the label |
| `trailingIcon` | `ReactNode \| IconName` | `undefined` | Optional 16×16 icon after the label (e.g., dropdown caret) |
| `icon` | `ReactNode \| IconName` | `undefined` | Icon for icon-only variant |
| `disabled` | `boolean` | `false` | Disabled state (reduce opacity to ~0.5, remove pointer events) |
| `onClick` | `() => void` | — | Click handler |
| `type` | `"button" \| "submit" \| "reset"` | `"button"` | HTML button type |
| `fullWidth` | `boolean` | `false` | If true, button stretches to 100% container width |
| `as` | `"button" \| "a"` | `"button"` | Render as anchor for link-style buttons |
| `className` | `string` | — | Additional CSS class overrides |

---

### IMPLEMENTATION NOTES

1. All icons are 16×16px and should inherit their color from the button variant (white for primary, neutrals-700 for everything else).
2. The component should use CSS custom properties referencing the design tokens above, making theme changes easy.
3. Ensure keyboard accessibility: visible focus ring on Tab navigation (`:focus-visible`), not on mouse click.
4. Add `cursor: pointer` on interactive states, `cursor: not-allowed` on disabled.
5. Use `transition: background-color 150ms ease, border-color 150ms ease` for smooth hover transitions.
6. The trailing chevron icon in the Figma design is "chevron_forward" rotated −90° (pointing downward), used as a dropdown indicator.
7. The component name in Figma is "button primary" — reused across all variants with different styling overrides. In code, use a single `<Button>` component with a `variant` prop.
8. The Figma file uses a "Variable collection" and "Tokens" mode system (Auto / Mode 1), suggesting the design supports theming. Structure CSS variables to allow easy dark-mode or theme switching.
155 changes: 155 additions & 0 deletions backend/docs/agent/547-component-redesign/checkbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
**Container (row wrapper):**
- Flow: Horizontal (flexbox row), vertically centered
- Gap: 8px (between box and label)
- Width: Hug content (auto-sizes to content)
- Height: Hug content (resolves to ~20px with 16px box + alignment)

**Checkbox Box (the interactive square):**
- Width: 16px (`spacing/4`)
- Height: 16px (`spacing/4`)
- Border radius: 4px (`radius/sm`)
- Flow: Vertical (for centering the checkmark inside)
- Contains: checkmark icon when checked (12×12px / `spacing/3`)

**Label Text:**
- Font family: Lato
- Font weight: 500 (Medium)
- Font size: 14px
- Line height: 20px
- Letter spacing: 0.3px
- Color: neutrals-700 (#2F3442)

---

### STATE 1: DEFAULT (Unchecked)
`Checked: false, Disabled: false`

- Box background: theme/background (#FFFFFF — white)
- Box border: 1px solid brand-400 (#90003F), inner alignment
- Checkmark: not visible / not rendered
- Label color: neutrals-700 (#2F3442)
- Opacity: 100%
- Cursor: pointer

---

### STATE 2: SELECTED (Checked)
`Checked: true, Disabled: false`

- Box background: brand-400 (#90003F) — filled solid
- Box border: 1px solid brand-400 (#90003F), inner alignment
- Checkmark: white (#FFFFFF) check icon, 12×12px (`spacing/3`), centered in the box
- Label color: neutrals-700 (#2F3442)
- Opacity: 100%
- Cursor: pointer

---

### STATE 3: DEFAULT_DISABLED (Unchecked + Disabled)
`Checked: false, Disabled: true`

- Identical to DEFAULT state visually, but:
- **Opacity: 50%** (applied to entire row: box + label)
- Cursor: not-allowed
- Pointer events: none

---

### STATE 4: SELECTED_DISABLED (Checked + Disabled)
`Checked: true, Disabled: true`

- Identical to SELECTED state visually, but:
- **Opacity: 50%** (applied to entire row: box + label)
- Cursor: not-allowed
- Pointer events: none

---

### COMPONENT PROPERTIES (Figma Component Props → Code Props)

The Figma component exposes these properties:

| Figma Property | Code Prop | Type | Default | Description |
|----------------|-------------|-----------|----------|--------------------------------------|
| Checked | `checked` | `boolean` | `false` | Whether the checkbox is checked |
| Disabled | `disabled` | `boolean` | `false` | Whether the checkbox is disabled |
| (Label text) | `label` | `string` | `"Default"` | Text shown next to the checkbox |
| — | `onChange` | `(checked: boolean) => void` | — | Callback when toggled |
| — | `name` | `string` | — | Form field name |
| — | `id` | `string` | — | Unique ID for label association |
| — | `className` | `string` | — | Additional CSS class overrides |

In Figma, the 4 states are represented as a `Property 1` enum variant:
- `Default` → Checked=false, Disabled=false
- `Selected` → Checked=true, Disabled=false
- `Default_disabled` → Checked=false, Disabled=true
- `Selected_disabled` → Checked=true, Disabled=true

In code, use the two boolean props (`checked`, `disabled`) instead of a single variant enum.

---

### COMPONENT API (Suggested Props)
```tsx
interface CheckboxProps {
checked?: boolean;
disabled?: boolean;
label: string;
onChange?: (checked: boolean) => void;
name?: string;
id?: string;
className?: string;
indeterminate?: boolean; // optional: for tree/table partial selection
}
```

---

### CHECKMARK ICON

The checkmark inside the checked box:
- Component name in Figma: `check`
- Size: 12×12px (`spacing/3`)
- Color: white (#FFFFFF)
- Centered within the 16×16px box
- Implementation: use an inline SVG checkmark or an icon component. The SVG should be a simple check/tick path with `stroke: white` or `fill: white`.

Suggested SVG (12×12 viewBox):
```html
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M2.5 6L5 8.5L9.5 3.5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
```

---

### IMPLEMENTATION NOTES

1. **Accessibility:** Use a native `<input type="checkbox">` visually hidden (sr-only), with a `<label>` wrapping the custom box + text. This ensures keyboard navigation, screen reader support, and form compatibility.

2. **Disabled state:** Apply `opacity: 0.5` to the entire container (box + label), not individually. Add `pointer-events: none` and `cursor: not-allowed`.

3. **Focus ring:** Add a visible `:focus-visible` ring around the checkbox box for keyboard navigation. Use the same focus ring pattern from the Button component: `outline: 2px solid #90003F; outline-offset: 2px`.

4. **Transitions:** Add `transition: background-color 150ms ease, border-color 150ms ease, opacity 150ms ease` for smooth state changes.

5. **Hover state (not in Figma, recommended for UX):** On hover (when not disabled), slightly darken the border or add a subtle background change to the box to indicate interactivity. Consider `brand-600` (#720046) for the border on hover for the unchecked state, or a lighter brand tint for the background.

6. **Token-based sizing:** Use CSS custom properties for all sizes to enable easy scaling:
```css
--checkbox-size: 16px; /* spacing/4 */
--checkmark-size: 12px; /* spacing/3 */
--checkbox-radius: 4px; /* radius/sm */
--checkbox-gap: 8px; /* gap between box and label */
```

7. **The Figma file uses TailwindCSS tokens (Auto Default mode).** If using Tailwind, map the design tokens to your Tailwind config:
- `spacing/4` = `w-4 h-4` (16px)
- `spacing/3` = `w-3 h-3` (12px)
- `radius/sm` = `rounded` (4px)
- `gap: 8px` = `gap-2`
- `text-sm` for 14px, `font-medium` for weight 500, `leading-5` for 20px line-height

8. **Color consistency:** The checkbox border and checked fill both use `brand-400` (#90003F), the same color used for the primary button background and focus rings across the design system.

9. **Indeterminate state (optional enhancement):** While not shown in Figma, consider supporting an `indeterminate` prop that shows a horizontal dash (—) instead of a checkmark, useful for parent checkboxes in tree/table selection patterns. Use the same brand-400 fill with a white dash icon.
38 changes: 38 additions & 0 deletions backend/docs/agent/ABOUT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Agent Documentation

This folder contains documentation specifically for AI agents (Claude Code, etc.) working on this codebase.

## Folder Structure

```
docs/agent/
├── ABOUT.md # This file
├── [active-feature]/ # Active development specs (e.g., 547-component-redesign/)
├── code_quality_rules.md # Permanent: coding standards and rules
├── frontend_design_system.md # Permanent: design system overview
├── frontend_testing.md # Permanent: testing guidelines
├── govuk_components.md # Permanent: GOV.UK component reference
├── migration_notes.md # Permanent: migration guidelines
└── history/ # Completed/merged feature specs
```

## What Goes Where

### Top Level (Always Relevant)
- **Permanent guidelines** - Coding standards, testing approaches, design system docs
- **Active feature folders** - Current development work with specs and prompts

### history/ Folder
- **Completed specs** - Feature specifications that have been implemented and merged
- **Research docs** - Investigation notes for completed features
- **Implementation plans** - Plans for features that are now done

## For AI Agents

When exploring this codebase:

1. **Read top-level files** - These contain current guidelines and standards
2. **Check active feature folders** - These are what's currently being worked on
3. **Consult history/ sparingly** - Only when you need context about past decisions or patterns

The `history/` folder exists to preserve context without cluttering your immediate focus. If you need to understand why something was built a certain way, the historical specs can help.
10 changes: 0 additions & 10 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading