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

Docs/ 1158 Combobox finetune documentation #1647

Merged
merged 22 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion packages/components/badge/src/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Badge extends LitElement {

/**
* The size of the badge component.
* @default md
* @default 'md'
*/
@property({ reflect: true }) size?: BadgeSize;

Expand Down
2 changes: 1 addition & 1 deletion packages/components/button/src/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class Button extends LitElement {

/**
* The size of the button.
* @default md
* @default 'md'
*/
@property({ reflect: true }) size?: ButtonSize;

Expand Down
6 changes: 5 additions & 1 deletion packages/components/combobox/src/combobox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ export class Combobox<T = any, U = T> extends FormControlMixin(ScopedElementsMix
/** When set will cause the control to show it is valid after reportValidity is called. */
@property({ type: Boolean, attribute: 'show-valid' }) override showValid?: boolean;

/** The size of the combobox. */
/**
* The size of the combobox.
* @default 'md'
*/
@property({ reflect: true }) size?: ComboboxSize;

/**
Expand Down Expand Up @@ -405,6 +408,7 @@ export class Combobox<T = any, U = T> extends FormControlMixin(ScopedElementsMix
`;
}

/** @internal */
override focus(options?: FocusOptions): void {
this.input?.focus(options);
}
Expand Down
1 change: 1 addition & 0 deletions packages/components/form/src/form-control-mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ export function FormControlMixin<T extends Constructor<ReactiveElement>>(constru
return valid;
}

/** @internal Reset the form control state */
reset(value: unknown): void {
this.dirty = false;
this.formValue = value;
Expand Down
2 changes: 1 addition & 1 deletion packages/components/menu/src/menu-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class MenuButton extends ObserveAttributesMixin(ScopedElementsMixin(LitEl

/**
* The size of the button.
* @default md
* @default 'md'
*/
@property() size?: ButtonSize;

Expand Down
7,793 changes: 7,793 additions & 0 deletions website/src/_data/custom-elements/custom-elements.md

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions website/src/_data/tokens/core.json
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,16 @@
"type": "Icons",
"description": "icon.core.xmark"
},
"circle-xmark": {
"value": "circle-xmark",
"type": "Icons",
"description": "icon.core.circle-xmark"
},
"circle-xmark-solid": {
"value": "circle-xmark",
"type": "Icons",
"description": "icon.core.circle-xmark-solid"
},
"circle-solid": {
"value": "circle",
"type": "Icons",
Expand Down Expand Up @@ -2531,6 +2541,16 @@
"value": "dash",
"type": "Icons",
"description": "icon.core.dash-solid"
},
"plus": {
"value": "plus",
"type": "Icons",
"description": "icon.core.plus"
},
"minus": {
"value": "minus",
"type": "Icons",
"description": "icon.core.minus"
}
},
"typeset": {
Expand Down
70 changes: 70 additions & 0 deletions website/src/categories/components/combobox/accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: Combobox accessibility
tags: accessibility
eleventyNavigation:
parent: Combobox
key: ComboboxAccessibility
---

<section>

## Keyboard interactions

<div class="ds-table-wrapper">

|Command|Description|
|-|-|
|Tab|Moves the focus into/outside of the component.|
|Arrow up/down|Moves the active option 1 position up/down. The focus indicator loops, so when you are at the last option and press "down" it will focus on the first option.|
|Arrow left/right|When the combobox supports multiple selection, moves the focus to the tag on the left/right, assuming the caret is already at the beginning of the input.|
|Home/End|Moves the active option to the first/last option.|
|Enter|Toggles the active option.|
|Backspace|When a tag is focused, removes the tag. This is effectively the same as toggling the selected option using the Enter key.|

{.ds-table .ds-table-align-top}

</div>

</section>

<section>

## WAI-ARIA

WAI-ARIA Roles, States, and Properties for a combobox component provide essential information to assistive technologies and screen readers. They convey the combobox component's role, and additional properties to ensure accessibility and a better user experience for individuals using assistive technology.

### Input

<div class="ds-table-wrapper">

|Attribute|Value|Description|User supplied <sl-icon name="info" aria-describedby="tooltip1" size="md"></sl-icon><sl-tooltip id="tooltip1">Specifies whether the attribute is always set in the component (no) or it needs to be provided by the developer (yes)</sl-tooltip>|
|-|-|-|-|
|`role`|`'combobox'`|Identifies the input as a combobox.|no|
|`aria-activedescendant`|string|When an option in the listbox is visually indicated as having keyboard focus, refers to that option (by `id`) or when it is already selected.|no|
|`aria-autocomplete`|`both`|Indicates that the combobox can be used for both input and suggestions. The value `both` indicates that the combobox is a multi-function combobox.|no|
|`aria-controls`|string|Identifies the listbox controlled by the combobox.|no|
|`aria-expanded`|boolean|Set to `true` if the listbox (list of options) is visible, `false` if it is hidden.|no|
|`aria-haspopup`|`listbox`|Indicates that the combobox has a listbox popup.|no|
|`aria-label` |string|Defines a string that labels the action that will be performed when the user interacts with the combobox. Needs to be added when the combobox is not wrapped with `sl-form-field` and there is no `sl-label`. |yes|
|`aria-labelledby`|string|Used to connect with single header/element that describes the combobox, when there is no label component connected to.|yes|
|`aria-owns`|string|Identifies the listbox controlled by the combobox.|no|
|`aria-describedby`|string|Indicates the elements that describe the combobox. Used for helper text and validation.|no|

{.ds-table .ds-table-align-top}

</div>

### Listbox

<div class="ds-table-wrapper">

|Attribute|Value|Description|User supplied <sl-icon name="info" aria-describedby="tooltip1" size="md"></sl-icon><sl-tooltip id="tooltip1">Specifies whether the attribute is always set in the component (no) or it needs to be provided by the developer (yes)</sl-tooltip>|
|-|-|-|-|
|`role`|`'listbox'`|Identifies the element as a listbox.|no|
|`aria-multiselectable`|string|Indicates whether the combobox supports multiple selection (`true`), otherwise not present.|no|

{.ds-table .ds-table-align-top}

</div>

</section>
195 changes: 195 additions & 0 deletions website/src/categories/components/combobox/code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
---
title: Combobox code
tags: code
APIdescription: {
sl-combobox: "The Combobox streamlines single and multiple selections in large datasets of over 15 options. Its autocomplete feature filters options as users type, improving speed and usability. For multiple selections, it displays choices as tags in a tag list, enabling easy management and clear visibility of selected items."
}
eleventyNavigation:
parent: Combobox
key: ComboboxCode
---

<section>

<div class="ds-example">

<sl-combobox multiple style="inline-size: 100%; max-inline-size: min(30vw, 500px)" value='["0","3"]'>
<sl-listbox>
<sl-option-group label="Math">
<sl-option value="0">Algebra</sl-option>
<sl-option value="1">Geometry</sl-option>
<sl-option value="2">Calculus</sl-option>
</sl-option-group>
<sl-option-group label="Languages">
<sl-option value="3">English</sl-option>
<sl-option value="4">German</sl-option>
<sl-option value="5">French</sl-option>
<sl-option value="6">Spanish</sl-option>
<sl-option value="7">Chinese</sl-option>
</sl-option-group>
</sl-listbox>
</sl-combobox>

</div>

<div class="ds-code">

```html
<sl-combobox multiple value='["0","1"]'>
<sl-listbox>
<sl-option-group label="Math">
<sl-option value="0">Algebra</sl-option>
<sl-option value="1">Geometry</sl-option>
<sl-option value="2">Calculus</sl-option>
</sl-option-group>
<sl-option-group label="Languages">
<sl-option value="3">English</sl-option>
<sl-option value="4">German</sl-option>
<sl-option value="5">French</sl-option>
<sl-option value="6">Spanish</sl-option>
<sl-option value="7">Chinese</sl-option>
</sl-option-group>
</sl-listbox>
</sl-combobox>
```

</div>

</section>

<ds-install-info link-in-navigation package="combobox"></ds-install-info>

<section>

## Listbox

Unlike the native `<select>` element, you have to wrap the options in an `sl-listbox` element. This is because the listbox needs to be associated with the `<input>` element of the embedded text field for accessibility purposes (`aria-controls`, `aria-expanded` and `aria-haspopup`). That can only be done if the listbox is in the same shadow root as the input.

If you are not rendering the options yourself (see below), the combobox component will automatically wrap the options in an `sl-listbox` element for you.

</section>

<section>

## Options

There are two ways you can define the options for the combobox:
1. By using the `sl-option` element inside the `sl-listbox` element yourself
2. By using the `options` property on the `sl-combobox` element

There is no difference in behavior of the combobox between the two methods.

### Using `sl-option` elements

Use this method if you have a small to medium number of options and you want to define them directly in your HTML.

```html
<sl-combobox>
<sl-listbox>
<sl-option value="0">Mathematics</sl-option>
<sl-option value="1">Geography</sl-option>
<sl-option value="2">Physics</sl-option>
<sl-option value="3">History</sl-option>
</sl-listbox>
</sl-combobox>
```

This is usually the simpler method, but it can become a performance issue if you have a large number of options (more than 100 options).

### Using the `options` property

Use this method if you have a large number of options. This method is more performant because it only renders the options that are currently visible. This method can be used with *thousands* of options, without any degradation in performance (this does not mean you should use the combobox component if you have thousands of options, but there are cases where the amount of options is determined by outside factors).

```js
const options = [
{ value: "0", label: "Mathematics" },
{ value: "1", label: "Geography" },
{ value: "2", label: "Physics" },
{ value: "3", label: "History" }
];
```

```html
<sl-combobox
.options=${options}
option-label-path="label"
option-value-path="value"
></sl-combobox>
```

By using the `option-group-path`, `option-label-path`, `option-selected-path` and `option-value-path` properties, you can specify which properties on the option objects should be used to render the options.

If you only specify a string array as the `options` property, the combobox will use the strings as both the label and value.

</section>

<section>

## Grouping options

You can group options using the `sl-option-group` element. This element can contain `sl-option` elements. It is not recommended to have nested `sl-option-group` elements.

```html
<sl-combobox>
<sl-listbox>
<sl-option-group label="Math">
<sl-option value="0">Algebra</sl-option>
<sl-option value="1">Geometry</sl-option>
<sl-option value="2">Calculus</sl-option>
</sl-option-group>
<sl-option-group label="Languages">
<sl-option value="3">English</sl-option>
<sl-option value="4">German</sl-option>
<sl-option value="5">French</sl-option>
<sl-option value="6">Spanish</sl-option>
<sl-option value="7">Chinese</sl-option>
</sl-option-group>
</sl-listbox>
</sl-combobox>
```

If you are using the `options` property, you can group options by setting the `option-group-path` property. The component will automatically group options based on the value of the specified property. The value of the group property will be used to label the group.

```js
const options = [
{ value: "0", label: "Algebra", group: "Math" },
{ value: "1", label: "Geometry", group: "Math" },
{ value: "2", label: "Calculus", group: "Math" },
{ value: "3", label: "English", group: "Languages" },
{ value: "4", label: "German", group: "Languages" },
{ value: "5", label: "French", group: "Languages" },
{ value: "6", label: "Spanish", group: "Languages" },
{ value: "7", label: "Chinese", group: "Languages" }
];
```

```html
<sl-combobox
.options=${options}
option-group-path="group"
option-label-path="label"
option-value-path="value"
></sl-combobox>
```

</section>

<section>

## Selected

The combobox component is in single selection mode by default. If you want to enable multiple selection, you can set the `multiple` property on the `sl-combobox` element. The `value` property is, depending on the selection mode, either a single value or an array of values.

There are two ways you can set the selected options for the combobox:
1. By using the `value` property on the `sl-combobox` element
2. By using the `selected` property on the `sl-option` elements

It is sometimes easier to set the `selected` property since you are already rendering the options yourself. If you are not rendering the options yourself, you can specify the `group-selected-path` property instead.

In both cases you could also use the `value` property on the `sl-combobox` element to set the selected options.

Do not use both methods at the same time.

</section>

{% include "../component-table.njk" %}
11 changes: 11 additions & 0 deletions website/src/categories/components/combobox/combobox.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"layout": "categories/components/components.njk",
"tags": "combobox",
"componentStatus": "draft",
"componentTagName": [
{
"name": "Combobox",
"selector": "sl-combobox"
}
]
}
14 changes: 14 additions & 0 deletions website/src/categories/components/combobox/combobox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Combobox
description: The Combobox streamlines single and multiple selections in large datasets of over 15 options. Its autocomplete feature filters options as users type, improving speed and usability. For multiple selections, it displays choices as tags in a tag list, enabling easy management and clear visibility of selected items.
componentType: form
shortDescription: An combobox is an advanced dropdown selection component with autocomplete functionality for efficient and intuitive user input
layout: "categories/components/components.njk"
tags: component
packageName: combobox
storybookCategory: form
eleventyNavigation:
parent: Components
key: Combobox
status: new
---
Loading