Skip to content

Commit c4d3de8

Browse files
authored
Merge pull request #1696 from p3ol/feature/checkbox-indeterminate
✨ feat(react): add checkbox indeterminate state
2 parents 8cda460 + 176a222 commit c4d3de8

20 files changed

Lines changed: 164 additions & 704 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
name: Unit tests
3131
runs-on: ubuntu-24.04
3232
timeout-minutes: 10
33+
env:
34+
YARN_ENABLE_HARDENED_MODE: 0
3335
strategy:
3436
matrix:
3537
node-version: [20, 22, 24]
@@ -44,6 +46,8 @@ jobs:
4446
cache: yarn
4547
- name: Install deps
4648
run: yarn install
49+
- name: Build needed packages
50+
run: yarn p:core build && yarn p:tailwind build
4751
- name: Test
4852
run: yarn test
4953
- name: Codecov upload

.yarnrc.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
approvedGitRepositories:
2-
- "**"
3-
4-
enableGlobalCache: true
5-
6-
enableScripts: true
7-
8-
nmHoistingLimits: workspaces
9-
101
nodeLinker: node-modules
112

12-
npmMinimalAgeGate: 0
13-
143
yarnPath: .yarn/releases/yarn-4.15.0.cjs

packages/core/tsconfig.build.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"noEmit": false,
77
"emitDeclarationOnly": true,
88
"outDir": "dist/types",
9-
"rootDir": "./lib"
9+
"rootDir": "./lib",
10+
"paths": {},
1011
},
1112
"exclude": [
1213
"tests",

packages/hooks/tsconfig.build.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"noEmit": false,
77
"emitDeclarationOnly": true,
88
"outDir": "dist/types",
9-
"rootDir": "./lib"
9+
"rootDir": "./lib",
10+
"paths": {},
1011
},
1112
"exclude": [
1213
"tests",

packages/react-d3-plugin/tsconfig.build.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"noEmit": false,
77
"emitDeclarationOnly": true,
88
"outDir": "dist/types",
9-
"rootDir": "./lib"
9+
"rootDir": "./lib",
10+
"paths": {},
1011
},
1112
"exclude": [
1213
"tests",

packages/react/lib/CheckboxField/index.stories.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Abstract from '../Abstract';
66
import FieldControl from '../FieldControl';
77
import Label from '../Label';
88

9-
export default { title: 'react/Checkbox' };
9+
export default { title: 'react/CheckboxField' };
1010

1111
export const Basic = () => (
1212
<CheckboxField onChange={action('change')}>
@@ -98,3 +98,12 @@ export const Controlled = () => {
9898
</>
9999
);
100100
};
101+
102+
export const Indeterminate = () => (
103+
<CheckboxField
104+
checked="indeterminate"
105+
onChange={action('change')}
106+
>
107+
Check this
108+
</CheckboxField>
109+
);

packages/react/lib/CheckboxField/index.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,18 @@ describe('<CheckboxField />', () => {
203203

204204
unmount();
205205
});
206+
207+
it('should allow to use indeterminate state', async () => {
208+
const user = userEvent.setup();
209+
const { unmount, container } = render(
210+
<CheckboxField checked="indeterminate" />
211+
);
212+
213+
expect(container).toMatchSnapshot('indeterminate');
214+
215+
await user.click(container.querySelector('label'));
216+
expect(container).toMatchSnapshot('checked');
217+
218+
unmount();
219+
});
206220
});

packages/react/lib/CheckboxField/index.test.tsx.snap

