Skip to content

Commit

Permalink
feat: ✨ sd-checkbox & sd-checkbox-group (#507)
Browse files Browse the repository at this point in the history
Co-authored-by: Hargesheimer, Daniel <[email protected]>
  • Loading branch information
DanielHargesheimer authored Nov 10, 2023
1 parent d5d951f commit ea9bda2
Show file tree
Hide file tree
Showing 9 changed files with 763 additions and 184 deletions.
26 changes: 0 additions & 26 deletions packages/components/src/_components/checkbox/checkbox.stories.ts

This file was deleted.

118 changes: 0 additions & 118 deletions packages/components/src/_components/checkbox/checkbox.styles.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import '../../solid-components';
import { html } from 'lit-html';
import { storybookDefaults, storybookHelpers, storybookTemplate } from '../../../scripts/storybook/helper';
import { userEvent } from '@storybook/testing-library';
import { waitUntil } from '@open-wc/testing-helpers';

const { argTypes, parameters } = storybookDefaults('sd-checkbox-group');
const { generateTemplate } = storybookTemplate('sd-checkbox-group');
const { overrideArgs } = storybookHelpers('sd-checkbox-group');

export default {
title: 'Components/sd-checkbox-group',
component: 'sd-checkbox-group',
args: overrideArgs([
{ type: 'slot', name: 'label', value: `<label slot="label">Group Label</label>` },
{
type: 'slot',
name: 'default',
value: `<sd-checkbox name="checkbox" value="1">Checkbox 1</sd-checkbox><sd-checkbox name="checkbox" value="2">Checkbox 2</sd-checkbox><sd-checkbox name="checkbox" value="3">Checkbox 3</sd-checkbox>`
}
]),
argTypes,
parameters: {
...parameters,
design: {
type: 'figma',
url: 'https://www.figma.com/file/Q7E9GTBET7Gs2HyH1kbpu5/Checkbox-%2F-Checkbox-Group?type=design&node-id=0-1&mode=design&t=DV2yJRUqqYBrskyb-0'
}
}
};

/**
* Default: This shows sd-checkbox-group in its default state.
*/

export const Default = {
render: (args: any) => {
return generateTemplate({ args });
}
};

/**
* The sd-checkbox in all possible combinations of `orientation` and `size`.
*/

export const Orientation = {
parameters: { controls: { exclude: ['orientation', 'size', 'default'] } },
render: (args: any) => {
return generateTemplate({
axis: {
x: { type: 'attribute', name: 'orientation' },
y: { type: 'attribute', name: 'size' }
},
args
});
}
};

/**
* Use the disabled attribute to disable an input checkbox. Clicks will be suppressed until the disabled state is removed
*/

export const Disabled = {
name: 'Disabled x Size',
parameters: { controls: { exclude: ['size', 'default'] } },
render: (args: any) => {
return generateTemplate({
axis: {
x: [
{
type: 'slot',
name: 'default',
title: 'disabled',
values: [
{
value:
'<sd-checkbox value="1" disabled>Option 1</sd-checkbox><sd-checkbox value="2">Option 2</sd-checkbox><sd-checkbox value="3">Option 3</sd-checkbox>',
title: 'true'
},
{
value:
'<sd-checkbox value="1">Option 1</sd-checkbox><sd-checkbox value="2">Option 2</sd-checkbox><sd-checkbox value="3">Option 3</sd-checkbox>',
title: 'false'
}
]
}
],
y: { type: 'attribute', name: 'size' }
},
args
});
}
};

/**
* Use the `form-control`, `form-control-label` and `form-control-input` part selectors to customize the checkbox-group.
*/
export const Parts = {
parameters: {
controls: { exclude: ['form-control', 'form-control-label', 'form-control-input'] }
},
render: (args: any) => {
return generateTemplate({
axis: {
y: {
type: 'template',
name: 'sd-checkbox-group::part(...){outline: solid 2px red}',
values: ['form-control', 'form-control-label', 'form-control-input'].map(part => {
return {
title: part,
value: `<style>#part-${part} sd-checkbox-group::part(${part}){outline: solid 2px red}</style><div id="part-${part}">%TEMPLATE%</div>`
};
})
}
},
constants: [{ type: 'template', name: 'width', value: '<div style="width: 300px">%TEMPLATE%</div>' }],
args
});
}
};

/**
* sd-checkbox-group is fully accessibile via keyboard.
*/
export const Mouseless = {
render: (args: any) => {
return html`<div class="mouseless">${generateTemplate({ args })}</div>`;
},

play: async ({ canvasElement }: { canvasElement: HTMLUnknownElement }) => {
const el = canvasElement.querySelector('.mouseless sd-checkbox-group');
await waitUntil(() => el?.shadowRoot?.querySelector('label'));

if (el?.shadowRoot) {
const label = el.shadowRoot.querySelector('label');
if (label) {
await userEvent.type(label, '{space}', { pointerEventsCheck: 0 });
}
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { expect, fixture, html, waitUntil } from '@open-wc/testing';
import sinon from 'sinon';

describe('when submitting a form', () => {
it('should submit the correct value when a value is provided', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sd-checkbox-group>
<sd-checkbox id="checkbox-1" name="a" value="1"></sd-checkbox>
<sd-checkbox id="checkbox-2" name="a" value="2"></sd-checkbox>
<sd-checkbox id="checkbox-3" name="a" value="3"></sd-checkbox>
</sd-checkbox-group>
<sd-button type="submit">Submit</sd-button>
</form>
`);
const button = form.querySelector('sd-button')!;
const checkbox = form.querySelectorAll('sd-checkbox')[1]!;
const checkbox2 = form.querySelectorAll('sd-checkbox')[2]!;
const submitHandler = sinon.spy((event: SubmitEvent) => {
formData = new FormData(form);

event.preventDefault();
});
let formData: FormData;

form.addEventListener('submit', submitHandler);
checkbox2.click();
checkbox.click();
button.click();
await waitUntil(() => submitHandler.calledOnce);
expect(formData!.getAll('a')).to.eql(['2', '3']);
});

it('should be present in form data when using the form attribute and located outside of a <form>', async () => {
const el = await fixture<HTMLFormElement>(html`
<div>
<form id="f">
<sd-button type="submit">Submit</sd-button>
</form>
<sd-checkbox-group>
<sd-checkbox id="checkbox-1" name="a" value="1" checked form="f"></sd-checkbox>
<sd-checkbox id="checkbox-2" name="a" value="2" form="f"></sd-checkbox>
<sd-checkbox id="checkbox-3" name="a" value="3" checked form="f"></sd-checkbox>
</sd-checkbox-group>
</div>
`);
const form = el.querySelector('form')!;
const formData = new FormData(form);

expect(formData.getAll('a')).to.eql(['1', '3']);
});
});
Loading

0 comments on commit ea9bda2

Please sign in to comment.