Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sbb-select): implement native form support #3101

Merged
merged 14 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/elements/checkbox/checkbox-panel/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,26 @@ The component provides the same accessibility features as the native checkbox.
Always provide an accessible label via `aria-label` for checkboxes without descriptive text content.
If you don't want the label to appear next to the checkbox, you can use `aria-label` to specify an appropriate label.

<!-- Override
@type value => string \| null
-->
<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| --------------- | --------------- | ------- | --------------------------------- | --------- | ----------------------------------------------------------- |
| `borderless` | `borderless` | public | `boolean` | `false` | Whether the unselected panel has a border. |
| `checked` | `checked` | public | `boolean` | `false` | Whether the checkbox is checked. |
| `color` | `color` | public | `'white' \| 'milk'` | `'white'` | The background color of the panel. |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `form` | - | public | `HTMLFormElement \| null` | | Returns the form owner of internals target element. |
| `group` | - | public | `SbbCheckboxGroupElement \| null` | `null` | Reference to the connected checkbox group. |
| `indeterminate` | `indeterminate` | public | `boolean` | `false` | Whether the checkbox is indeterminate. |
| `name` | `name` | public | `string` | | Name of the form element. Will be read from name attribute. |
| `required` | `required` | public | `boolean` | `false` | Whether the component is required. |
| `size` | `size` | public | `SbbPanelSize` | `'m'` | Size variant. |
| `value` | `value` | public | `string \| null` | `null` | Value of the form element. |
| Name | Attribute | Privacy | Type | Default | Description |
| --------------- | --------------- | ------- | --------------------------------- | --------- | -------------------------------------------------------------- |
| `borderless` | `borderless` | public | `boolean` | `false` | Whether the unselected panel has a border. |
| `checked` | `checked` | public | `boolean` | `false` | Whether the checkbox is checked. |
| `color` | `color` | public | `'white' \| 'milk'` | `'white'` | The background color of the panel. |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `form` | - | public | `HTMLFormElement \| null` | | Returns the form owner of the internals of the target element. |
| `group` | - | public | `SbbCheckboxGroupElement \| null` | `null` | Reference to the connected checkbox group. |
| `indeterminate` | `indeterminate` | public | `boolean` | `false` | Whether the checkbox is indeterminate. |
| `name` | `name` | public | `string` | | Name of the form element. Will be read from name attribute. |
| `required` | `required` | public | `boolean` | `false` | Whether the component is required. |
| `size` | `size` | public | `SbbPanelSize` | `'m'` | Size variant. |
| `value` | `value` | public | `string \| null` | `null` | Value of the form element. |

## Events

Expand Down
5 changes: 4 additions & 1 deletion src/elements/checkbox/checkbox/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ If you don't want the label to appear next to the checkbox, you can use `aria-la
<sbb-checkbox aria-label="Subscribed to email message"></sbb-checkbox>
```

<!-- Override
@type value => string \| null
-->
<!-- Auto Generated Below -->

## Properties
Expand All @@ -85,7 +88,7 @@ If you don't want the label to appear next to the checkbox, you can use `aria-la
| --------------- | ---------------- | ------- | --------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `checked` | `checked` | public | `boolean` | `false` | Whether the checkbox is checked. |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `form` | - | public | `HTMLFormElement \| null` | | Returns the form owner of internals target element. |
| `form` | - | public | `HTMLFormElement \| null` | | Returns the form owner of the internals of the target element. |
| `group` | - | public | `SbbCheckboxGroupElement \| null` | `null` | Reference to the connected checkbox group. |
| `iconName` | `icon-name` | public | `string \| undefined` | | The icon name we want to use, choose from the small icon variants from the ui-icons category from here https://icons.app.sbb.ch. |
| `iconPlacement` | `icon-placement` | public | `SbbIconPlacement` | `'end'` | The label position relative to the labelIcon. Defaults to end |
Expand Down
35 changes: 19 additions & 16 deletions src/elements/core/mixins/form-associated-mixin.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { LitElement } from 'lit';
import { property, state } from 'lit/decorators.js';

import type { Constructor } from './constructor.js';
import type { AbstractConstructor } from './constructor.js';