Lines changed: 70 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,7 @@ exports[`<CheckboxField /> > should add value if provided 1`] = `
1717
/>
1818
<div
1919
class="inner"
20-
>
21-
<svg
22-
class="junipero icon check"
23-
height="7"
24-
viewBox="0 0 10 7"
25-
width="10"
26-
>
27-
<path
28-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
29-
/>
30-
</svg>
31-
</div>
20+
/>
3221
<div
3322
class="content"
3423
/>
@@ -97,18 +86,7 @@ exports[`<CheckboxField /> > should allow to render a controller checkbox > unch
9786
/>
9887
<div
9988
class="inner"
100-
>
101-
<svg
102-
class="junipero icon check"
103-
height="7"
104-
viewBox="0 0 10 7"
105-
width="10"
106-
>
107-
<path
108-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
109-
/>
110-
</svg>
111-
</div>
89+
/>
11290
<div
11391
class="content"
11492
>
@@ -118,15 +96,15 @@ exports[`<CheckboxField /> > should allow to render a controller checkbox > unch
11896
</div>
11997
`;
12098

121-
exports[`<CheckboxField /> > should not trigger event and change state if user click but checkbox is disabled 1`] = `
99+
exports[`<CheckboxField /> > should allow to use indeterminate state > checked 1`] = `
122100
<div>
123101
<label
124-
aria-checked="false"
125-
aria-disabled="true"
102+
aria-checked="true"
103+
aria-disabled="false"
126104
aria-required="false"
127-
class="junipero checkbox-field pristine valid disabled"
105+
class="junipero checkbox-field dirty valid checked"
128106
role="checkbox"
129-
tabindex="-1"
107+
tabindex="0"
130108
>
131109
<input
132110
tabindex="-1"
@@ -154,13 +132,13 @@ exports[`<CheckboxField /> > should not trigger event and change state if user c
154132
</div>
155133
`;
156134

157-
exports[`<CheckboxField /> > should render 1`] = `
135+
exports[`<CheckboxField /> > should allow to use indeterminate state > indeterminate 1`] = `
158136
<div>
159137
<label
160138
aria-checked="false"
161139
aria-disabled="false"
162140
aria-required="false"
163-
class="junipero checkbox-field pristine valid"
141+
class="junipero checkbox-field pristine valid indeterminate"
164142
role="checkbox"
165143
tabindex="0"
166144
>
@@ -173,13 +151,13 @@ exports[`<CheckboxField /> > should render 1`] = `
173151
class="inner"
174152
>
175153
<svg
176-
class="junipero icon check"
177-
height="7"
178-
viewBox="0 0 10 7"
154+
class="junipero icon minus"
155+
height="10"
156+
viewBox="0 0 9 10"
179157
width="10"
180158
>
181159
<path
182-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
160+
d="M1 5L8 5"
183161
/>
184162
</svg>
185163
</div>
@@ -190,6 +168,56 @@ exports[`<CheckboxField /> > should render 1`] = `
190168
</div>
191169
`;
192170

171+
exports[`<CheckboxField /> > should not trigger event and change state if user click but checkbox is disabled 1`] = `
172+
<div>
173+
<label
174+
aria-checked="false"
175+
aria-disabled="true"
176+
aria-required="false"
177+
class="junipero checkbox-field pristine valid disabled"
178+
role="checkbox"
179+
tabindex="-1"
180+
>
181+
<input
182+
tabindex="-1"
183+
type="checkbox"
184+
value=""
185+
/>
186+
<div
187+
class="inner"
188+
/>
189+
<div
190+
class="content"
191+
/>
192+
</label>
193+
</div>
194+
`;
195+
196+
exports[`<CheckboxField /> > should render 1`] = `
197+
<div>
198+
<label
199+
aria-checked="false"
200+
aria-disabled="false"
201+
aria-required="false"
202+
class="junipero checkbox-field pristine valid"
203+
role="checkbox"
204+
tabindex="0"
205+
>
206+
<input
207+
tabindex="-1"
208+
type="checkbox"
209+
value=""
210+
/>
211+
<div
212+
class="inner"
213+
/>
214+
<div
215+
class="content"
216+
/>
217+
</label>
218+
</div>
219+
`;
220+
193221
exports[`<CheckboxField /> > should set checked if provided 1`] = `
194222
<div>
195223
<label
@@ -243,18 +271,7 @@ exports[`<CheckboxField /> > should set focused state on focus > focused 1`] = `
243271
/>
244272
<div
245273
class="inner"
246-
>
247-
<svg
248-
class="junipero icon check"
249-
height="7"
250-
viewBox="0 0 10 7"
251-
width="10"
252-
>
253-
<path
254-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
255-
/>
256-
</svg>
257-
</div>
274+
/>
258275
<div
259276
class="content"
260277
/>
@@ -279,18 +296,7 @@ exports[`<CheckboxField /> > should set focused state on focus > not focused 1`]
279296
/>
280297
<div
281298
class="inner"
282-
>
283-
<svg
284-
class="junipero icon check"
285-
height="7"
286-
viewBox="0 0 10 7"
287-
width="10"
288-
>
289-
<path
290-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
291-
/>
292-
</svg>
293-
</div>
299+
/>
294300
<div
295301
class="content"
296302
/>
@@ -351,18 +357,7 @@ exports[`<CheckboxField /> > should set invalid state following custom onValidat
351357
/>
352358
<div
353359
class="inner"
354-
>
355-
<svg
356-
class="junipero icon check"
357-
height="7"
358-
viewBox="0 0 10 7"
359-
width="10"
360-
>
361-
<path
362-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
363-
/>
364-
</svg>
365-
</div>
360+
/>
366361
<div
367362
class="content"
368363
/>
@@ -387,18 +382,7 @@ exports[`<CheckboxField /> > should set invalid state if checkbox is invalid and
387382
/>
388383
<div
389384
class="inner"
390-
>
391-
<svg
392-
class="junipero icon check"
393-
height="7"
394-
viewBox="0 0 10 7"
395-
width="10"
396-
>
397-
<path
398-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
399-
/>
400-
</svg>
401-
</div>
385+
/>
402386
<div
403387
class="content"
404388
/>
@@ -459,18 +443,7 @@ exports[`<CheckboxField /> > should toggle active state on click > active 1`] =
459443
/>
460444
<div
461445
class="inner"
462-
>
463-
<svg
464-
class="junipero icon check"
465-
height="7"
466-
viewBox="0 0 10 7"
467-
width="10"
468-
>
469-
<path
470-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
471-
/>
472-
</svg>
473-
</div>
446+
/>
474447
<div
475448
class="content"
476449
/>
@@ -495,18 +468,7 @@ exports[`<CheckboxField /> > should toggle active state on click > inactive 1`]
495468
/>
496469
<div
497470
class="inner"
498-
>
499-
<svg
500-
class="junipero icon check"
501-
height="7"
502-
viewBox="0 0 10 7"
503-
width="10"
504-
>
505-
<path
506-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
507-
/>
508-
</svg>
509-
</div>
471+
/>
510472
<div
511473
class="content"
512474
/>
@@ -567,18 +529,7 @@ exports[`<CheckboxField /> > should toggle check if checkbox is clicked > unchec
567529
/>
568530
<div
569531
class="inner"
570-
>
571-
<svg
572-
class="junipero icon check"
573-
height="7"
574-
viewBox="0 0 10 7"
575-
width="10"
576-
>
577-
<path
578-
d="M1.75259 3.49582L4.25675 6L8.24741 1"
579-
/>
580-
</svg>
581-
</div>
532+
/>
582533
<div
583534
class="content"
584535
/>

0 commit comments

Comments
 (0)