@synerise/ds-field-set 1.2.19 → 1.2.20

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/CLAUDE.md +101 -0
  3. package/package.json +7 -6
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.2.20](https://github.com/Synerise/synerise-design/compare/@synerise/ds-field-set@1.2.19...@synerise/ds-field-set@1.2.20) (2026-07-23)
7
+
8
+ **Note:** Version bump only for package @synerise/ds-field-set
9
+
6
10
  ## [1.2.19](https://github.com/Synerise/synerise-design/compare/@synerise/ds-field-set@1.2.18...@synerise/ds-field-set@1.2.19) (2026-07-16)
7
11
 
8
12
  **Note:** Version bump only for package @synerise/ds-field-set
package/CLAUDE.md ADDED
@@ -0,0 +1,101 @@
1
+ # FieldSet (`@synerise/ds-field-set`)
2
+
3
+ > A labelled section wrapper with an optional header (title + description + prefix/trigger), divider, and a collapsible content area that animates open/closed.
4
+
5
+ ## Package structure
6
+
7
+ ```
8
+ src/
9
+ FieldSet.tsx — main component
10
+ FieldSet.types.ts — FieldSetProps, TriggerType
11
+ FieldSet.styles.ts — all styled-components
12
+ index.ts — public exports (default only)
13
+ FieldSet.spec.tsx — Vitest tests
14
+ ```
15
+
16
+ ## Public exports
17
+
18
+ ### `FieldSet` (default export)
19
+
20
+ `FieldSetProps = WithHTMLAttributes<HTMLDivElement, { … }>`
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `title` | `ReactNode` | — | Header title text/node |
25
+ | `description` | `ReactNode` | — | Subtitle rendered below `title`; when both are set the header aligns to `flex-start` (top) |
26
+ | `component` | `ReactNode` | — | Main content rendered inside the collapsible area |
27
+ | `button` | `ReactNode` | — | Action node rendered at the bottom of the collapsible area (padded `8px`) |
28
+ | `prefix` | `ReactNode` | — | Custom prefix shown in the header; **ignored** when `expandable` is `true` (replaced by expander/switch) |
29
+ | `divider` | `boolean` | `true` | Renders a full-width `Divider` between the header and content |
30
+ | `expandable` | `boolean` | — | Enables expand/collapse of `component` and `button`; replaces `prefix` with the trigger |
31
+ | `triggerType` | `'expander' \| 'switch'` | `'expander'` | Which trigger to show when `expandable` is `true` |
32
+ | `defaultExpanded` | `boolean` | — | Initial expanded state; also syncs if the prop changes externally |
33
+ | `onExpandChange` | `(expanded: boolean) => void` | — | Callback fired after expand/collapse toggle |
34
+ | `onTitleClick` | `(ev: MouseEvent<HTMLElement>) => void` | — | Click handler for the title; also triggers expand when `expandable` is `true` |
35
+ | `className` | `string` | — | Appended to the root element alongside `ds-field-set` |
36
+
37
+ No `forwardRef`.
38
+
39
+ > **Note:** `FieldSetProps` and `TriggerType` are **not exported** from `index.ts`. To use the type, import directly from the internal path or derive it: `React.ComponentProps<typeof FieldSet>`.
40
+
41
+ ## Usage patterns
42
+
43
+ ```tsx
44
+ import FieldSet from '@synerise/ds-field-set';
45
+
46
+ // Static section with divider
47
+ <FieldSet title="Advanced option" description="For advanced users only" />
48
+
49
+ // Collapsible with expander trigger (default)
50
+ <FieldSet
51
+ title="Advanced option"
52
+ expandable
53
+ defaultExpanded
54
+ component={<MyFormFields />}
55
+ onExpandChange={(isExpanded) => console.log(isExpanded)}
56
+ />
57
+
58
+ // Collapsible with switch trigger
59
+ <FieldSet
60
+ title="Enable feature"
61
+ expandable
62
+ triggerType="switch"
63
+ component={<FeatureOptions />}
64
+ />
65
+
66
+ // Static with custom prefix and action button
67
+ <FieldSet
68
+ title="Section"
69
+ prefix={<MyIcon />}
70
+ component={<Content />}
71
+ button={<Button>Add item</Button>}
72
+ divider={false}
73
+ />
74
+ ```
75
+
76
+ ## Styling
77
+
78
+ All styles are in `FieldSet.styles.ts`. Notable patterns:
79
+
80
+ - `ContainerWrapper`: `flex-column; gap: 16px` — overall layout
81
+ - `CollapsibleContent`: when `expandable`, uses `max-height` CSS transition (`0.7s ease-in-out`) between `0` and the measured natural height. Transition only fires when `shouldAnimate` is `true` (set on click, cleared on `transitionend`) to avoid animating on initial render.
82
+ - `Title`: `font-size: 16px; font-weight: 500; grey-800`; `cursor: pointer` when `isClickable`
83
+ - `Description`: `font-size: 13px`
84
+ - No theme variant pattern — sizing and colours are hardcoded or use `theme.palette` tokens directly.
85
+
86
+ ## Key dependencies
87
+
88
+ - `@synerise/ds-button` — `Expander` (expander trigger)
89
+ - `@synerise/ds-switch` — `RawSwitch` (switch trigger)
90
+ - `@synerise/ds-divider` — `Divider` used for the section divider
91
+ - `@synerise/ds-utils` — `useResizeObserver` (measures collapsible content height), `WithHTMLAttributes`
92
+
93
+ ## Implementation notes
94
+
95
+ - **Expand animation** — `useResizeObserver` watches the inner `CollapsibleContentInner` div and updates `maxHeight` state with its current pixel height. `CollapsibleContent` then sets `max-height` CSS property to that value when expanded (or `0` when collapsed). If `maxHeight` hasn't been measured yet, it falls back to `9999px`.
96
+ - **`defaultExpanded` sync** — a `useEffect` re-syncs local `expanded` state whenever the `defaultExpanded` prop changes. This is intentional: the prop acts as a controlled default that can be updated externally.
97
+ - **`prefix` is replaced when `expandable`** — passing both `prefix` and `expandable` will silently discard `prefix`.
98
+ - **CSS class** — root element always has `ds-field-set` plus any `className` passed via props.
99
+ - **Collapsible visibility** — `aria-hidden` is set to `"true"` when collapsed and `"false"` when expanded; `data-testid="field-set-collapsible"` is on the `CollapsibleContent` div.
100
+ - **Uses Vitest** for testing.
101
+ - **Storybook deep-imports** `ExpanderWrapper` from `@synerise/ds-field-set/dist/FieldSet.styles` — this is a fragile internal import and should not be replicated in consumer code.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-field-set",
3
- "version": "1.2.19",
3
+ "version": "1.2.20",
4
4
  "description": "FieldSet UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -17,6 +17,7 @@
17
17
  "files": [
18
18
  "/dist",
19
19
  "CHANGELOG.md",
20
+ "CLAUDE.md",
20
21
  "README.md",
21
22
  "package.json",
22
23
  "LICENSE.md"
@@ -41,10 +42,10 @@
41
42
  ],
42
43
  "types": "dist/index.d.ts",
43
44
  "dependencies": {
44
- "@synerise/ds-button": "^1.5.34",
45
- "@synerise/ds-divider": "^1.3.15",
46
- "@synerise/ds-switch": "^1.2.33",
47
- "@synerise/ds-utils": "^1.10.1"
45
+ "@synerise/ds-button": "^1.5.35",
46
+ "@synerise/ds-divider": "^1.3.16",
47
+ "@synerise/ds-switch": "^1.2.34",
48
+ "@synerise/ds-utils": "^1.10.2"
48
49
  },
49
50
  "peerDependencies": {
50
51
  "@synerise/ds-core": "*",
@@ -53,5 +54,5 @@
53
54
  "styled-components": "^5.3.3",
54
55
  "vitest": "4"
55
56
  },
56
- "gitHead": "a81ab6519d49a3dea9c0cfebcdc9104cbb4f4226"
57
+ "gitHead": "d0a43cc43d8528a36f105aceea52ab470edb71d9"
57
58
  }