export declare abstract class SbbFormAssociatedMixinType {
export declare abstract class SbbFormAssociatedMixinType<V = string> {
public get form(): HTMLFormElement | null;
public get name(): string;
public set name(value: string);
public get type(): string;
public get value(): string | null;
public set value(value: string | null);
public get value(): V | null;
public set value(value: V | null);

public get validity(): ValidityState;
public get validationMessage(): string;
Expand All @@ -36,17 +36,17 @@ export declare abstract class SbbFormAssociatedMixinType {
* The FormAssociatedMixin enables native form support for custom controls.
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export const SbbFormAssociatedMixin = <T extends Constructor<LitElement>>(
export const SbbFormAssociatedMixin = <T extends AbstractConstructor<LitElement>, V = string>(
kyubisation marked this conversation as resolved.
Show resolved Hide resolved
superClass: T,
): Constructor<SbbFormAssociatedMixinType> & T => {
): AbstractConstructor<SbbFormAssociatedMixinType<V>> & T => {
abstract class SbbFormAssociatedElement
extends superClass
implements Partial<SbbFormAssociatedMixinType>
implements Partial<SbbFormAssociatedMixinType<V>>
{
public static formAssociated = true;

/**
* Returns the form owner of internals target element.
* Returns the form owner of the internals of the target element.
*/
public get form(): HTMLFormElement | null {
return this.internals.form;
Expand All @@ -73,14 +73,14 @@ export const SbbFormAssociatedMixin = <T extends Constructor<LitElement>>(

/** Value of the form element. */
@property()
public set value(value: string | null) {
public set value(value: V | null) {
this._value = value;
this.updateFormValue();
}
public get value(): string | null {
public get value(): V | null {
return this._value;
}
private _value: string | null = null;
private _value: V | null = null;

/**
* Returns the ValidityState object for internals target element.
Expand Down Expand Up @@ -192,12 +192,15 @@ export const SbbFormAssociatedMixin = <T extends Constructor<LitElement>>(
reason: FormRestoreReason,
): void;

/** Should be called when form value is changed. */
protected updateFormValue(): void {
this.internals.setFormValue(this.value);
}
/**
* Should be called when form value is changed.
* Adapts and sets the formValue in the supported format (string | FormData | File | null)
* https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
*/
protected abstract updateFormValue(): void;
TomMenga marked this conversation as resolved.
Show resolved Hide resolved
}
return SbbFormAssociatedElement as unknown as Constructor<SbbFormAssociatedMixinType> & T;
return SbbFormAssociatedElement as unknown as AbstractConstructor<SbbFormAssociatedMixinType<V>> &
T;
};

/**
Expand Down
3 changes: 2 additions & 1 deletion src/elements/core/mixins/required-mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export declare class SbbRequiredMixinType {
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export const SbbRequiredMixin = <
T extends AbstractConstructor<LitElement & SbbFormAssociatedMixinType>,
T extends AbstractConstructor<LitElement & SbbFormAssociatedMixinType<V>>,
V,
>(
superClass: T,
): AbstractConstructor<SbbRequiredMixinType> & T => {
Expand Down
25 changes: 15 additions & 10 deletions src/elements/select/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,25 @@ Opened panel:
| <kbd>Shift</kbd><kbd>Up Arrow</kbd> | If `multiple`, moves to the next non-disabled option and toggle its selection. |
| Any char or number | If exists, select the first non-disabled matching option after the selected value. |

<!-- Override
@type value => string \| string[] \| null
-->
<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| ------------- | ------------- | ------- | --------------------------------- | ------- | ------------------------------------------------------------------------ |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `isOpen` | - | public | `boolean` | | Whether the element is open. |
| `multiple` | `multiple` | public | `boolean` | `false` | Whether the select allows for multiple selection. |
| `negative` | `negative` | public | `boolean` | `false` | Negative coloring variant flag. |
| `placeholder` | `placeholder` | public | `string \| undefined` | | The placeholder used if no value has been selected. |
| `readonly` | `readonly` | public | `boolean` | `false` | Whether the select is readonly. |
| `required` | `required` | public | `boolean` | `false` | Whether the select is required. |
| `value` | `value` | public | `string \| string[] \| undefined` | | The value of the select component. If `multiple` is true, it's an array. |
| Name | Attribute | Privacy | Type | Default | Description |
| ------------- | ------------- | ------- | ---------------------------- | ------- | -------------------------------------------------------------- |
| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. |
| `form` | - | public | `HTMLFormElement \| null` | | Returns the form owner of the internals of the target element. |
| `isOpen` | - | public | `boolean` | | Whether the element is open. |
| `multiple` | `multiple` | public | `boolean` | `false` | Whether the select allows for multiple selection. |
| `name` | `name` | public | `string` | | Name of the form element. Will be read from name attribute. |
| `negative` | `negative` | public | `boolean` | `false` | Negative coloring variant flag. |
| `placeholder` | `placeholder` | public | `string \| undefined` | | The placeholder used if no value has been selected. |
| `readonly` | `readonly` | public | `boolean` | `false` | Whether the select is readonly. |
| `required` | `required` | public | `boolean` | `false` | Whether the component is required. |
| `value` | `value` | public | `string \| string[] \| null` | `null` | Value of the form element. |

## Methods

Expand Down
Loading
Loading