md-multi-select spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
Pick several values from a list. Everything
md-select does, plus multiple selection rendered as
chips / a count / plain text, an optional select-all row, a selection cap, and
a field-or-button trigger. Form-associated via ElementInternals.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Teams" supporting-text="Pick up to three" max-selected="3" clearable style="min-width: 280px;">
<md-select-option value="eng" supporting-text="24 members" selected>Engineering</md-select-option>
<md-select-option value="des" supporting-text="6 members" selected>Design</md-select-option>
<md-select-option value="ops" supporting-text="11 members">Operations</md-select-option>
<md-select-option value="sec" supporting-text="4 members">Security</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Teams" supportingText="Pick up to three" maxSelected="3" clearable style={{ minWidth: '280px' }}>
<MdSelectOption value="eng" supportingText="24 members" selected>Engineering</MdSelectOption>
<MdSelectOption value="des" supportingText="6 members" selected>Design</MdSelectOption>
<MdSelectOption value="ops" supportingText="11 members">Operations</MdSelectOption>
<MdSelectOption value="sec" supportingText="4 members">Security</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Teams" supporting-text="Pick up to three" max-selected="3" clearable style="min-width: 280px;">
<md-select-option value="eng" supporting-text="24 members" selected>Engineering</md-select-option>
<md-select-option value="des" supporting-text="6 members" selected>Design</md-select-option>
<md-select-option value="ops" supporting-text="11 members">Operations</md-select-option>
<md-select-option value="sec" supporting-text="4 members">Security</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Teams" supporting-text="Pick up to three" max-selected="3" clearable style="min-width: 280px;">
<md-select-option value="eng" supporting-text="24 members" selected>Engineering</md-select-option>
<md-select-option value="des" supporting-text="6 members" selected>Design</md-select-option>
<md-select-option value="ops" supporting-text="11 members">Operations</md-select-option>
<md-select-option value="sec" supporting-text="4 members">Security</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Teams" supporting-text="Pick up to three" max-selected="3" clearable style="min-width: 280px;">
<md-select-option value="eng" supporting-text="24 members" selected>Engineering</md-select-option>
<md-select-option value="des" supporting-text="6 members" selected>Design</md-select-option>
<md-select-option value="ops" supporting-text="11 members">Operations</md-select-option>
<md-select-option value="sec" supporting-text="4 members">Security</md-select-option>
</md-multi-select>
Already installed? See the
Installation guide for one-time package setup
(core + tokens, fonts). Each tab below shows two patterns for using
md-multi-select in your project: Option A registers every AWC UI
component at once (simplest), Option B imports only this component for
tree-shake-friendly bundles.
<!-- ─── Option A: global registration (all components) ─── -->
<script type="module">
import '@awc-ui/core/define';
</script>
<!-- ─── Option B: single import (tree-shake only md-multi-select) ─── -->
<script type="module">
import '@awc-ui/core/components/md-multi-select';
</script>
<md-multi-select></md-multi-select>// ─── Option A: typed React wrapper (registers all components) ───
// Importing from '@awc-ui/react' calls defineCustomElements() as a
// side effect, so every md-* element becomes available in the browser.
import { MdMultiSelect } from '@awc-ui/react';
export function Example() {
return <MdMultiSelect></MdMultiSelect>;
}
// ─── Option B: single import (tree-shake to only md-multi-select) ───
// Skip the wrapper and use the raw custom element. Smallest bundle,
// but you lose typed props/events on JSX.
import '@awc-ui/core/components/md-multi-select';
export function ExampleTreeShaken() {
return <md-multi-select></md-multi-select>;
}// ─── Option A: schema module (any md-* element accepted) ───
// Pair with `defineCustomElements(window)` in main.ts.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<md-multi-select></md-multi-select>`,
})
export class ExampleComponent {}
// ─── Option B: typed directive (tree-shake friendly) ───
// Pair with `import '@awc-ui/core/components/md-multi-select'` in main.ts.
import { Component } from '@angular/core';
import { MdMultiSelect } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [MdMultiSelect],
template: `<md-multi-select></md-multi-select>`,
})
export class ExampleTreeShakenComponent {}<!-- ─── Option A: typed Vue wrapper (registers all components) ─── -->
<script setup lang="ts">
import { MdMultiSelect } from '@awc-ui/vue';
</script>
<template>
<MdMultiSelect></MdMultiSelect>
</template>
<!-- ─── Option B: single import (tree-shake to only md-multi-select) ─── -->
<script setup lang="ts">
import '@awc-ui/core/components/md-multi-select';
</script>
<template>
<md-multi-select></md-multi-select>
</template><!-- ─── Option A: global registration (done once in main entry) ─── -->
<!-- main.ts: -->
<!-- import { defineCustomElements } from '@awc-ui/svelte'; -->
<!-- defineCustomElements(window); -->
<md-multi-select></md-multi-select>
<!-- ─── Option B: single import (tree-shake to only md-multi-select) ─── -->
<script lang="ts">
import '@awc-ui/core/components/md-multi-select';
</script>
<md-multi-select></md-multi-select>max-selected, or with a select-all shortcut.| Situation | Use instead |
|---|---|
| Exactly one value | md-select |
| Few options, all worth showing | md-checkbox group |
| Assigning a subset from a large pool, side by side | md-transfer-list |
| Free text with suggestions | md-autocomplete |
| A handful of toggleable filters | md-chip set |
| 2–5 exclusive options | md-segmented-button |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select id="teams" label="Teams" display-mode="count"></md-multi-select>
<script type="module">
const el = document.getElementById('teams');
// Both are PROPERTIES — an array and a function never cross as attributes.
el.options = teams.map((t) => ({ value: t.id, label: t.name }));
el.value = ['eng', 'design'];
el.countFormatter = (n) => n + ' teams selected';
</script>import { MdMultiSelect } from '@awc-ui/react';
// Both are PROPERTIES — an array and a function never cross as attributes.
const options = teams.map((t) => ({ value: t.id, label: t.name }));
const value = ['eng', 'design'];
const countFormatter = (n) => n + ' teams selected';
export function Demo() {
return (
<>
<MdMultiSelect id="teams"
options={options}
value={value}
countFormatter={countFormatter} label="Teams" displayMode="count"></MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
// app.component.ts — the bound values live on the class
import { Component } from '@angular/core';
@Component({
selector: 'app-demo',
templateUrl: './app.component.html',
})
export class DemoComponent {
options = teams.map((t) => ({ value: t.id, label: t.name }));
value = ['eng', 'design'];
countFormatter = (n) => n + ' teams selected';
}
<!-- app.component.html -->
<md-multi-select id="teams"
[options]="options"
[value]="value"
[count-formatter]="countFormatter" label="Teams" display-mode="count"></md-multi-select><script setup>
import '@awc-ui/core/define';
const options = teams.map((t) => ({ value: t.id, label: t.name }));
const value = ['eng', 'design'];
const countFormatter = (n) => n + ' teams selected';
</script>
<template>
<md-multi-select id="teams"
:options="options"
:value="value"
:count-formatter="countFormatter" label="Teams" display-mode="count"></md-multi-select>
</template><script>
import '@awc-ui/core/define';
const options = teams.map((t) => ({ value: t.id, label: t.name }));
const value = ['eng', 'design'];
const countFormatter = (n) => n + ' teams selected';
</script>
<md-multi-select id="teams"
{options}
{value}
{countFormatter} label="Teams" display-mode="count"></md-multi-select>The same two option sources as md-select apply — declarative
md-select-option children or the options
array property, never both.
| Need | Setting |
|---|---|
| Chips inside the field | display="chips" |
| A “3 selected” summary | display="count" |
| Chips below the field | display="chips-inline" |
| A button instead of a field | trigger="button" |
| A “select all” row | select-all |
| A hard limit | max-selected |
| An in-menu search box | filterable |
| Compact trigger, chips and rows | density="-1…-4" |
| Mode | Renders |
|---|---|
chips | Default. Chips below the field |
chips-inline | Chips inside the field |
count | A summary such as “3 selected” (customise with countFormatter) |
text | Comma-separated labels |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Chips" display-mode="chips" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Chips inline" display-mode="chips-inline" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Count" display-mode="count" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Text" display-mode="text" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Chips" displayMode="chips" style={{ minWidth: '240px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Chips inline" displayMode="chips-inline" style={{ minWidth: '240px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Count" displayMode="count" style={{ minWidth: '240px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Text" displayMode="text" style={{ minWidth: '240px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Chips" display-mode="chips" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Chips inline" display-mode="chips-inline" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Count" display-mode="count" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Text" display-mode="text" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Chips" display-mode="chips" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Chips inline" display-mode="chips-inline" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Count" display-mode="count" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Text" display-mode="text" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Chips" display-mode="chips" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Chips inline" display-mode="chips-inline" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Count" display-mode="count" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Text" display-mode="text" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>chip-overflow="count" collapses the tail into a “+5” chip; "wrap" lets the
chips wrap. chip-position places the chip strip bottom (default), top,
left or right.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Overflow as +N" chip-overflow="count" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c" selected>Operations</md-select-option>
<md-select-option value="d" selected>Security</md-select-option>
<md-select-option value="e" selected>Support</md-select-option>
</md-multi-select>
<md-multi-select label="Chips above" chip-position="top" chip-overflow="wrap" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Overflow as +N" chipOverflow="count" style={{ minWidth: '260px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c" selected>Operations</MdSelectOption>
<MdSelectOption value="d" selected>Security</MdSelectOption>
<MdSelectOption value="e" selected>Support</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Chips above" chipPosition="top" chipOverflow="wrap" style={{ minWidth: '260px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Overflow as +N" chip-overflow="count" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c" selected>Operations</md-select-option>
<md-select-option value="d" selected>Security</md-select-option>
<md-select-option value="e" selected>Support</md-select-option>
</md-multi-select>
<md-multi-select label="Chips above" chip-position="top" chip-overflow="wrap" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Overflow as +N" chip-overflow="count" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c" selected>Operations</md-select-option>
<md-select-option value="d" selected>Security</md-select-option>
<md-select-option value="e" selected>Support</md-select-option>
</md-multi-select>
<md-multi-select label="Chips above" chip-position="top" chip-overflow="wrap" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Overflow as +N" chip-overflow="count" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c" selected>Operations</md-select-option>
<md-select-option value="d" selected>Security</md-select-option>
<md-select-option value="e" selected>Support</md-select-option>
</md-multi-select>
<md-multi-select label="Chips above" chip-position="top" chip-overflow="wrap" style="min-width: 260px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>trigger="button" swaps the text-field trigger for a button, named by
trigger-label and iconed by trigger-icon.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Field trigger" trigger="field" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
</md-multi-select>
<md-multi-select trigger="button" trigger-icon="add" trigger-label="Add tags" chip-position="right" chip-overflow="wrap">
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Field trigger" trigger="field" style={{ minWidth: '240px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b">Design</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect trigger="button" triggerIcon="add" triggerLabel="Add tags" chipPosition="right" chipOverflow="wrap">
<MdSelectOption value="a" selected>Alpha</MdSelectOption>
<MdSelectOption value="b">Beta</MdSelectOption>
<MdSelectOption value="c">Gamma</MdSelectOption>
</MdMultiSelect>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Field trigger" trigger="field" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
</md-multi-select>
<md-multi-select trigger="button" trigger-icon="add" trigger-label="Add tags" chip-position="right" chip-overflow="wrap">
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Field trigger" trigger="field" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
</md-multi-select>
<md-multi-select trigger="button" trigger-icon="add" trigger-label="Add tags" chip-position="right" chip-overflow="wrap">
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<md-multi-select label="Field trigger" trigger="field" style="min-width: 240px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
</md-multi-select>
<md-multi-select trigger="button" trigger-icon="add" trigger-label="Add tags" chip-position="right" chip-overflow="wrap">
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>trigger="button" is a convenience, not a ceiling. Put any element in
slot="trigger" and it becomes the opener: the built-in field / button is not
rendered at all, and the chips keep their chip-position relationship to
whatever you supplied. The opener sits outside the component’s own chrome
without losing the chip layout.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Tags" chip-position="right" chip-overflow="wrap">
<md-button slot="trigger" variant="outlined" size="xs" icon="add">Add tags</md-button>
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>
<md-multi-select label="Filters" chip-position="right" chip-overflow="wrap">
<md-icon-button slot="trigger" variant="tonal" icon="filter_list" aria-label="Filter"></md-icon-button>
<md-select-option value="open" selected>Open</md-select-option>
<md-select-option value="mine">Assigned to me</md-select-option>
<md-select-option value="urgent">Urgent</md-select-option>
</md-multi-select>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdButton, MdIconButton, MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Tags" chipPosition="right" chipOverflow="wrap">
<MdButton slot="trigger" variant="outlined" size="xs" icon="add">Add tags</MdButton>
<MdSelectOption value="a" selected>Alpha</MdSelectOption>
<MdSelectOption value="b">Beta</MdSelectOption>
<MdSelectOption value="c">Gamma</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Filters" chipPosition="right" chipOverflow="wrap">
<MdIconButton slot="trigger" variant="tonal" icon="filter_list" aria-label="Filter"></MdIconButton>
<MdSelectOption value="open" selected>Open</MdSelectOption>
<MdSelectOption value="mine">Assigned to me</MdSelectOption>
<MdSelectOption value="urgent">Urgent</MdSelectOption>
</MdMultiSelect>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Tags" chip-position="right" chip-overflow="wrap">
<md-button slot="trigger" variant="outlined" size="xs" icon="add">Add tags</md-button>
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>
<md-multi-select label="Filters" chip-position="right" chip-overflow="wrap">
<md-icon-button slot="trigger" variant="tonal" icon="filter_list" aria-label="Filter"></md-icon-button>
<md-select-option value="open" selected>Open</md-select-option>
<md-select-option value="mine">Assigned to me</md-select-option>
<md-select-option value="urgent">Urgent</md-select-option>
</md-multi-select><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Tags" chip-position="right" chip-overflow="wrap">
<md-button slot="trigger" variant="outlined" size="xs" icon="add">Add tags</md-button>
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>
<md-multi-select label="Filters" chip-position="right" chip-overflow="wrap">
<md-icon-button slot="trigger" variant="tonal" icon="filter_list" aria-label="Filter"></md-icon-button>
<md-select-option value="open" selected>Open</md-select-option>
<md-select-option value="mine">Assigned to me</md-select-option>
<md-select-option value="urgent">Urgent</md-select-option>
</md-multi-select>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<md-multi-select label="Tags" chip-position="right" chip-overflow="wrap">
<md-button slot="trigger" variant="outlined" size="xs" icon="add">Add tags</md-button>
<md-select-option value="a" selected>Alpha</md-select-option>
<md-select-option value="b">Beta</md-select-option>
<md-select-option value="c">Gamma</md-select-option>
</md-multi-select>
<md-multi-select label="Filters" chip-position="right" chip-overflow="wrap">
<md-icon-button slot="trigger" variant="tonal" icon="filter_list" aria-label="Filter"></md-icon-button>
<md-select-option value="open" selected>Open</md-select-option>
<md-select-option value="mine">Assigned to me</md-select-option>
<md-select-option value="urgent">Urgent</md-select-option>
</md-multi-select>The component wires the element it is given rather than re-rendering it: a click
opens the menu, an id makes it the menu’s anchor, and aria-haspopup="listbox"
advertises the popup (aria-expanded follows on triggers whose role supports it).
Escape closes and returns focus to it.
show-select-all adds a select-all row. max-selected caps the selection —
and the value that means “no cap” is 0.
When the cap is reached the component rejects further selections. Because
md-menu-item / md-checkbox self-toggle on click before the parent
reconciles, a rejected pick has to be reverted via the event target — the
component does this internally, but if you wrap it in your own controlled
layer, replicate it or you will get a phantom check.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Everything" show-select-all select-all-label="Select all" style="min-width: 250px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Capped at 2" max-selected="2" supporting-text="Pick up to two" style="min-width: 250px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Everything" showSelectAll selectAllLabel="Select all" style={{ minWidth: '250px' }}>
<MdSelectOption value="a">Engineering</MdSelectOption>
<MdSelectOption value="b">Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Capped at 2" maxSelected="2" supportingText="Pick up to two" style={{ minWidth: '250px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Everything" show-select-all select-all-label="Select all" style="min-width: 250px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Capped at 2" max-selected="2" supporting-text="Pick up to two" style="min-width: 250px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Everything" show-select-all select-all-label="Select all" style="min-width: 250px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Capped at 2" max-selected="2" supporting-text="Pick up to two" style="min-width: 250px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Everything" show-select-all select-all-label="Select all" style="min-width: 250px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Capped at 2" max-selected="2" supporting-text="Pick up to two" style="min-width: 250px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>Explain the cap in supporting-text — a silent rejection is invisible,
especially to screen-reader users.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select variant="outlined" label="Outlined" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select variant="filled" label="Filled" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Disabled" disabled style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Teams" required error error-text="Choose at least one" reserve-supporting-space style="min-width: 210px;">
<md-select-option value="a">Alpha</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect variant="outlined" label="Outlined" style={{ minWidth: '210px' }}>
<MdSelectOption value="a" selected>Alpha</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect variant="filled" label="Filled" style={{ minWidth: '210px' }}>
<MdSelectOption value="a" selected>Alpha</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Disabled" disabled style={{ minWidth: '210px' }}>
<MdSelectOption value="a" selected>Alpha</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Teams" required error errorText="Choose at least one" reserveSupportingSpace style={{ minWidth: '210px' }}>
<MdSelectOption value="a">Alpha</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select variant="outlined" label="Outlined" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select variant="filled" label="Filled" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Disabled" disabled style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Teams" required error error-text="Choose at least one" reserve-supporting-space style="min-width: 210px;">
<md-select-option value="a">Alpha</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select variant="outlined" label="Outlined" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select variant="filled" label="Filled" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Disabled" disabled style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Teams" required error error-text="Choose at least one" reserve-supporting-space style="min-width: 210px;">
<md-select-option value="a">Alpha</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select variant="outlined" label="Outlined" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select variant="filled" label="Filled" style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Disabled" disabled style="min-width: 210px;">
<md-select-option value="a" selected>Alpha</md-select-option>
</md-multi-select>
<md-multi-select label="Teams" required error error-text="Choose at least one" reserve-supporting-space style="min-width: 210px;">
<md-select-option value="a">Alpha</md-select-option>
</md-multi-select>error-text replaces supporting-text when error is set — never show
both. soft-disabled keeps the trigger focusable so an unavailable control is
still discoverable.
filterable renders a search box inside the menu — turn it on past roughly 15
options. loading drives the progress affordance while options are fetched.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Filterable" filterable search-placeholder="Search…" filter-label="Filter teams" style="min-width: 220px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Loading" loading loading-text="Loading…" style="min-width: 220px;"></md-multi-select>
<md-multi-select label="Slotted loader" loading loading-text="Loading…" style="min-width: 220px;">
<md-progress-indicator slot="loader" variant="circular" indeterminate size="24" label="Loading"></md-progress-indicator>
</md-multi-select>
<md-multi-select label="Density -3" density="-3" style="min-width: 220px;">
<md-select-option value="a" selected>Engineering</md-select-option>
</md-multi-select>import { MdMultiSelect, MdProgressIndicator, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Filterable" filterable searchPlaceholder="Search…" filterLabel="Filter teams" style={{ minWidth: '220px' }}>
<MdSelectOption value="a">Engineering</MdSelectOption>
<MdSelectOption value="b">Design</MdSelectOption>
<MdSelectOption value="c">Operations</MdSelectOption>
</MdMultiSelect>
<MdMultiSelect label="Loading" loading loadingText="Loading…" style={{ minWidth: '220px' }}></MdMultiSelect>
<MdMultiSelect label="Slotted loader" loading loadingText="Loading…" style={{ minWidth: '220px' }}>
<MdProgressIndicator slot="loader" variant="circular" indeterminate size="24" label="Loading"></MdProgressIndicator>
</MdMultiSelect>
<MdMultiSelect label="Density -3" density="-3" style={{ minWidth: '220px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Filterable" filterable search-placeholder="Search…" filter-label="Filter teams" style="min-width: 220px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Loading" loading loading-text="Loading…" style="min-width: 220px;"></md-multi-select>
<md-multi-select label="Slotted loader" loading loading-text="Loading…" style="min-width: 220px;">
<md-progress-indicator slot="loader" variant="circular" indeterminate size="24" label="Loading"></md-progress-indicator>
</md-multi-select>
<md-multi-select label="Density -3" density="-3" style="min-width: 220px;">
<md-select-option value="a" selected>Engineering</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Filterable" filterable search-placeholder="Search…" filter-label="Filter teams" style="min-width: 220px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Loading" loading loading-text="Loading…" style="min-width: 220px;"></md-multi-select>
<md-multi-select label="Slotted loader" loading loading-text="Loading…" style="min-width: 220px;">
<md-progress-indicator slot="loader" variant="circular" indeterminate size="24" label="Loading"></md-progress-indicator>
</md-multi-select>
<md-multi-select label="Density -3" density="-3" style="min-width: 220px;">
<md-select-option value="a" selected>Engineering</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Filterable" filterable search-placeholder="Search…" filter-label="Filter teams" style="min-width: 220px;">
<md-select-option value="a">Engineering</md-select-option>
<md-select-option value="b">Design</md-select-option>
<md-select-option value="c">Operations</md-select-option>
</md-multi-select>
<md-multi-select label="Loading" loading loading-text="Loading…" style="min-width: 220px;"></md-multi-select>
<md-multi-select label="Slotted loader" loading loading-text="Loading…" style="min-width: 220px;">
<md-progress-indicator slot="loader" variant="circular" indeterminate size="24" label="Loading"></md-progress-indicator>
</md-multi-select>
<md-multi-select label="Density -3" density="-3" style="min-width: 220px;">
<md-select-option value="a" selected>Engineering</md-select-option>
</md-multi-select><!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select id="users" label="Users" filterable></md-multi-select>
<script type="module">
const el = document.getElementById('users');
let loaded = false;
el.addEventListener('mdOpen', async () => {
if (loaded) return;
loaded = true;
el.loading = true;
el.loadOptions(await fetchUsers()); // SelectOptionInit[] or { count, getRow }
el.loading = false;
});
</script>import { useEffect, useRef } from 'react';
import { MdMultiSelect } from '@awc-ui/react';
export function Demo() {
const elRef = useRef(null);
useEffect(() => {
const el = elRef.current;
let loaded = false;
el.addEventListener('mdOpen', async () => {
if (loaded) return;
loaded = true;
el.loading = true;
el.loadOptions(await fetchUsers()); // SelectOptionInit[] or { count, getRow }
el.loading = false;
});
}, []);
return (
<>
<MdMultiSelect id="users" ref={elRef} label="Users" filterable></MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
// app.component.ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-demo',
templateUrl: './app.component.html',
})
export class DemoComponent implements AfterViewInit {
@ViewChild('el') elRef!: ElementRef;
ngAfterViewInit() {
const el = this.elRef.nativeElement;
let loaded = false;
el.addEventListener('mdOpen', async () => {
if (loaded) return;
loaded = true;
el.loading = true;
el.loadOptions(await fetchUsers()); // SelectOptionInit[] or { count, getRow }
el.loading = false;
});
}
}
<!-- app.component.html -->
<md-multi-select id="users" #el label="Users" filterable></md-multi-select><script setup>
import { onMounted, ref } from 'vue';
import '@awc-ui/core/define';
const elRef = ref(null);
onMounted(() => {
const el = elRef.value;
let loaded = false;
el.addEventListener('mdOpen', async () => {
if (loaded) return;
loaded = true;
el.loading = true;
el.loadOptions(await fetchUsers()); // SelectOptionInit[] or { count, getRow }
el.loading = false;
});
});
</script>
<template>
<md-multi-select id="users" ref="elRef" label="Users" filterable></md-multi-select>
</template><script>
import { onMount } from 'svelte';
import '@awc-ui/core/define';
let elRef;
onMount(() => {
const el = elRef;
let loaded = false;
el.addEventListener('mdOpen', async () => {
if (loaded) return;
loaded = true;
el.loading = true;
el.loadOptions(await fetchUsers()); // SelectOptionInit[] or { count, getRow }
el.loading = false;
});
});
</script>
<md-multi-select id="users" bind:this={elRef} label="Users" filterable></md-multi-select>virtualize="always" hands the option set to the WASM-backed store: rows stream
in through a factory instead of existing as JS objects, and only the visible
window is ever in the DOM. Filtering and typeahead run in the same store, so a
query over ten million rows is not a JS array scan.
Same caveat as md-select — give non-uniform rows a stable row-height, or the
scroll position drifts.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select
id="options"
label="Option"
filterable
show-select-all
display-mode="count"
virtualize="always"
row-height="48"
max-height="320"
></md-multi-select>
<script type="module">
const el = document.getElementById('options');
// A row factory streams into WASM — ten million options never exist as JS
// objects at once. Flip the loading flag around it so the trigger says so.
el.loading = true;
await el.loadOptions({
count: 10_000_000,
getRow: (i) => ({ value: `v${i}`, label: `Option ${i}` }),
});
el.loading = false;
</script>import { useEffect, useRef } from 'react';
import { MdMultiSelect } from '@awc-ui/react';
export function Demo() {
const elRef = useRef(null);
useEffect(() => {
const el = elRef.current;
// A row factory streams into WASM — ten million options never exist as JS
// objects at once. Flip the loading flag around it so the trigger says so.
el.loading = true;
await el.loadOptions({
count: 10_000_000,
getRow: (i) => ({ value: `v${i}`, label: `Option ${i}` }),
});
el.loading = false;
}, []);
return (
<>
<MdMultiSelect
id="options" ref={elRef}
label="Option"
filterable
showSelectAll
displayMode="count"
virtualize="always"
rowHeight="48"
maxHeight="320"
></MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
// app.component.ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-demo',
templateUrl: './app.component.html',
})
export class DemoComponent implements AfterViewInit {
@ViewChild('el') elRef!: ElementRef;
ngAfterViewInit() {
const el = this.elRef.nativeElement;
// A row factory streams into WASM — ten million options never exist as JS
// objects at once. Flip the loading flag around it so the trigger says so.
el.loading = true;
await el.loadOptions({
count: 10_000_000,
getRow: (i) => ({ value: `v${i}`, label: `Option ${i}` }),
});
el.loading = false;
}
}
<!-- app.component.html -->
<md-multi-select
id="options" #el
label="Option"
filterable
show-select-all
display-mode="count"
virtualize="always"
row-height="48"
max-height="320"
></md-multi-select><script setup>
import { onMounted, ref } from 'vue';
import '@awc-ui/core/define';
const elRef = ref(null);
onMounted(() => {
const el = elRef.value;
// A row factory streams into WASM — ten million options never exist as JS
// objects at once. Flip the loading flag around it so the trigger says so.
el.loading = true;
await el.loadOptions({
count: 10_000_000,
getRow: (i) => ({ value: `v${i}`, label: `Option ${i}` }),
});
el.loading = false;
});
</script>
<template>
<md-multi-select
id="options" ref="elRef"
label="Option"
filterable
show-select-all
display-mode="count"
virtualize="always"
row-height="48"
max-height="320"
></md-multi-select>
</template><script>
import { onMount } from 'svelte';
import '@awc-ui/core/define';
let elRef;
onMount(() => {
const el = elRef;
// A row factory streams into WASM — ten million options never exist as JS
// objects at once. Flip the loading flag around it so the trigger says so.
el.loading = true;
await el.loadOptions({
count: 10_000_000,
getRow: (i) => ({ value: `v${i}`, label: `Option ${i}` }),
});
el.loading = false;
});
</script>
<md-multi-select
id="options" bind:this={elRef}
label="Option"
filterable
show-select-all
display-mode="count"
virtualize="always"
row-height="48"
max-height="320"
></md-multi-select>md-multi-select is form-associated via ElementInternals, so name puts
the selection into FormData across the shadow boundary — no hidden <input>
needed. required participates in constraint validation, with
value-missing-label as the message.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<form id="signup">
<md-multi-select id="teams" label="Teams" name="teams" required
value-missing-label="Please select at least one option">
<md-select-option value="eng">Engineering</md-select-option>
<md-select-option value="des">Design</md-select-option>
</md-multi-select>
<md-button variant="filled" type="submit">Save</md-button>
</form>
<script type="module">
const el = document.getElementById('teams');
el.value = ['eng']; // ARRAY property
el.addEventListener('mdChange', (e) => save(e.detail)); // string[]
el.addEventListener('mdRemove', (e) => log('removed', e.detail));
el.addEventListener('mdClear', () => log('cleared'));
document.getElementById('signup').addEventListener('submit', (e) => {
e.preventDefault();
console.log(new FormData(e.target).getAll('teams'));
});
</script>import { useState } from 'react';
import { MdMultiSelect, MdSelectOption, MdButton } from '@awc-ui/react';
export function TeamsForm() {
// value is an array PROPERTY, forwarded by the wrapper — pass it as a prop.
const [teams, setTeams] = useState(['eng']);
return (
<form onSubmit={(e) => { e.preventDefault(); }}>
<MdMultiSelect
value={teams}
label="Teams"
name="teams"
required
onMdChange={(e) => setTeams(e.detail)}
>
<MdSelectOption value="eng">Engineering</MdSelectOption>
<MdSelectOption value="des">Design</MdSelectOption>
</MdMultiSelect>
<MdButton variant="filled" type="submit">Save</MdButton>
</form>
);
}import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-teams-form',
template: `
<form (submit)="onSubmit($event)">
<md-multi-select #teams label="Teams" name="teams" required
(mdChange)="onChange($event)"></md-multi-select>
<md-button variant="filled" type="submit">Save</md-button>
</form>
`,
})
export class TeamsFormComponent implements AfterViewInit {
@ViewChild('teams') teams!: ElementRef<HTMLElement & { value: string[] }>;
ngAfterViewInit() {
this.teams.nativeElement.value = ['eng']; // array property
}
onChange(e: CustomEvent<string[]>) { save(e.detail); }
onSubmit(e: Event) { e.preventDefault(); }
}<script setup lang="ts">
import { ref, onMounted } from 'vue';
const teams = ref<(HTMLElement & { value: string[] }) | null>(null);
onMounted(() => {
if (teams.value) teams.value.value = ['eng']; // array property
});
function onChange(e: CustomEvent<string[]>) { save(e.detail); }
</script>
<template>
<form @submit.prevent>
<md-multi-select
ref="teams"
label="Teams"
name="teams"
required
@mdChange="onChange"
/>
<md-button variant="filled" type="submit">Save</md-button>
</form>
</template><script lang="ts">
import { onMount } from 'svelte';
let teams: HTMLElement & { value: string[] };
onMount(() => { teams.value = ['eng']; }); // array property
function onChange(e: CustomEvent<string[]>) { save(e.detail); }
</script>
<form on:submit|preventDefault>
<md-multi-select
bind:this={teams}
label="Teams"
name="teams"
required
on:mdChange={onChange}
></md-multi-select>
<md-button variant="filled" type="submit">Save</md-button>
</form>| Event | Cancelable | Detail | Fires |
|---|---|---|---|
mdChange | no | string[] | The selection changed — carries the new full array |
mdRemove | no | string | A chip’s × removed one value |
mdClear | no | void | The clear affordance was used |
mdOpen | no | void | The dropdown opened |
mdClose | no | void | The dropdown closed |
mdValidityChange | no | { valid, validationMessage, flags } | Validity changed |
mdValidityChange is not composed — listen on the element itself.
mdOpen / mdClose are composed, so they also fire on an embedding shadow
host at AT_TARGET.
| Property | Attribute | Type | Default | Reflects |
|---|---|---|---|---|
valueMissingLabel | value-missing-label | string | 'Please select at least one option' | — |
reserveSupportingSpace | reserve-supporting-space | boolean | false | — |
variant | variant | 'filled' | 'outlined' | 'outlined' | Yes |
label | label | string | '' | — |
placeholder | placeholder | string | '' | — |
supportingText | supporting-text | string | '' | — |
error | error | boolean | false | Yes |
errorText | error-text | string | '' | — |
disabled | disabled | boolean | false | Yes |
softDisabled | soft-disabled | boolean | false | Yes |
required | required | boolean | false | Yes |
density | density | 0 | -1 | -2 | -3 | -4 | 0 | Yes |
options | options | SelectOptionInit[] | string | [] | — |
virtualize | virtualize | 'auto' | 'always' | 'never' | 'auto' | — |
filterable | filterable | boolean | false | — |
filterMode | filter-mode | FilterMode | 'substring' | — |
rowHeight | row-height | number | — | — |
value | JS only | string[] | [] | — |
maxSelected | max-selected | number | 0 | — |
showSelectAll | show-select-all | boolean | false | Yes |
selectAllLabel | select-all-label | string | 'Select all' | — |
placement | placement | 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'bottom-start' | — |
maxHeight | max-height | number | — | — |
matchTriggerWidth | match-trigger-width | boolean | true | Yes |
displayMode | display-mode | 'chips' | 'chips-inline' | 'count' | 'text' | 'chips' | Yes |
chipOverflow | chip-overflow | 'count' | 'wrap' | 'count' | Yes |
chipPosition | chip-position | 'bottom' | 'top' | 'left' | 'right' | 'bottom' | Yes |
trigger | trigger | 'field' | 'button' | 'field' | Yes |
triggerIcon | trigger-icon | string | 'add' | — |
triggerLabel | trigger-label | string | '' | — |
countFormatter | JS only | (count: number) => string | — | — |
searchPlaceholder | search-placeholder | string | 'Search…' | — |
filterLabel | filter-label | string | '' | — |
noResultsText | no-results-text | string | 'No results' | — |
noOptionsText | no-options-text | string | 'No options' | — |
searchingLabel | searching-label | string | 'Searching' | — |
loadingText | loading-text | string | 'Loading…' | — |
loading | loading | boolean | false | Yes |
clearable | clearable | boolean | false | Yes |
clearIcon | clear-icon | string | 'close' | — |
clearLabel | clear-label | string | 'Clear selection' | — |
dropdownIcon | dropdown-icon | string | 'arrow_drop_down' | — |
name | name | string | '' | Yes |
open | open | boolean | false | Yes |
| Method | Parameters |
|---|---|
show() | none |
close() | none |
focusTrigger() | none |
reset() | none |
loadOptions() | source: SelectOptionInit[] | OptionRowSource |
setQuery() | query: string |
getLabels() | values: string[] |
getValidity() | none |
checkValidity() | none |
reportValidity() | none |
setCustomValidity() | message: string |
| Slot | Description |
|---|---|
(default) | — |
trigger | — |
trigger-leading | — |
trigger-trailing | — |
loader | — |
dropdown-icon | — |
menu-header | — |
menu-loader | — |
Override on the host element for per-instance theming:
| Property | Description |
|---|---|
--md-multi-select-min-width | — |
--md-multi-select-chip-gap | — |
--md-multi-select-chip-radius | — |
--md-multi-select-caret-color | — |
--md-multi-select-clear-color | — |
--md-multi-select-option-icon-size | — |
--md-multi-select-width | — |
--md-multi-select-frame-gap | — |
--md-multi-select-trigger-width | — |
--md-multi-select-inline-chips-block-start | — |
--md-multi-select-chip-height | — |
--md-multi-select-chip-outline | — |
--md-multi-select-clear-size | — |
--md-multi-select-clear-bg | — |
--md-multi-select-clear-radius | — |
--md-multi-select-clear-icon-size | — |
--md-multi-select-clear-hover-bg | — |
--md-multi-select-clear-focus-ring-width | — |
--md-multi-select-clear-focus-ring-color | — |
--md-multi-select-clear-focus-ring-offset | — |
--md-multi-select-caret-size | — |
--md-multi-select-caret-box-size | — |
--md-multi-select-loader-size | — |
--md-multi-select-spinner-size | — |
--md-multi-select-loading-padding | — |
--md-multi-select-empty-padding | — |
--md-multi-select-empty-color | — |
--md-multi-select-empty-font | — |
--md-multi-select-select-all-divider-width | — |
--md-multi-select-select-all-divider-color | — |
--md-multi-select-option-icon-color | — |
--md-multi-select-search-padding | — |
--md-multi-select-search-color | — |
--md-multi-select-search-bg | — |
--md-multi-select-search-border-width | — |
--md-multi-select-search-border-color | — |
--md-multi-select-search-placeholder-color | — |
--md-multi-select-search-spinner-size | — |
Style internal elements through shadow DOM with ::part():
| Part | Description |
|---|---|
remove | — |
field | — |
loading-spinner | — |
clear | — |
caret-box | — |
caret | — |
field button | — |
button-desc | — |
chip | — |
chips | — |
overflow-chip | — |
listbox | — |
option-icon | — |
empty | — |
menu | — |
menu-header | — |
search-wrap | — |
search | — |
search-spinner | — |
select-all | — |
select-all-item | — |
loading-bar | — |
loading-progress | — |
frame | — |
live-region | — |
field-container | — |
field-input | — |
field-label | — |
chip-remove | — |
chip-label | — |
menu-surface | — |
empty-text | — |
label names the control. The menu is a managed listbox with a live-region
part, so selection changes are announced.Escape closes the menu and returns focus to the trigger.md-select, full combobox ARIA can’t be wired across the shadow
boundary — don’t attempt it from outside.supporting-text / error-text; a silent
rejection is invisible to screen-reader users.| Key | Action |
|---|---|
Enter / Space / ↓ | Open the menu from the trigger |
↑ / ↓ | Move between options |
Home / End | First / last option |
Enter / Space | Toggle the focused option — the menu stays open |
| A–Z | Typeahead, or types into the search box when filterable |
Escape | Close, returning focus to the trigger |
Backspace | On a focused chip, remove it |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Teams" supporting-text="Pick as many as you need" style="min-inline-size: 280px;">
<md-select-option value="eng" selected>Engineering</md-select-option>
<md-select-option value="des" selected>Design</md-select-option>
<md-select-option value="pm">Product</md-select-option>
<md-select-option value="ops" disabled>Operations</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Teams" supportingText="Pick as many as you need" style={{ minInlineSize: '280px' }}>
<MdSelectOption value="eng" selected>Engineering</MdSelectOption>
<MdSelectOption value="des" selected>Design</MdSelectOption>
<MdSelectOption value="pm">Product</MdSelectOption>
<MdSelectOption value="ops" disabled>Operations</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Teams" supporting-text="Pick as many as you need" style="min-inline-size: 280px;">
<md-select-option value="eng" selected>Engineering</md-select-option>
<md-select-option value="des" selected>Design</md-select-option>
<md-select-option value="pm">Product</md-select-option>
<md-select-option value="ops" disabled>Operations</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Teams" supporting-text="Pick as many as you need" style="min-inline-size: 280px;">
<md-select-option value="eng" selected>Engineering</md-select-option>
<md-select-option value="des" selected>Design</md-select-option>
<md-select-option value="pm">Product</md-select-option>
<md-select-option value="ops" disabled>Operations</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Teams" supporting-text="Pick as many as you need" style="min-inline-size: 280px;">
<md-select-option value="eng" selected>Engineering</md-select-option>
<md-select-option value="des" selected>Design</md-select-option>
<md-select-option value="pm">Product</md-select-option>
<md-select-option value="ops" disabled>Operations</md-select-option>
</md-multi-select>RTL — field, chips, caret and menu mirror under dir="rtl". placement is
logical; chip-position="left" / "right" is physical, so re-check it per
direction. See RTL.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start;">
<div dir="ltr"><md-multi-select label="Teams" style="min-inline-size: 240px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option><md-select-option value="c">Product</md-select-option></md-multi-select></div>
<div dir="rtl"><md-multi-select label="الفرق" style="min-inline-size: 240px;"><md-select-option value="a" selected>الهندسة</md-select-option><md-select-option value="b" selected>التصميم</md-select-option><md-select-option value="c">المنتج</md-select-option></md-multi-select></div>
</div>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<div style={{ display: 'flex', gap: '24px', flexWrap: 'wrap', alignItems: 'flex-start' }}>
<div dir="ltr"><MdMultiSelect label="Teams" style={{ minInlineSize: '240px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption><MdSelectOption value="c">Product</MdSelectOption></MdMultiSelect></div>
<div dir="rtl"><MdMultiSelect label="الفرق" style={{ minInlineSize: '240px' }}><MdSelectOption value="a" selected>الهندسة</MdSelectOption><MdSelectOption value="b" selected>التصميم</MdSelectOption><MdSelectOption value="c">المنتج</MdSelectOption></MdMultiSelect></div>
</div>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start;">
<div dir="ltr"><md-multi-select label="Teams" style="min-inline-size: 240px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option><md-select-option value="c">Product</md-select-option></md-multi-select></div>
<div dir="rtl"><md-multi-select label="الفرق" style="min-inline-size: 240px;"><md-select-option value="a" selected>الهندسة</md-select-option><md-select-option value="b" selected>التصميم</md-select-option><md-select-option value="c">المنتج</md-select-option></md-multi-select></div>
</div><script setup>
import '@awc-ui/core/define';
</script>
<template>
<div style="display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start;">
<div dir="ltr"><md-multi-select label="Teams" style="min-inline-size: 240px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option><md-select-option value="c">Product</md-select-option></md-multi-select></div>
<div dir="rtl"><md-multi-select label="الفرق" style="min-inline-size: 240px;"><md-select-option value="a" selected>الهندسة</md-select-option><md-select-option value="b" selected>التصميم</md-select-option><md-select-option value="c">المنتج</md-select-option></md-multi-select></div>
</div>
</template><script>
import '@awc-ui/core/define';
</script>
<div style="display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start;">
<div dir="ltr"><md-multi-select label="Teams" style="min-inline-size: 240px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option><md-select-option value="c">Product</md-select-option></md-multi-select></div>
<div dir="rtl"><md-multi-select label="الفرق" style="min-inline-size: 240px;"><md-select-option value="a" selected>الهندسة</md-select-option><md-select-option value="b" selected>التصميم</md-select-option><md-select-option value="c">المنتج</md-select-option></md-multi-select></div>
</div>Density — density="-1…-4" compacts trigger, chips and menu rows together.
See Density.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start;">
<md-multi-select density="0" label="0" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-1" label="-1" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-2" label="-2" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-3" label="-3" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-4" label="-4" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
</div>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap', alignItems: 'flex-start' }}>
<MdMultiSelect density="0" label="0" style={{ minInlineSize: '200px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption></MdMultiSelect>
<MdMultiSelect density="-1" label="-1" style={{ minInlineSize: '200px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption></MdMultiSelect>
<MdMultiSelect density="-2" label="-2" style={{ minInlineSize: '200px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption></MdMultiSelect>
<MdMultiSelect density="-3" label="-3" style={{ minInlineSize: '200px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption></MdMultiSelect>
<MdMultiSelect density="-4" label="-4" style={{ minInlineSize: '200px' }}><MdSelectOption value="a" selected>Engineering</MdSelectOption><MdSelectOption value="b" selected>Design</MdSelectOption></MdMultiSelect>
</div>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start;">
<md-multi-select density="0" label="0" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-1" label="-1" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-2" label="-2" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-3" label="-3" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-4" label="-4" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
</div><script setup>
import '@awc-ui/core/define';
</script>
<template>
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start;">
<md-multi-select density="0" label="0" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-1" label="-1" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-2" label="-2" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-3" label="-3" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-4" label="-4" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
</div>
</template><script>
import '@awc-ui/core/define';
</script>
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start;">
<md-multi-select density="0" label="0" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-1" label="-1" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-2" label="-2" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-3" label="-3" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
<md-multi-select density="-4" label="-4" style="min-inline-size: 200px;"><md-select-option value="a" selected>Engineering</md-select-option><md-select-option value="b" selected>Design</md-select-option></md-multi-select>
</div>i18n — translate label, placeholder, supporting-text, error-text,
select-all-label, search-placeholder, filter-label, no-results-text,
no-options-text, clear-label, searching-label, loading-text,
trigger-label and value-missing-label — they all default to English — and
make countFormatter pluralization-aware.
| Custom property | Purpose |
|---|---|
--md-multi-select-width / --md-multi-select-min-width | Trigger width |
--md-multi-select-trigger-width | Button-trigger width |
--md-multi-select-chip-gap / -chip-height / -chip-radius / -chip-outline | Chip metrics |
--md-multi-select-inline-chips-block-start | Inline-chip offset |
--md-multi-select-caret-color / --md-multi-select-clear-color / -clear-size | Trailing controls |
--md-multi-select-option-icon-size | Option row icons |
--md-multi-select-search-bg | In-menu search background |
--md-multi-select-select-all-divider-color | Select-all separator |
--md-multi-select-empty-color | Empty-state text |
--md-multi-select-frame-gap | Field / chips spacing |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Themed" style="--md-multi-select-min-width: 280px; --md-multi-select-chip-gap: 10px; --md-multi-select-chip-radius: 4px; --md-multi-select-caret-color: var(--md-sys-color-primary);">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Themed" style={{ '--md-multi-select-min-width': '280px', '--md-multi-select-chip-gap': '10px', '--md-multi-select-chip-radius': '4px', '--md-multi-select-caret-color': 'var(--md-sys-color-primary)' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Themed" style="--md-multi-select-min-width: 280px; --md-multi-select-chip-gap: 10px; --md-multi-select-chip-radius: 4px; --md-multi-select-caret-color: var(--md-sys-color-primary);">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Themed" style="--md-multi-select-min-width: 280px; --md-multi-select-chip-gap: 10px; --md-multi-select-chip-radius: 4px; --md-multi-select-caret-color: var(--md-sys-color-primary);">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Themed" style="--md-multi-select-min-width: 280px; --md-multi-select-chip-gap: 10px; --md-multi-select-chip-radius: 4px; --md-multi-select-caret-color: var(--md-sys-color-primary);">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
</md-multi-select>Every default resolves through an md-sys-color role, so a control that sets no
custom properties follows the theme on its own:
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-multi-select label="Untouched defaults" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdMultiSelect label="Untouched defaults" style={{ minInlineSize: '280px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Product</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-multi-select label="Untouched defaults" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-multi-select label="Untouched defaults" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<md-multi-select label="Untouched defaults" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>| Part | Element |
|---|---|
field / button | The field trigger, or the button trigger |
frame | Field-plus-chips wrapper |
chips / chip / overflow-chip / remove | The chip row, each chip, the “+N” chip, a chip’s remove affordance |
caret / caret-box / clear | Trailing controls |
menu / menu-header / listbox | The popup, its header, the option list |
search | In-menu search field |
select-all / select-all-item | Select-all row and its option |
option-icon | Per-option icon |
empty | No-results / no-options text |
loading-bar / loading-progress | Async loading indicator |
live-region | The announcement region |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<style>
.parts-ms::part(chip) { border-radius: 4px; }
.parts-ms::part(caret) { color: var(--md-sys-color-primary); }
.parts-ms::part(chips) { gap: 10px; }
</style>
<md-multi-select class="parts-ms" label="Styled parts" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>import { MdMultiSelect, MdSelectOption } from '@awc-ui/react';
export function Demo() {
return (
<>
<style>
.parts-ms::part(chip) { border-radius: 4px; }
.parts-ms::part(caret) { color: var(--md-sys-color-primary); }
.parts-ms::part(chips) { gap: 10px; }
</style>
<MdMultiSelect className="parts-ms" label="Styled parts" style={{ minInlineSize: '280px' }}>
<MdSelectOption value="a" selected>Engineering</MdSelectOption>
<MdSelectOption value="b" selected>Design</MdSelectOption>
<MdSelectOption value="c">Product</MdSelectOption>
</MdMultiSelect>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<style>
.parts-ms::part(chip) { border-radius: 4px; }
.parts-ms::part(caret) { color: var(--md-sys-color-primary); }
.parts-ms::part(chips) { gap: 10px; }
</style>
<md-multi-select class="parts-ms" label="Styled parts" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select><script setup>
import '@awc-ui/core/define';
</script>
<template>
<style>
.parts-ms::part(chip) { border-radius: 4px; }
.parts-ms::part(caret) { color: var(--md-sys-color-primary); }
.parts-ms::part(chips) { gap: 10px; }
</style>
<md-multi-select class="parts-ms" label="Styled parts" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>
</template><script>
import '@awc-ui/core/define';
</script>
<style>
.parts-ms::part(chip) { border-radius: 4px; }
.parts-ms::part(caret) { color: var(--md-sys-color-primary); }
.parts-ms::part(chips) { gap: 10px; }
</style>
<md-multi-select class="parts-ms" label="Styled parts" style="min-inline-size: 280px;">
<md-select-option value="a" selected>Engineering</md-select-option>
<md-select-option value="b" selected>Design</md-select-option>
<md-select-option value="c">Product</md-select-option>
</md-multi-select>md-select ·
md-select-option ·
md-transfer-list ·
md-autocomplete ·
md-checkbox ·
md-chip ·
md-menu ·
md-text-field
md-multi-selectTwo artefacts to give your AI agent so it generates correct UI with this component. The per-component spec answers "how do I use this exact tag?". The main-llm spec answers "which tag should I pick in the first place?".
md-multi-select spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
System-prompt preamble · decision matrix · token reference · page recipes · anti-patterns. Paste into the system prompt at the start of a piece of work.