diff --git a/libs/core/src/components.d.ts b/libs/core/src/components.d.ts index 31cf8cb6c..08b2b8c65 100644 --- a/libs/core/src/components.d.ts +++ b/libs/core/src/components.d.ts @@ -48,6 +48,53 @@ export namespace Components { */ "variant": 'primary' | 'secondary' | 'accent' | 'disclosure' | 'destructive'; } + interface SageCheckbox { + /** + * Whether or not the checkbox is checked. + * @defaultValue false + */ + "checked": boolean; + /** + * Whether or not the checkbox is disabled. + * @defaultValue false + */ + "disabled": boolean; + /** + * Whether or not the checkbox is invalid. + * @defaultValue false + */ + "error": boolean; + /** + * String used for checkbox ID and label `for` attribute. + */ + "id": string; + /** + * Whether or not the checkbox is indeterminate. + * @defaultValue false + */ + "indeterminate": boolean; + /** + * String used for label next to checkbox + */ + "label": string; + /** + * String used for message below checkbox + */ + "message": string; + /** + * String used for checkbox `name` attribute. + */ + "name": string; + /** + * Whether or not the checkbox is required. + * @defaultValue false + */ + "required": boolean; + /** + * The value of the checkbox that is submitted with a form. + */ + "value": string; + } interface SageImage { /** * The image's alt tag. If none is provided, it will default to an empty string. @@ -188,6 +235,10 @@ export namespace Components { "variant": 'primary' | 'availability' | 'filter'; } } +export interface SageCheckboxCustomEvent extends CustomEvent { + detail: T; + target: HTMLSageCheckboxElement; +} export interface SageInputCustomEvent extends CustomEvent { detail: T; target: HTMLSageInputElement; @@ -209,6 +260,12 @@ declare global { prototype: HTMLSageButtonElement; new (): HTMLSageButtonElement; }; + interface HTMLSageCheckboxElement extends Components.SageCheckbox, HTMLStencilElement { + } + var HTMLSageCheckboxElement: { + prototype: HTMLSageCheckboxElement; + new (): HTMLSageCheckboxElement; + }; interface HTMLSageImageElement extends Components.SageImage, HTMLStencilElement { } var HTMLSageImageElement: { @@ -248,6 +305,7 @@ declare global { interface HTMLElementTagNameMap { "my-component": HTMLMyComponentElement; "sage-button": HTMLSageButtonElement; + "sage-checkbox": HTMLSageCheckboxElement; "sage-image": HTMLSageImageElement; "sage-input": HTMLSageInputElement; "sage-link": HTMLSageLinkElement; @@ -299,6 +357,54 @@ declare namespace LocalJSX { */ "variant"?: 'primary' | 'secondary' | 'accent' | 'disclosure' | 'destructive'; } + interface SageCheckbox { + /** + * Whether or not the checkbox is checked. + * @defaultValue false + */ + "checked"?: boolean; + /** + * Whether or not the checkbox is disabled. + * @defaultValue false + */ + "disabled"?: boolean; + /** + * Whether or not the checkbox is invalid. + * @defaultValue false + */ + "error"?: boolean; + /** + * String used for checkbox ID and label `for` attribute. + */ + "id"?: string; + /** + * Whether or not the checkbox is indeterminate. + * @defaultValue false + */ + "indeterminate"?: boolean; + /** + * String used for label next to checkbox + */ + "label"?: string; + /** + * String used for message below checkbox + */ + "message"?: string; + /** + * String used for checkbox `name` attribute. + */ + "name"?: string; + "onCheckedChanged"?: (event: SageCheckboxCustomEvent) => void; + /** + * Whether or not the checkbox is required. + * @defaultValue false + */ + "required"?: boolean; + /** + * The value of the checkbox that is submitted with a form. + */ + "value"?: string; + } interface SageImage { /** * The image's alt tag. If none is provided, it will default to an empty string. @@ -446,6 +552,7 @@ declare namespace LocalJSX { interface IntrinsicElements { "my-component": MyComponent; "sage-button": SageButton; + "sage-checkbox": SageCheckbox; "sage-image": SageImage; "sage-input": SageInput; "sage-link": SageLink; @@ -460,6 +567,7 @@ declare module "@stencil/core" { interface IntrinsicElements { "my-component": LocalJSX.MyComponent & JSXBase.HTMLAttributes; "sage-button": LocalJSX.SageButton & JSXBase.HTMLAttributes; + "sage-checkbox": LocalJSX.SageCheckbox & JSXBase.HTMLAttributes; "sage-image": LocalJSX.SageImage & JSXBase.HTMLAttributes; "sage-input": LocalJSX.SageInput & JSXBase.HTMLAttributes; "sage-link": LocalJSX.SageLink & JSXBase.HTMLAttributes; diff --git a/libs/core/src/components/sage-checkbox/readme.md b/libs/core/src/components/sage-checkbox/readme.md new file mode 100644 index 000000000..010d02aaf --- /dev/null +++ b/libs/core/src/components/sage-checkbox/readme.md @@ -0,0 +1,33 @@ +# sage-checkbox + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------------- | --------------- | -------------------------------------------------------- | --------- | ----------- | +| `checked` | `checked` | Whether or not the checkbox is checked. | `boolean` | `undefined` | +| `disabled` | `disabled` | Whether or not the checkbox is disabled. | `boolean` | `undefined` | +| `error` | `error` | Whether or not the checkbox is invalid. | `boolean` | `undefined` | +| `id` | `id` | String used for checkbox ID and label `for` attribute. | `string` | `undefined` | +| `indeterminate` | `indeterminate` | Whether or not the checkbox is indeterminate. | `boolean` | `undefined` | +| `label` | `label` | String used for label next to checkbox | `string` | `undefined` | +| `message` | `message` | String used for message below checkbox | `string` | `undefined` | +| `name` | `name` | String used for checkbox `name` attribute. | `string` | `undefined` | +| `required` | `required` | Whether or not the checkbox is required. | `boolean` | `undefined` | +| `value` | `value` | The value of the checkbox that is submitted with a form. | `string` | `undefined` | + + +## Events + +| Event | Description | Type | +| ---------------- | ----------- | ---------------------- | +| `checkedChanged` | | `CustomEvent` | + + +---------------------------------------------- + + diff --git a/libs/core/src/components/sage-checkbox/sage-checkbox.tsx b/libs/core/src/components/sage-checkbox/sage-checkbox.tsx new file mode 100644 index 000000000..06c6a1796 --- /dev/null +++ b/libs/core/src/components/sage-checkbox/sage-checkbox.tsx @@ -0,0 +1,121 @@ +import { Component, h, Prop, State, Event, EventEmitter, Host } from '@stencil/core'; + +@Component({ + tag: 'sage-checkbox', + styleUrl: 'sage-checkbox.scss', + shadow: true, +}) +export class SageCheckbox { + /** + * Whether or not the checkbox is checked. + * @defaultValue false + */ + @Prop() checked: boolean; + + /** + * Whether or not the checkbox is disabled. + * @defaultValue false + */ + @Prop() disabled: boolean; + + /** + * Whether or not the checkbox is invalid. + * @defaultValue false + */ + @Prop() error: boolean; + + /** + * String used for checkbox ID and label `for` attribute. + */ + @Prop() id: string; + + /** + * String used for label next to checkbox + */ + @Prop() label: string; + + /** + * String used for message below checkbox + */ + @Prop() message: string; + + /** + * String used for checkbox `name` attribute. + */ + @Prop() name: string; + + /** + * Whether or not the checkbox is indeterminate. + * @defaultValue false + */ + @Prop() indeterminate: boolean; + + /** + * Whether or not the checkbox is required. + * @defaultValue false + */ + @Prop() required: boolean; + + /** + * The value of the checkbox that is submitted with a form. + */ + @Prop() value: string; + + @State() checkboxState: 'checked' | 'indeterminate' | 'unchecked' = 'unchecked'; + + @Event() checkedChanged: EventEmitter; + + private handleCheckboxChange(event: Event) { + if (this.disabled) { + return; + } + + const target = event.target as HTMLInputElement; + const isChecked = target.checked; + + this.checkedChanged.emit(isChecked); + } + + private classNames() { + let className = `sage-checkbox`; + + if (this.error) { + const errorClassName = 'sage-checkbox--error'; + className += ' ' + errorClassName; + } + + if (this.indeterminate) { + const indeterminateClassName = 'sage-checkbox--indeterminate'; + className += ' ' + indeterminateClassName; + } + + return className; + } + + render() { + let message; + + if (this.message) { + message =
{this.message}
; + } + + return ( + +
+ this.handleCheckboxChange(event)} + required={this.required} + disabled={this.disabled} + /> + + {message} +
+
+ ); + } +} diff --git a/libs/react/src/components/proxies.ts b/libs/react/src/components/proxies.ts index db31e1b76..0da199916 100644 --- a/libs/react/src/components/proxies.ts +++ b/libs/react/src/components/proxies.ts @@ -10,6 +10,7 @@ import { applyPolyfills, defineCustomElements } from '@sage/core/loader'; applyPolyfills().then(() => defineCustomElements()); export const MyComponent = /*@__PURE__*/createReactComponent('my-component'); export const SageButton = /*@__PURE__*/createReactComponent('sage-button'); +export const SageCheckbox = /*@__PURE__*/createReactComponent('sage-checkbox'); export const SageIcon = /*@__PURE__*/createReactComponent('sage-icon'); export const SageImage = /*@__PURE__*/createReactComponent('sage-image'); export const SageInput = /*@__PURE__*/createReactComponent('sage-input');