Skip to content

Commit

Permalink
feat: custom checkbox web component
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbert committed Oct 7, 2021
1 parent ce25e82 commit 5c3d795
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 1 deletion.
14 changes: 14 additions & 0 deletions components/custom-checkbox/stencil.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

@import "./bem";

:host {
display: block;
}

:host([hidden]) {
display: none !important;
}
145 changes: 145 additions & 0 deletions components/custom-checkbox/stencil.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<!--
@license EUPL-1.2
Copyright (c) 2021 Robbert Broersma
-->

import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
import "./bem.scss";

export const defaultArgs = {
checked: false,
disabled: false,
indeterminate: false,
invalid: false,
required: false,
value: "",
};

export const CustomCheckbox = ({
checked = false,
disabled = false,
indeterminate = false,
invalid = false,
required = false,
value = "",
}) =>
`<utrecht-custom-checkbox${checked ? ' checked="true"' : ""}${disabled ? ' disabled="true"' : ""}${
indeterminate ? ' indeterminate="true"' : ""
}${invalid ? ' invalid="true"' : ""}${required ? ' required="true"' : ""}${
value ? ` value="${value}"` : ""
}></utrecht-custom-checkbox>`;

<Meta
title="Web Component/Custom Checkbox"
argTypes={{
checked: {
description: "Checked",
control: "boolean",
},
disabled: {
description: "Disabled",
control: "boolean",
},
indeterminate: {
description: "Indeterminate",
control: "boolean",
},
invalid: {
description: "Invalid",
control: "boolean",
},
required: {
description: "Required",
control: "boolean",
},
value: {
description: "Set the value of the text box",
control: "text",
},
}}
decorators={[(story) => `<form method="POST" action="#">${story()}</form>`]}
parameters={{
docs: {
transformSource: (_src, { args }) => CustomCheckbox(args),
},
status: {
type: "WORK IN PROGRESS",
},
}}
/>

# Checkbox Component

<Canvas>
<Story
name="Custom Checkbox"
args={{
...defaultArgs,
}}
>
{CustomCheckbox.bind({})}
</Story>
</Canvas>

<ArgsTable story="Custom Checkbox" />

## States

### Disabled

<Canvas>
<Story
name="Disabled checkbox"
args={{
...defaultArgs,
disabled: true,
}}
>
{CustomCheckbox.bind({})}
</Story>
</Canvas>

### Checked

<Canvas>
<Story
name="Checked checkbox"
args={{
...defaultArgs,
checked: true,
}}
>
{CustomCheckbox.bind({})}
</Story>
</Canvas>

### Indeterminate

<Canvas>
<Story
name="Indeterminate checkbox"
args={{
...defaultArgs,
indeterminate: true,
}}
>
{CustomCheckbox.bind({})}
</Story>
</Canvas>

### Required and invalid

The native checkbox should have the same position and size as the custom checkbox, so the native error message tooltip aligns with the custom checkbox.

<Canvas>
<Story
name="Required checkbox"
args={{
...defaultArgs,
invalid: true,
required: true,
}}
>
{CustomCheckbox.bind({})}
</Story>
</Canvas>
87 changes: 87 additions & 0 deletions components/custom-checkbox/stencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

import { Component, Event, EventEmitter, h, Prop } from "@stencil/core";
import clsx from "clsx";

@Component({
tag: "utrecht-custom-checkbox",
styleUrl: "stencil.scss",
shadow: true,
})
export class CustomCheckbox {
@Prop({ reflect: true }) disabled: boolean = false;
@Prop({ reflect: true }) checked: boolean = false;
@Prop({ reflect: true }) indeterminate: boolean = false;
@Prop({ reflect: true }) invalid: boolean = false;
@Event() utrechtBlur: EventEmitter;
@Event() utrechtChange: EventEmitter;
@Event() utrechtFocus: EventEmitter;
@Event() utrechtInput: EventEmitter;

render() {
const { checked, disabled, indeterminate, invalid } = this;
const active = false;

const toggleInteraction = () => {
if (!this.disabled) {
this.checked = !this.checked;
this.utrechtInput.emit(this);
this.utrechtChange.emit(this);
}
};

const handleClick = () => {
toggleInteraction();
};

const handleKeyPress = (evt) => {
if (evt.code === "Space" || evt.key === " ") {
// Do not scroll the page using Space when the toggle is focussed
evt.preventDefault();
}
};

const handleKeyUp = (evt) => {
if (evt.code === "Space" || evt.key === " ") {
toggleInteraction();
}
};

return (
<div
class="utrecht-custom-checkbox"
role="checkbox"
tabIndex={disabled ? null : 0}
aria-checked={indeterminate ? "mixed" : checked}
aria-disabled={disabled}
aria-invalid={invalid}
onClick={handleClick}
onKeyPress={handleKeyPress}
onKeyUp={handleKeyUp}
>
<div
class={clsx(
"utrecht-custom-checkbox__box",
active && "utrecht-custom-checkbox__box--active",
checked && "utrecht-custom-checkbox__box--checked",
!checked && "utrecht-custom-checkbox__box--not-checked",
disabled && "utrecht-custom-checkbox__box--disabled",
focus && "utrecht-custom-checkbox__box--focus",
invalid && "utrecht-custom-checkbox__box--invalid",
indeterminate && "utrecht-custom-checkbox__box--indeterminate"
)}
>
<utrecht-icon-checkmark class="utrecht-custom-checkbox__icon utrecht-custom-checkbox__icon--checked">
</utrecht-icon-checkmark>
<utrecht-icon-indeterminate class="utrecht-custom-checkbox__icon utrecht-custom-checkbox__icon--indeterminate">
</utrecht-icon-indeterminate>
</div>
</div>
);
}
}
2 changes: 2 additions & 0 deletions packages/web-component-library-angular/src/index.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
UtrechtButton,
UtrechtCheckbox,
UtrechtContactCardTemplate,
UtrechtCustomCheckbox,
UtrechtDigidButton,
UtrechtDigidLogo,
UtrechtDocument,
Expand Down Expand Up @@ -67,6 +68,7 @@ const components = [
UtrechtButton,
UtrechtCheckbox,
UtrechtContactCardTemplate,
UtrechtCustomCheckbox,
UtrechtDigidButton,
UtrechtDigidLogo,
UtrechtDocument,
Expand Down
7 changes: 6 additions & 1 deletion packages/web-component-library-stencil/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ const valueAccessorConfigs: ValueAccessorConfig = [
type: 'number',
},
{
elementSelectors: ['utrecht-checkbox', 'utrecht-form-field-checkbox', 'utrecht-form-toggle'],
elementSelectors: [
'utrecht-checkbox',
'utrecht-custom-checkbox',
'utrecht-form-field-checkbox',
'utrecht-form-toggle',
],
event: 'utrechtInput',
targetAttr: 'checked',
type: 'boolean',
Expand Down

0 comments on commit 5c3d795

Please sign in to comment.