@westpac/ui 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ # @westpac/ui Component Conventions
2
+
3
+ These conventions apply to all code in `packages/ui/`. Follow them when creating, modifying, or reviewing components.
4
+
5
+ ## File Structure
6
+
7
+ Every component lives in `src/components/{kebab-case-name}/` with these files:
8
+
9
+ - `index.ts` — Public exports (component + props type only, NOT styles)
10
+ - `{name}.component.tsx` — Component implementation
11
+ - `{name}.styles.ts` — Tailwind Variants styles
12
+ - `{name}.types.ts` — TypeScript types
13
+ - `{name}.spec.tsx` — Vitest + React Testing Library tests
14
+ - `{name}.stories.tsx` — Storybook stories
15
+
16
+ Optional: `{name}.utils.ts` for helpers, `components/` subdirectory for compound sub-components.
17
+
18
+ ## Import Conventions
19
+
20
+ - **Always use `.js` extensions** in relative imports (e.g., `'./button.styles.js'`)
21
+ - Import `ResponsiveVariants` from `../../types/responsive-variants.types.js`
22
+ - Import `useBreakpoint` from `../../hook/breakpoints.hook.js`
23
+ - Import `resolveResponsiveVariant` from `../../utils/breakpoint.util.js`
24
+ - Import `IconProps` from `../icon/index.js`
25
+
26
+ ## Types (`*.types.ts`)
27
+
28
+ - Derive variant types: `type Variants = VariantProps<typeof styles>`
29
+ - Wrap responsive props: `ResponsiveVariants<Variants['propName']>`
30
+ - JSDoc comment with `@default` tag on every prop
31
+ - Extend appropriate HTML attributes (`HTMLAttributes<HTMLDivElement>`, `ButtonHTMLAttributes<Element>`, etc.)
32
+ - Use `Omit<>` for conflicting HTML attributes (e.g., `Omit<InputHTMLAttributes, 'size'>`)
33
+
34
+ ## Styles (`*.styles.ts`)
35
+
36
+ - Use `tv()` from `tailwind-variants`, exported as `styles`
37
+ - Use `slots` for multi-element components
38
+ - Use `compoundSlots` for variant combinations
39
+ - Use GEL design tokens — never hardcode colors:
40
+ - Text: `text-text-body`, `text-text-muted`, `text-text-link`, `text-text-mono`
41
+ - Surface: `bg-surface-primary`, `bg-surface-hero`, `bg-surface-muted-pale`
42
+ - Hover: `hover:bg-surface-hover-*`
43
+ - Active: `active:bg-surface-active-*`
44
+ - Border: `border-border-primary`, `border-border-hero`, `border-border-muted-soft`
45
+ - Background: `bg-background-white`
46
+ - Typography: `typography-body-*`
47
+ - Focus: `focus-outline` (not custom focus rings)
48
+
49
+ ## Components (`*.component.tsx`)
50
+
51
+ - Add `'use client';` directive when using hooks or interactivity
52
+ - Use `forwardRef` pattern when appropriate: `Base{Name}` function + `forwardRef(Base{Name})` export
53
+ - Destructure `className` and pass to `styles({ className })` or `styles.base({ className })`
54
+ - Resolve responsive props: `resolveResponsiveVariant(prop, breakpoint)` with `useBreakpoint()`
55
+ - Use `useFocusRing()` + `mergeProps()` from `react-aria` for interactive components
56
+ - Use plain function declarations — do NOT use `React.FC`
57
+ - Set sensible default values in prop destructuring
58
+
59
+ ## Index (`index.ts`)
60
+
61
+ ```ts
62
+ export { ComponentName } from './component-name.component.js';
63
+ export { type ComponentNameProps } from './component-name.types.js';
64
+ ```
65
+
66
+ Do NOT re-export styles.
67
+
68
+ ## Tests (`*.spec.tsx`)
69
+
70
+ - Use `@testing-library/react` for rendering, `userEvent.setup()` for interactions
71
+ - Use `vi.fn()` for mocks, `waitFor()` for async assertions
72
+ - Import from `.component.js` (not index)
73
+ - Minimum: a "renders the component" test
74
+ - Pre-mocked globals (do NOT re-mock): `window.scrollTo`, `window.matchMedia`, `ResizeObserver`, `window.URL.createObjectURL`
75
+ - Style files (`*.styles.ts`) are excluded from test coverage
76
+
77
+ ## Stories (`*.stories.tsx`)
78
+
79
+ - Import from `@storybook/react-vite`
80
+ - Include `tags: ['autodocs']` and decorator `[(Story: StoryFn) => <Story />]`
81
+ - JSDoc comments above stories use `>` blockquote format
82
+ - Interactive stories using `useState` are defined as function components
83
+ - Use `fn()` from `storybook/test` for callback props
84
+
85
+ ## Registering New Components
86
+
87
+ After creating a component, add it to `src/components/index.ts`:
88
+
89
+ ```ts
90
+ export * from './{kebab-case-name}/index.js';
91
+ ```
92
+
93
+ ## Key Patterns
94
+
95
+ - **Responsive variants**: Use `ResponsiveVariants<T>` type, resolve with `resolveResponsiveVariant()` + `useBreakpoint()`
96
+ - **Compound components**: Use React Context, place sub-components in `components/` subdirectory
97
+ - **Icon props**: Type as `(props: IconProps) => JSX.Element`
98
+ - **Polymorphic tag**: `tag?: keyof JSX.IntrinsicElements` or a constrained subset
99
+
100
+ ## TypeScript Best Practices
101
+
102
+ - **No `any`** — Use proper types. If a type is truly unknown, use `unknown` and narrow it. The only acceptable escape hatch is `as unknown as TargetType` for complex generic interop (e.g., `forwardRef` with generics)
103
+ - **Prefer `type` over `interface`** for props — keeps consistency with `VariantProps` intersections (`&`)
104
+ - **Export types with `export { type ... }`** — use explicit `type` keyword for type-only exports
105
+ - **Derive types from source** — don't duplicate: use `VariantProps<typeof styles>`, `Pick<>`, `Omit<>`, and mapped types
106
+ - **Use `ReactNode` for children** — not `JSX.Element` or `React.ReactElement` (unless narrowing is required for compound components)
107
+ - **Type event handlers precisely** — use `React.MouseEvent<HTMLButtonElement>`, not generic `React.SyntheticEvent`
108
+ - **Avoid type assertions** — prefer type guards and narrowing over `as`. Use `satisfies` for validation without widening
109
+
110
+ ## React Best Practices
111
+
112
+ ### Component Design
113
+
114
+ - **One component per file** — the main component in `*.component.tsx`, sub-components in their own files under `components/`
115
+ - **Plain functions, not `React.FC`** — function declarations with explicit props typing: `function Button({ children }: ButtonProps)`
116
+ - **Destructure props at the function signature** — not inside the body. Order: `className`, variant props, behavioural props, `children`, `...rest`
117
+ - **Prefer composition over configuration** — use children and compound component patterns rather than deeply nested config objects (see Compacta, Repeater, ButtonGroup)
118
+ - **Keep components pure** — no side effects in render. Move side effects to `useEffect`
119
+
120
+ ### Hooks
121
+
122
+ - **`useMemo`** — for expensive computations or referentially stable objects/arrays passed to children. Don't over-use for primitive values
123
+ - **`useCallback`** — for event handlers passed to memoized children or used in dependency arrays
124
+ - **Custom hooks** — extract reusable logic into hooks in `src/hook/`. Prefix with `use`
125
+ - **Dependency arrays** — list all dependencies. Suppress lint warnings only with a comment explaining why
126
+ - **`useEffect` cleanup** — always clean up subscriptions, event listeners, and timers
127
+
128
+ ### Refs and DOM
129
+
130
+ - **`forwardRef`** — use for components that render a single native element consumers might need to reference
131
+ - **Type refs precisely** — `Ref<HTMLButtonElement>`, not `Ref<HTMLElement>` or `Ref<any>`
132
+ - **Don't read refs during render** — access `.current` only in effects or event handlers
133
+
134
+ ### State Management
135
+
136
+ - **Lift state only when needed** — keep state as close to where it's used as possible
137
+ - **React Context for compound components** — share state between parent and children (Accordion, List, Compacta)
138
+ - **`react-stately` for complex state** — use Adobe's hooks (`useDisclosureGroupState`, `useOverlayTriggerState`, etc.) instead of hand-rolling state machines
139
+ - **Controlled vs uncontrolled** — support both patterns where sensible. Use `defaultValue`/`value` naming convention
140
+
141
+ ### Performance
142
+
143
+ - **Don't prematurely optimise** — only add `memo()`, `useMemo`, `useCallback` when there's a measurable problem or the component is used in lists
144
+ - **Avoid inline object/array literals in JSX** — these create new references every render. Extract to `useMemo` or module scope if they're static
145
+ - **Key lists properly** — use stable, unique identifiers, never array index (unless the list is static and never reordered)
146
+
147
+ ### Patterns to Avoid
148
+
149
+ - **No `React.FC`** — doesn't support generics well and adds implicit `children`
150
+ - **No `default export` for components** — use named exports for better refactoring support and tree-shaking
151
+ - **No `// @ts-ignore` or `// @ts-expect-error`** — fix the type issue instead. If absolutely unavoidable, add a comment explaining why
152
+ - **No `useEffect` for derived state** — compute derived values directly or with `useMemo`, not by syncing state in effects
153
+ - **No prop drilling beyond 2 levels** — use Context or composition instead
154
+
155
+ ## Available Skills
156
+
157
+ Load these skills for specific tasks:
158
+
159
+ - **`creating-gel-component`** — Step-by-step scaffolding workflow with file templates for new components
160
+ - **`reviewing-gel-component`** — Checklist for auditing components against these conventions
161
+ - **`writing-gel-tests`** — Detailed guide for Vitest + React Testing Library test patterns, categories, and coverage targets
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: creating-gel-component
3
+ description: 'Scaffolds a new GEL design system UI component following project conventions. Use when creating a new component, adding a component, or scaffolding a component in packages/ui.'
4
+ ---
5
+
6
+ # Creating a GEL Component
7
+
8
+ Scaffolds a new React component in `packages/ui/src/components/`. All conventions (file naming, imports, patterns) are defined in the `packages/ui/.agents/AGENTS.md` — follow those automatically.
9
+
10
+ ## Step-by-Step Workflow
11
+
12
+ ### 1. Create the types file (`{name}.types.ts`)
13
+
14
+ ```tsx
15
+ import { HTMLAttributes } from 'react';
16
+ import { type VariantProps } from 'tailwind-variants';
17
+
18
+ import { ResponsiveVariants } from '../../types/responsive-variants.types.js';
19
+
20
+ import { styles } from './{kebab-case-name}.styles.js';
21
+
22
+ type Variants = VariantProps<typeof styles>;
23
+
24
+ export type {PascalName}Props = {
25
+ /**
26
+ * Description of variant prop
27
+ * @default defaultValue
28
+ */
29
+ variantProp?: ResponsiveVariants<Variants['variantProp']>;
30
+ } & HTMLAttributes<HTMLElement>;
31
+ ```
32
+
33
+ ### 2. Create the styles file (`{name}.styles.ts`)
34
+
35
+ ```ts
36
+ import { tv } from 'tailwind-variants';
37
+
38
+ export const styles = tv({
39
+ base: '',
40
+ variants: {},
41
+ });
42
+ ```
43
+
44
+ ### 3. Create the component file (`{name}.component.tsx`)
45
+
46
+ ```tsx
47
+ 'use client';
48
+
49
+ import React, { forwardRef, Ref } from 'react';
50
+ import { mergeProps, useFocusRing } from 'react-aria';
51
+
52
+ import { useBreakpoint } from '../../hook/breakpoints.hook.js';
53
+ import { resolveResponsiveVariant } from '../../utils/breakpoint.util.js';
54
+
55
+ import { styles as componentStyles } from './{kebab-case-name}.styles.js';
56
+ import { type {PascalName}Props } from './{kebab-case-name}.types.js';
57
+
58
+ function Base{PascalName}(
59
+ { className, variant = 'default', ...props }: {PascalName}Props,
60
+ ref: Ref<HTMLDivElement>,
61
+ ) {
62
+ const breakpoint = useBreakpoint();
63
+ const { isFocusVisible, focusProps } = useFocusRing();
64
+
65
+ return (
66
+ <div
67
+ ref={ref}
68
+ className={componentStyles({
69
+ className,
70
+ variant: resolveResponsiveVariant(variant, breakpoint),
71
+ isFocusVisible,
72
+ })}
73
+ {...mergeProps(props, focusProps)}
74
+ />
75
+ );
76
+ }
77
+
78
+ export const {PascalName} = forwardRef(Base{PascalName});
79
+ ```
80
+
81
+ ### 4. Create the index file (`index.ts`)
82
+
83
+ ```ts
84
+ export { {PascalName} } from './{kebab-case-name}.component.js';
85
+ export { type {PascalName}Props } from './{kebab-case-name}.types.js';
86
+ ```
87
+
88
+ ### 5. Create the test file (`{name}.spec.tsx`)
89
+
90
+ ```tsx
91
+ import { render } from '@testing-library/react';
92
+
93
+ import { {PascalName} } from './{kebab-case-name}.component.js';
94
+
95
+ describe('{PascalName}', () => {
96
+ it('renders the component', () => {
97
+ const { container } = render(<{PascalName} />);
98
+ expect(container).toBeInTheDocument();
99
+ });
100
+ });
101
+ ```
102
+
103
+ See the `writing-gel-tests` skill for comprehensive testing guidance.
104
+
105
+ ### 6. Create the stories file (`{name}.stories.tsx`)
106
+
107
+ ```tsx
108
+ import { type Meta, StoryFn, type StoryObj } from '@storybook/react-vite';
109
+
110
+ import { {PascalName} } from './{kebab-case-name}.component.js';
111
+
112
+ const meta: Meta<typeof {PascalName}> = {
113
+ title: 'Components/{PascalName}',
114
+ component: {PascalName},
115
+ tags: ['autodocs'],
116
+ decorators: [(Story: StoryFn) => <Story />],
117
+ };
118
+
119
+ export default meta;
120
+ type Story = StoryObj<typeof meta>;
121
+
122
+ /**
123
+ * > Default usage example
124
+ */
125
+ export const Default: Story = {
126
+ args: {},
127
+ };
128
+ ```
129
+
130
+ Interactive stories using `useState` can be defined as function components:
131
+
132
+ ```tsx
133
+ export const Example = () => {
134
+ const [state, setState] = useState(initialValue);
135
+
136
+ return <Component prop={state} onChange={setState} />;
137
+ };
138
+ ```
139
+
140
+ ### 7. Register the component
141
+
142
+ Add the export to `packages/ui/src/components/index.ts`:
143
+
144
+ ```ts
145
+ export * from './{kebab-case-name}/index.js';
146
+ ```
147
+
148
+ ### 8. Verify
149
+
150
+ Run these commands from `packages/ui/`:
151
+
152
+ - `pnpm vitest run src/components/{kebab-case-name}` — Run tests
153
+ - `pnpm build` — Verify build
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: reviewing-gel-component
3
+ description: 'Reviews GEL design system components for convention compliance, accessibility, and best practices. Use when reviewing a component, checking component quality, or auditing GEL components.'
4
+ ---
5
+
6
+ # Reviewing a GEL Component
7
+
8
+ Reviews components in `packages/ui/src/components/` against the conventions defined in `packages/ui/.agents/AGENTS.md`.
9
+
10
+ ## Review Checklist
11
+
12
+ ### 1. File Structure
13
+
14
+ - [ ] All required files exist: `index.ts`, `*.component.tsx`, `*.styles.ts`, `*.types.ts`, `*.spec.tsx`, `*.stories.tsx`
15
+ - [ ] File names use kebab-case matching the directory name
16
+ - [ ] Component is exported from `packages/ui/src/components/index.ts`
17
+
18
+ ### 2. Types
19
+
20
+ - [ ] `Variants` type alias derived from `VariantProps<typeof styles>`
21
+ - [ ] Responsive props wrapped with `ResponsiveVariants<Variants['...']>`
22
+ - [ ] Every prop has a JSDoc comment with `@default` tag where applicable
23
+ - [ ] Extends correct HTML attributes type
24
+ - [ ] Uses `Omit<>` for conflicting HTML attributes
25
+ - [ ] `.js` extensions on relative imports
26
+
27
+ ### 3. Styles
28
+
29
+ - [ ] Uses tailwind styling except when animations/dynamic styles are required
30
+ - [ ] Uses `tv()` from `tailwind-variants`, exported as `styles`
31
+ - [ ] Uses GEL design tokens — no hardcoded colors
32
+ - [ ] Uses `typography-body-*` for text, `focus-outline` for focus
33
+ - [ ] Uses `slots` for multi-element components
34
+ - [ ] Uses `compoundSlots` for variant combinations
35
+
36
+ ### 4. Component
37
+
38
+ - [ ] Has `'use client';` if using hooks or client-side rendering
39
+ - [ ] Uses `forwardRef` pattern when appropriate
40
+ - [ ] Destructures `className` and passes to styles
41
+ - [ ] Uses `useBreakpoint()` + `resolveResponsiveVariant()` for responsive props
42
+ - [ ] Uses `useFocusRing()` + `mergeProps()` from `react-aria` where appropriate
43
+ - [ ] All props are used (no unused props)
44
+ - [ ] `.js` extensions on all relative imports
45
+ - [ ] Plain function declarations (not `React.FC`)
46
+
47
+ ### 5. Accessibility
48
+
49
+ - [ ] Interactive elements use appropriate ARIA attributes
50
+ - [ ] Decorative icons use `aria-hidden`
51
+ - [ ] `react-aria` hooks used for focus and accessibility where appropriate
52
+ - [ ] Semantic HTML elements used
53
+ - [ ] `react-stately` hooks for state management where applicable
54
+
55
+ ### 6. Index
56
+
57
+ - [ ] Exports component and props type only
58
+ - [ ] Does NOT re-export styles
59
+ - [ ] `.js` extensions
60
+
61
+ ### 7. Tests
62
+
63
+ - [ ] At minimum a "renders the component" test
64
+ - [ ] Uses `userEvent.setup()` (not `fireEvent`) for interactions
65
+ - [ ] Imports from `.component.js` (not index)
66
+
67
+ ### 8. Stories
68
+
69
+ - [ ] Imports from `@storybook/react-vite`
70
+ - [ ] Has `tags: ['autodocs']` and standard decorator
71
+ - [ ] Covers: default state, looks/variants, sizes, responsive, disabled
72
+ - [ ] Interactive stories defined as function components
73
+
74
+ ## Severity Levels
75
+
76
+ ### Critical
77
+
78
+ - Missing `'use client'` on components with hooks
79
+ - Hardcoded colors instead of design tokens
80
+ - Missing `forwardRef` on components rendering native elements
81
+ - Custom focus styles instead of `focus-outline`
82
+ - Missing `.js` extensions in imports
83
+
84
+ ### Warnings
85
+
86
+ - Missing JSDoc `@default` tags
87
+ - No responsive variant support where beneficial
88
+ - Minimal test coverage
89
+ - Missing `aria-*` attributes on interactive elements
90
+
91
+ ### Style
92
+
93
+ - Using `React.FC` instead of function declarations
94
+ - Inconsistent prop destructuring order
95
+ - Styles not using `slots` for multi-element components
96
+
97
+ ## How to Run
98
+
99
+ 1. Read all files in the component directory
100
+ 2. Check each item above
101
+ 3. Report findings grouped by severity
102
+ 4. Suggest specific fixes with code examples
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: writing-gel-tests
3
+ description: 'Writes Vitest + React Testing Library tests for GEL design system components. Use when writing tests, adding tests, or improving test coverage for components in packages/ui.'
4
+ ---
5
+
6
+ # Writing GEL Component Tests
7
+
8
+ Guides writing tests for components in `packages/ui/src/components/`. Test conventions are also summarised in `packages/ui/.agents/AGENTS.md`.
9
+
10
+ ## Test Environment
11
+
12
+ - **Runner**: Vitest with `jsdom` environment
13
+ - **Rendering**: `@testing-library/react` (`render`, `screen`, `waitFor`)
14
+ - **User Events**: `@testing-library/user-event` (`userEvent.setup()`)
15
+ - **Mocks**: `vi` from `vitest`
16
+ - **Matchers**: `@testing-library/jest-dom` (loaded via `vitest.setup.ts`)
17
+ - **Excluded from tests**: `*.styles.ts` files (excluded in vitest config)
18
+
19
+ ### Pre-mocked Globals
20
+
21
+ Already mocked in `vitest.setup.ts` — do NOT re-mock:
22
+
23
+ - `window.scrollTo`
24
+ - `window.URL.createObjectURL` / `revokeObjectURL`
25
+ - `window.matchMedia`
26
+ - `ResizeObserver`
27
+
28
+ ## Test File Structure
29
+
30
+ ```tsx
31
+ import { render, screen, waitFor } from '@testing-library/react';
32
+ import userEvent from '@testing-library/user-event';
33
+ import { vi } from 'vitest';
34
+
35
+ import { ComponentName } from './component-name.component.js';
36
+
37
+ describe('ComponentName', () => {
38
+ const user = userEvent.setup();
39
+
40
+ it('renders the component', () => {
41
+ const { container } = render(<ComponentName />);
42
+ expect(container).toBeInTheDocument();
43
+ });
44
+ });
45
+ ```
46
+
47
+ Import from `./component-name.component.js` (NOT from `index`), sub-components from `./components/index.js`, icons from `../icon/index.js`. Always use `.js` extensions.
48
+
49
+ ## Test Categories
50
+
51
+ ### 1. Render Tests (Required)
52
+
53
+ ```tsx
54
+ it('renders the component', () => {
55
+ const { container } = render(<ComponentName />);
56
+ expect(container).toBeInTheDocument();
57
+ });
58
+ ```
59
+
60
+ ### 2. Variant Rendering
61
+
62
+ ```tsx
63
+ it('renders as an anchor tag', () => {
64
+ render(
65
+ <Button tag="a" href="#">
66
+ Link
67
+ </Button>,
68
+ );
69
+ expect(screen.getByRole('link', { name: 'Link' })).toBeInTheDocument();
70
+ });
71
+ ```
72
+
73
+ ### 3. User Interactions
74
+
75
+ Always use `userEvent.setup()` (NOT `fireEvent`):
76
+
77
+ ```tsx
78
+ it('calls onClick when clicked', async () => {
79
+ const handleClick = vi.fn();
80
+ render(<Button onClick={handleClick}>Click me</Button>);
81
+
82
+ act(() => {
83
+ user.click(screen.getByRole('button', { name: 'Click me' }));
84
+ });
85
+
86
+ await waitFor(() => {
87
+ expect(handleClick).toHaveBeenCalledTimes(1);
88
+ });
89
+ });
90
+ ```
91
+
92
+ ### 4. Visibility / State
93
+
94
+ ```tsx
95
+ it('shows content when expanded', async () => {
96
+ const { getByText } = render(
97
+ <Accordion>
98
+ <AccordionItem key="item1" id="item1" title="Title">
99
+ Hidden content
100
+ </AccordionItem>
101
+ </Accordion>,
102
+ );
103
+
104
+ user.click(getByText('Title'));
105
+
106
+ await waitFor(() => {
107
+ expect(getByText('Hidden content')).toBeVisible();
108
+ });
109
+ });
110
+ ```
111
+
112
+ ### 5. Icon Rendering
113
+
114
+ ```tsx
115
+ it('renders an icon when passed', () => {
116
+ render(<Button iconBefore={ArrowRightIcon} />);
117
+ expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
118
+ });
119
+ ```
120
+
121
+ ### 6. Utility Functions
122
+
123
+ ```tsx
124
+ describe('ComponentName utils', () => {
125
+ it('maps correct values', () => {
126
+ expect(utilFunction('input')).toBe('expected');
127
+ });
128
+
129
+ it('handles responsive values', () => {
130
+ expect(utilFunction({ initial: 'small', md: 'large' })).toStrictEqual({ initial: 'xsmall', md: 'small' });
131
+ });
132
+ });
133
+ ```
134
+
135
+ ## Querying Elements
136
+
137
+ Prefer accessible queries:
138
+
139
+ 1. `screen.getByRole('button', { name: 'Text' })` — interactive elements
140
+ 2. `screen.getByText('Text')` — content assertions
141
+ 3. `screen.getByLabelText('Label')` — form elements
142
+ 4. `container.querySelector()` — last resort only
143
+
144
+ ## Coverage Targets
145
+
146
+ ```js
147
+ branches: 80,
148
+ functions: 80,
149
+ lines: 80,
150
+ statements: 80,
151
+ ```
152
+
153
+ ## Running Tests
154
+
155
+ ```bash
156
+ pnpm vitest run src/components/{name} # Specific component
157
+ pnpm vitest run # All tests
158
+ pnpm vitest src/components/{name} # Watch mode
159
+ pnpm vitest run --coverage # With coverage
160
+ ```
161
+
162
+ ## What NOT to Test
163
+
164
+ - Style files (`*.styles.ts`) — excluded in vitest config
165
+ - Tailwind class names — don't assert on specific CSS classes
166
+ - Internal implementation details — test behavior, not implementation
167
+ - Storybook stories — tested separately via Storybook
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @westpac/ui
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2eebb35: - fix issue with font import in style config
8
+ - fix security issues
9
+
10
+ ## 1.1.0
11
+
12
+ ### Minor Changes
13
+
14
+ - bd3422f: add onPasteComplete handler to passcode
15
+
3
16
  ## 1.0.0
4
17
 
5
18
  ### 📦 Major Changes — @westpac/ui & @westpac/style-config