diff --git a/change/@fluentui-web-components-39809c10-c214-4e43-b550-a3f303e597d0.json b/change/@fluentui-web-components-39809c10-c214-4e43-b550-a3f303e597d0.json
new file mode 100644
index 00000000000000..9d833897e12907
--- /dev/null
+++ b/change/@fluentui-web-components-39809c10-c214-4e43-b550-a3f303e597d0.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "feat(web-components): generate SSR templates and stylesheets into src/ and copy into dist during compile",
+ "packageName": "@fluentui/web-components",
+ "email": "863023+radium-v@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/package.json b/package.json
index 9c279de29feb4a..37b3c5891bccc2 100644
--- a/package.json
+++ b/package.json
@@ -72,10 +72,10 @@
"@microsoft/api-extractor": "7.51.0",
"@microsoft/api-extractor-model": "7.31.2",
"@microsoft/eslint-plugin-sdl": "1.0.1",
- "@microsoft/fast-build": "0.6.0",
+ "@microsoft/fast-build": "0.7.0",
"@microsoft/fast-element": "2.10.4",
- "@microsoft/fast-html": "1.0.0-alpha.53",
- "@microsoft/fast-test-harness": "0.3.0",
+ "@microsoft/fast-html": "1.0.0-alpha.54",
+ "@microsoft/fast-test-harness": "0.3.1",
"@microsoft/focusgroup-polyfill": "1.5.0",
"@microsoft/load-themed-styles": "1.10.26",
"@microsoft/loader-load-themed-styles": "2.0.17",
diff --git a/packages/web-components/README.md b/packages/web-components/README.md
index 5945f3d08569ae..51f206621085c6 100644
--- a/packages/web-components/README.md
+++ b/packages/web-components/README.md
@@ -88,6 +88,24 @@ import CEM from '@fluentui/custom-elements.json' with { type: 'json' };
To start the component development environment, run `yarn start`.
+### SSR templates and stylesheets
+
+Each component ships a declarative-shadow-DOM template (`*.template.html`) and an extracted stylesheet (`*.styles.css`) next to its `*.template.ts` and `*.styles.ts` sources. These files are generated from the TypeScript sources and committed to the repo so the DSD output is visible without running a build.
+
+After editing a `*.template.ts` or `*.styles.ts`, regenerate the matching HTML and CSS with:
+
+```sh
+yarn generate:ssr
+```
+
+To check that the committed files match what the generators would produce (for example, before opening a PR), run:
+
+```sh
+yarn check:ssr
+```
+
+`yarn compile` does not regenerate these files; it copies them from `src/` into `dist/esm/` alongside the compiled JS.
+
### Known issue with Storybook site hot-reloading during development
Storybook will watch modules for changes and hot-reload the module when necessary. This is usually great but poses a problem when the module being hot-reloaded defines a custom element. A custom element name can only be defined by the `CustomElementsRegistry` once, so reloading a module that defines a custom element will attempt to re-register the custom element name, throwing an error because the name has already been defined. This error will manifest with the following message:
diff --git a/packages/web-components/package.json b/packages/web-components/package.json
index cdaab2491138db..14f6d52ca4693d 100644
--- a/packages/web-components/package.json
+++ b/packages/web-components/package.json
@@ -79,11 +79,10 @@
"compile:benchmark": "rollup -c rollup.bench.js",
"clean": "node ./scripts/clean dist",
"generate-api": "api-extractor run --local",
- "build": "yarn compile && yarn build:rollup && yarn build:ssr && yarn generate-api && yarn analyze",
- "build:ssr:templates": "fast-test-harness generate-templates --tag-prefix=fluent",
- "build:ssr:styles": "fast-test-harness generate-stylesheets",
- "build:ssr": "yarn build:ssr:templates && yarn build:ssr:styles",
+ "build": "yarn compile && yarn build:rollup && yarn generate-api && yarn analyze",
"build:rollup": "rollup -c",
+ "generate:ssr": "node ./scripts/generate-ssr.js",
+ "check:ssr": "node ./scripts/generate-ssr.js --check",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"format": "prettier -w src/**/*.{ts,html} src/*.{ts,html} --ignore-path ../../.prettierignore",
diff --git a/packages/web-components/scripts/compile.js b/packages/web-components/scripts/compile.js
index b57091b02a0f73..162ff7e79a898f 100644
--- a/packages/web-components/scripts/compile.js
+++ b/packages/web-components/scripts/compile.js
@@ -1,27 +1,47 @@
/* eslint-disable no-undef */
-import { execSync } from 'child_process';
-import chalk from 'chalk';
-
-main();
+import { execSync } from 'node:child_process';
+import { cp, glob, mkdir } from 'node:fs/promises';
+import { dirname, join } from 'node:path';
-function compile() {
- try {
- console.log(chalk.bold(`🎬 compile:start`));
+import chalk from 'chalk';
- console.log(chalk.blueBright(`compile: generating design tokens`));
- execSync(`node ./scripts/generate-tokens`, { stdio: 'inherit' });
+const SRC = 'src';
+const OUT = 'dist/esm';
- console.log(chalk.blueBright(`compile: running tsc`));
- execSync(`tsc -p tsconfig.lib.json --rootDir ./src --baseUrl .`, { stdio: 'inherit' });
+async function copySsrAssets() {
+ const patterns = ['**/*.template.html', '**/*.styles.css'];
+ let count = 0;
- console.log(chalk.bold(`🏁 compile:end`));
- } catch (err) {
- console.error(err);
- process.exit(1);
+ for (const pattern of patterns) {
+ for await (const file of glob(pattern, { cwd: SRC })) {
+ const from = join(SRC, file);
+ const to = join(OUT, file);
+ await mkdir(dirname(to), { recursive: true });
+ await cp(from, to);
+ count++;
+ }
}
+
+ console.log(chalk.dim(`compile: copied ${count} SSR asset${count === 1 ? '' : 's'} from ${SRC}/ → ${OUT}/`));
}
-function main() {
- compile();
+async function compile() {
+ console.log(chalk.bold(`🎬 compile:start`));
+
+ console.log(chalk.blueBright(`compile: generating design tokens`));
+ execSync(`node ./scripts/generate-tokens`, { stdio: 'inherit' });
+
+ console.log(chalk.blueBright(`compile: running tsc`));
+ execSync(`tsc -p tsconfig.lib.json --rootDir ./src --baseUrl .`, { stdio: 'inherit' });
+
+ console.log(chalk.blueBright(`compile: copying SSR assets`));
+ await copySsrAssets();
+
+ console.log(chalk.bold(`🏁 compile:end`));
}
+
+compile().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/packages/web-components/scripts/generate-ssr.js b/packages/web-components/scripts/generate-ssr.js
new file mode 100644
index 00000000000000..eb388fa7b21f50
--- /dev/null
+++ b/packages/web-components/scripts/generate-ssr.js
@@ -0,0 +1,219 @@
+/* eslint-disable no-undef */
+
+/**
+ * Regenerates SSR template HTML and stylesheet CSS files next to their
+ * source `.template.ts` / `.styles.ts` counterparts in `src/`.
+ *
+ * Flow:
+ * 1. Compile `src/` to a throwaway temp dir so we have JS modules with
+ * runtime metadata for the generators to walk.
+ * 2. Run `generate-templates` and `generate-stylesheets` from the
+ * `@microsoft/fast-test-harness` library, writing back into `src/`
+ * while preserving the per-component subdirectory structure.
+ *
+ * The generated files should be committed to the repo; the normal `compile` script
+ * copies them into `dist/esm/`.
+ *
+ * Running this script is only necessary when making changes to the source `.template.ts` or `.styles.ts` files,
+ * and should be part of the development workflow when working on those files. The generated files can then
+ * be modified as needed for SSR purposes, and those modifications should also be committed to the repo.
+ *
+ * Pass `--check` to compare what regeneration would produce against the
+ * current working tree without writing. Each output file is classified
+ * against the matrix of (TS@HEAD vs TS@working) × (HTML@HEAD vs
+ * HTML@working) × (regen output vs disk). Exits non-zero when any
+ * stale, hand-edited, or conflicting files are detected.
+ */
+
+import { execSync } from 'node:child_process';
+import { mkdirSync, mkdtempSync, rmSync } from 'node:fs';
+import { glob, readFile } from 'node:fs/promises';
+import { join, relative } from 'node:path';
+
+import chalk from 'chalk';
+import prettier from 'prettier';
+
+import { generateStylesheets } from '@microsoft/fast-test-harness/build/generate-stylesheets.js';
+import { generateFTemplates } from '@microsoft/fast-test-harness/build/generate-templates.js';
+
+const cwd = process.cwd();
+const TEMP_PARENT = join(cwd, 'temp');
+const checkMode = process.argv.includes('--check');
+const label = checkMode ? 'generate:ssr:check' : 'generate:ssr';
+
+async function main() {
+ mkdirSync(TEMP_PARENT, { recursive: true });
+ const tempDir = mkdtempSync(join(TEMP_PARENT, 'ssr-'));
+ const stagingDir = checkMode ? mkdtempSync(join(TEMP_PARENT, 'ssr-staging-')) : null;
+ const prettierConfig = (await prettier.resolveConfig(cwd)) ?? {};
+ const outDir = stagingDir ? relative(cwd, stagingDir) : 'src';
+ let exitCode = 0;
+
+ try {
+ console.log(chalk.bold(`🎬 ${label} start`));
+
+ console.log(chalk.blueBright(`${label}: compiling src → ${tempDir}`));
+ execSync(`tsc -p tsconfig.lib.json --rootDir ./src --baseUrl . --outDir ${tempDir} --declaration false`, {
+ stdio: 'inherit',
+ });
+
+ console.log(chalk.blueBright(`${label}: writing *.template.html → ${outDir}/`));
+ await generateFTemplates({
+ cwd,
+ distDir: tempDir,
+ outDir,
+ tagPrefix: 'fluent',
+ format: content =>
+ prettier.format(content, { ...prettierConfig, parser: 'html', htmlWhitespaceSensitivity: 'ignore' }),
+ });
+
+ console.log(chalk.blueBright(`${label}: writing *.styles.css → ${outDir}/`));
+ await generateStylesheets({
+ cwd,
+ distDir: tempDir,
+ outDir,
+ format: content => prettier.format(content, { ...prettierConfig, parser: 'css' }),
+ });
+
+ if (checkMode) {
+ const result = await classify(stagingDir);
+ printSummary(result);
+ if (result.stale.length || result.handEdited.length || result.conflicts.length) {
+ exitCode = 1;
+ }
+ }
+
+ console.log(chalk.bold(`🏁 ${label} end`));
+ } finally {
+ rmSync(tempDir, { recursive: true, force: true });
+ if (stagingDir) rmSync(stagingDir, { recursive: true, force: true });
+ }
+
+ if (exitCode) process.exit(exitCode);
+}
+
+/**
+ * Classify each staged file against the working tree using the
+ * four-state matrix. Returns counts plus per-bucket file lists.
+ *
+ * - `unchanged` — regen produces the file already on disk
+ * - `created` — no committed baseline for this HTML/CSS
+ * - `updated` — TS changed; regen produces new HTML/CSS (normal flow)
+ * - `stale` — TS and HTML both at HEAD, but regen disagrees with disk
+ * (committed state is out of sync — CI failure signal)
+ * - `handEdited` — HTML differs from HEAD with no TS change; regen would clobber
+ * - `conflicts` — both TS and HTML differ from HEAD, and regen disagrees with disk
+ */
+async function classify(stagingDir) {
+ const dirtyMap = buildDirtyMap();
+ // git status --porcelain paths are relative to the repo root; lookups
+ // need to be prefixed with the path from repo root to cwd.
+ const repoPrefix = execSync('git rev-parse --show-prefix', { cwd, encoding: 'utf8' }).trim();
+ const dirtyStatus = path => statusOf(dirtyMap.get(repoPrefix + path));
+ const result = {
+ unchanged: [],
+ created: [],
+ updated: [],
+ stale: [],
+ handEdited: [],
+ conflicts: [],
+ };
+
+ for (const pattern of ['**/*.template.html', '**/*.styles.css']) {
+ for await (const file of glob(pattern, { cwd: stagingDir })) {
+ const stagedAbs = join(stagingDir, file);
+ const srcHtmlAbs = join(cwd, 'src', file);
+ const srcHtmlRel = join('src', file);
+
+ let srcTsRel;
+ if (file.endsWith('.template.html')) {
+ srcTsRel = join('src', file.replace(/\.template\.html$/, '.template.ts'));
+ } else if (file.endsWith('.styles.css')) {
+ srcTsRel = join('src', file.replace(/\.styles\.css$/, '.styles.ts'));
+ } else {
+ continue;
+ }
+
+ const tsStatus = dirtyStatus(srcTsRel);
+ const htmlStatus = dirtyStatus(srcHtmlRel);
+ const newHtml = await readFile(stagedAbs, 'utf8');
+ const onDiskHtml = await readFile(srcHtmlAbs, 'utf8').catch(() => null);
+
+ if (newHtml === onDiskHtml) {
+ result.unchanged.push(file);
+ continue;
+ }
+
+ if (htmlStatus === 'new') {
+ result.created.push(file);
+ continue;
+ }
+
+ if (htmlStatus === 'same') {
+ if (tsStatus === 'same') {
+ result.stale.push(file);
+ } else {
+ result.updated.push(file);
+ }
+ continue;
+ }
+
+ // htmlStatus === 'changed'
+ if (tsStatus === 'same') {
+ result.handEdited.push(file);
+ } else {
+ result.conflicts.push(file);
+ }
+ }
+ }
+
+ return result;
+}
+
+/**
+ * One git invocation that returns a map of {pathRelativeToCwd → status code}
+ * for every file that differs from HEAD (modified, added, untracked, etc.).
+ * Tracked files in sync with HEAD are absent from the map.
+ */
+function buildDirtyMap() {
+ const map = new Map();
+ const output = execSync('git status --porcelain=v1 -uall', { cwd, encoding: 'utf8' });
+ for (const line of output.split('\n')) {
+ if (!line) continue;
+ const code = line.slice(0, 2);
+ let path = line.slice(3);
+ if (path.startsWith('"')) path = JSON.parse(path);
+ const arrow = path.indexOf(' -> '); // rename: "old -> new"
+ if (arrow !== -1) path = path.slice(arrow + 4);
+ map.set(path, code);
+ }
+ return map;
+}
+
+function statusOf(code) {
+ if (!code) return 'same';
+ if (code[0] === '?' || code[0] === 'A') return 'new';
+ return 'changed';
+}
+
+function printSummary({ unchanged, created, updated, stale, handEdited, conflicts }) {
+ console.log(chalk.bold(`\n${label} summary:`));
+ console.log(chalk.green(` ✓ ${unchanged.length} unchanged`));
+ printBucket(chalk.cyan, '+', created, 'new (no committed baseline)');
+ printBucket(chalk.blue, '✎', updated, 'would update (TS changed)');
+ printBucket(chalk.yellow, '!', stale, 'stale (committed HTML out of sync with committed TS)');
+ printBucket(chalk.yellow, '⚠', handEdited, 'hand-edited (HTML differs from HEAD, TS unchanged)');
+ printBucket(chalk.red, '✘', conflicts, 'conflicts (TS and HTML both differ from HEAD, regen disagrees with disk)');
+ console.log('');
+}
+
+function printBucket(color, glyph, files, description) {
+ if (files.length === 0) return;
+ console.log(color(` ${glyph} ${files.length} ${description}`));
+ for (const f of files) console.log(chalk.dim(` ${f}`));
+}
+
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/packages/web-components/src/accordion-item/accordion-item.styles.css b/packages/web-components/src/accordion-item/accordion-item.styles.css
new file mode 100644
index 00000000000000..f153a1bc1ce27a
--- /dev/null
+++ b/packages/web-components/src/accordion-item/accordion-item.styles.css
@@ -0,0 +1,174 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ max-width: fit-content;
+ contain: content;
+}
+
+.heading {
+ height: 44px;
+ display: grid;
+ position: relative;
+ padding-inline: var(--spacingHorizontalM) var(--spacingHorizontalMNudge);
+ border-radius: var(--borderRadiusMedium);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase300);
+ grid-template-columns: auto auto 1fr auto;
+}
+
+.button {
+ appearance: none;
+ background: var(--colorTransparentBackground);
+ border: none;
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground1);
+ cursor: pointer;
+ font: inherit;
+ grid-column: auto / span 2;
+ grid-row: 1;
+ height: 44px;
+ outline: none;
+ padding: 0;
+ text-align: start;
+}
+
+.button::before {
+ content: '';
+ position: absolute;
+ inset: 0px;
+ cursor: pointer;
+ border-radius: var(--borderRadiusSmall);
+}
+
+:where(.default-marker-collapsed, .default-marker-expanded),
+::slotted(:is([slot='marker-collapsed'], [slot='marker-expanded'])) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ pointer-events: none;
+ position: relative;
+ height: 100%;
+ padding-inline-end: var(--spacingHorizontalS);
+ grid-column: 1 / span 1;
+ grid-row: 1;
+}
+
+.content {
+ margin: 0 var(--spacingHorizontalM);
+}
+
+::slotted([slot='start']) {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding-right: var(--spacingHorizontalS);
+ grid-column: 2 / span 1;
+ grid-row: 1;
+}
+
+button:focus-visible::after {
+ content: '';
+ position: absolute;
+ inset: 0px;
+ cursor: pointer;
+ border-radius: var(--borderRadiusSmall);
+ outline: none;
+ border: 2px solid var(--colorStrokeFocus1);
+ box-shadow: inset 0 0 0 1px var(--colorStrokeFocus2);
+}
+
+/* --- Disabled attr styles --- */
+
+:host([disabled]) .button {
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([disabled]) svg {
+ filter: invert(89%) sepia(0%) saturate(569%) hue-rotate(155deg) brightness(88%) contrast(87%);
+}
+
+/* --- Expanded attr styles --- */
+
+:host([expanded]) .content {
+ display: block;
+}
+
+:host([expanded]) .default-marker-collapsed,
+:host([expanded]) ::slotted([slot='marker-collapsed']),
+:host(:not([expanded])) :is(.default-marker-expanded, .content),
+:host(:not([expanded])) ::slotted([slot='marker-expanded']) {
+ display: none;
+}
+
+:host([expanded]) ::slotted([slot='marker-expanded']),
+:host(:not([expanded])) ::slotted([slot='marker-collapsed']) {
+ display: flex;
+}
+
+/* --- Appearance attr styles --- */
+
+.heading {
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+}
+
+:host([size='small']) .heading {
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+}
+
+:host([size='large']) .heading {
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='extra-large']) .heading {
+ font-size: var(--fontSizeBase500);
+ line-height: var(--lineHeightBase500);
+}
+
+/* --- marker-position attr styles --- */
+
+:host([marker-position='end']) ::slotted([slot='start']) {
+ grid-column: 1 / span 1;
+}
+
+:host([marker-position='end']) :is(.default-marker-collapsed, .default-marker-expanded) {
+ grid-column: 4 / span 1;
+ padding-inline-start: var(--spacingHorizontalS);
+ padding-inline-end: 0;
+}
+
+:host([marker-position='end']) .button {
+ grid-column: 2 / span 3;
+}
+
+/* --- Block attr styles --- */
+
+:host([block]) {
+ max-width: 100%;
+}
+
+:host([marker-position='end']) .heading {
+ grid-template-columns: auto auto 28px;
+ padding-inline: var(--spacingHorizontalM);
+}
+
+:host([marker-position='end']:has([slot='start'])) .heading {
+ padding-inline: var(--spacingHorizontalMNudge) var(--spacingHorizontalM);
+}
+
+:host([block][marker-position='end']) .heading {
+ grid-template-columns: auto 1fr;
+}
+
+:host([marker-position='end']) :is(.default-marker-collapsed, .default-marker-expanded) {
+ grid-column: 5 / span 1;
+}
diff --git a/packages/web-components/src/accordion-item/accordion-item.template.html b/packages/web-components/src/accordion-item/accordion-item.template.html
new file mode 100644
index 00000000000000..092f2a3ebb2241
--- /dev/null
+++ b/packages/web-components/src/accordion-item/accordion-item.template.html
@@ -0,0 +1,54 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/accordion/accordion.styles.css b/packages/web-components/src/accordion/accordion.styles.css
new file mode 100644
index 00000000000000..ebc048c03ece28
--- /dev/null
+++ b/packages/web-components/src/accordion/accordion.styles.css
@@ -0,0 +1,12 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: flex;
+}
+
+:host {
+ flex-direction: column;
+ width: 100%;
+ contain: content;
+}
diff --git a/packages/web-components/src/accordion/accordion.template.html b/packages/web-components/src/accordion/accordion.template.html
new file mode 100644
index 00000000000000..52563ec8181b50
--- /dev/null
+++ b/packages/web-components/src/accordion/accordion.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/anchor-button/anchor-button.styles.css b/packages/web-components/src/anchor-button/anchor-button.styles.css
new file mode 100644
index 00000000000000..072fbff48f853b
--- /dev/null
+++ b/packages/web-components/src/anchor-button/anchor-button.styles.css
@@ -0,0 +1,226 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --icon-spacing: var(--spacingHorizontalSNudge);
+ position: relative;
+ contain: layout style;
+ vertical-align: middle;
+ align-items: center;
+ box-sizing: border-box;
+ justify-content: center;
+ text-align: center;
+ text-decoration-line: none;
+ margin: 0;
+ min-height: 32px;
+ outline-style: none;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ padding: 0 var(--spacingHorizontalM);
+ min-width: 96px;
+ border-radius: var(--borderRadiusMedium);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ line-height: var(--lineHeightBase300);
+ transition-duration: var(--durationFaster);
+ transition-property: background, border, color;
+ transition-timing-function: var(--curveEasyEase);
+ cursor: pointer;
+ user-select: none;
+}
+
+.content {
+ display: inherit;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground1Hover);
+ border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:hover:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ border-color: var(--colorNeutralStroke1Pressed);
+ color: var(--colorNeutralForeground1Pressed);
+ outline-style: none;
+}
+
+:host(:focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host {
+ transition-duration: 0.01ms;
+ }
+}
+
+::slotted(svg) {
+ font-size: 20px;
+ height: 20px;
+ width: 20px;
+ fill: currentColor;
+}
+
+::slotted([slot='start']) {
+ margin-inline-end: var(--icon-spacing);
+}
+
+::slotted([slot='end']),
+[slot='end'] {
+ flex-shrink: 0;
+ margin-inline-start: var(--icon-spacing);
+}
+
+:host([icon-only]) {
+ min-width: 32px;
+ max-width: 32px;
+}
+
+:host([size='small']) {
+ --icon-spacing: var(--spacingHorizontalXS);
+ min-height: 24px;
+ min-width: 64px;
+ padding: 0 var(--spacingHorizontalS);
+ border-radius: var(--borderRadiusSmall);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small'][icon-only]) {
+ min-width: 24px;
+ max-width: 24px;
+}
+
+:host([size='large']) {
+ min-height: 40px;
+ border-radius: var(--borderRadiusLarge);
+ padding: 0 var(--spacingHorizontalL);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large'][icon-only]) {
+ min-width: 40px;
+ max-width: 40px;
+}
+
+:host([size='large']) ::slotted(svg) {
+ font-size: 24px;
+ height: 24px;
+ width: 24px;
+}
+
+:host(:is([shape='circular'], [shape='circular']:focus-visible)) {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:is([shape='square'], [shape='square']:focus-visible)) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='primary']) {
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ border-color: transparent;
+}
+
+:host([appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host([appearance='primary']:is(:hover, :hover:active):not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host([appearance='primary']:is(:hover, :hover:active)) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([appearance='primary']:hover:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host([appearance='primary']:focus-visible) {
+ border-color: var(--colorNeutralForegroundOnBrand);
+ box-shadow: var(--shadow2), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+:host([appearance='outline']) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='outline']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='outline']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='subtle']) {
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='subtle']:hover:active) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host([appearance='transparent']) {
+ background-color: var(--colorTransparentBackground);
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is([appearance='transparent'], [appearance='transparent']:is(:hover, :active))) {
+ border-color: transparent;
+}
+
+::slotted(a) {
+ position: absolute;
+ inset: 0;
+}
+
+@media (forced-colors: active) {
+ :host {
+ border-color: LinkText;
+ color: LinkText;
+ }
+}
diff --git a/packages/web-components/src/anchor-button/anchor-button.template.html b/packages/web-components/src/anchor-button/anchor-button.template.html
new file mode 100644
index 00000000000000..4047a190152bb8
--- /dev/null
+++ b/packages/web-components/src/anchor-button/anchor-button.template.html
@@ -0,0 +1,10 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/avatar/avatar.styles.css b/packages/web-components/src/avatar/avatar.styles.css
new file mode 100644
index 00000000000000..1affb564412a46
--- /dev/null
+++ b/packages/web-components/src/avatar/avatar.styles.css
@@ -0,0 +1,480 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-grid;
+}
+:host {
+ position: relative;
+ place-items: center;
+ place-content: center;
+ grid-template: 1fr / 1fr;
+ flex-shrink: 0;
+ width: 32px;
+ height: 32px;
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ font-size: var(--fontSizeBase300);
+ border-radius: var(--borderRadiusCircular);
+ color: var(--colorNeutralForeground3);
+ background-color: var(--colorNeutralBackground6);
+ contain: layout style;
+}
+
+.monogram,
+.default-icon {
+ grid-area: 1 / 1 / -1 / -1;
+}
+
+.monogram:empty {
+ display: none;
+}
+
+.default-slot:is(.has-slotted, :has-slotted) ~ .default-icon,
+.default-slot:is(.has-slotted, :has-slotted) ~ .monogram,
+:host(:is([name]):not([name=''])) .default-icon,
+:host(:is([initials]):not([initials=''])) .default-icon {
+ display: none;
+}
+
+.default-icon,
+::slotted(svg) {
+ width: 20px;
+ height: 20px;
+ font-size: 20px;
+}
+
+::slotted(img) {
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ border-radius: var(--borderRadiusCircular);
+}
+
+::slotted([slot='badge']) {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ box-shadow: 0 0 0 var(--strokeWidthThin) var(--colorNeutralBackground1);
+}
+
+:host([size='64']) ::slotted([slot='badge']),
+:host([size='72']) ::slotted([slot='badge']),
+:host([size='96']) ::slotted([slot='badge']),
+:host([size='120']) ::slotted([slot='badge']),
+:host([size='128']) ::slotted([slot='badge']) {
+ box-shadow: 0 0 0 var(--strokeWidthThick) var(--colorNeutralBackground1);
+}
+
+:host([size='16']),
+:host([size='20']),
+:host([size='24']) {
+ font-size: var(--fontSizeBase100);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='16']) {
+ width: 16px;
+ height: 16px;
+}
+
+:host([size='20']) {
+ width: 20px;
+ height: 20px;
+}
+
+:host([size='24']) {
+ width: 24px;
+ height: 24px;
+}
+
+:host([size='16']) .default-icon,
+:host([size='16']) ::slotted(svg) {
+ width: 12px;
+ height: 12px;
+ font-size: 12px;
+}
+
+:host([size='20']) .default-icon,
+:host([size='24']) .default-icon,
+:host([size='20']) ::slotted(svg),
+:host([size='24']) ::slotted(svg) {
+ width: 16px;
+ height: 16px;
+ font-size: 16px;
+}
+
+:host([size='28']) {
+ width: 28px;
+ height: 28px;
+ font-size: var(--fontSizeBase200);
+}
+
+:host([size='36']) {
+ width: 36px;
+ height: 36px;
+}
+
+:host([size='40']) {
+ width: 40px;
+ height: 40px;
+}
+
+:host([size='48']),
+:host([size='56']) {
+ font-size: var(--fontSizeBase400);
+}
+
+:host([size='48']) {
+ width: 48px;
+ height: 48px;
+}
+
+:host([size='48']) .default-icon,
+:host([size='48']) ::slotted(svg) {
+ width: 24px;
+ height: 24px;
+ font-size: 24px;
+}
+
+:host([size='56']) {
+ width: 56px;
+ height: 56px;
+}
+
+:host([size='56']) .default-icon,
+:host([size='56']) ::slotted(svg) {
+ width: 28px;
+ height: 28px;
+ font-size: 28px;
+}
+
+:host([size='64']),
+:host([size='72']),
+:host([size='96']) {
+ font-size: var(--fontSizeBase500);
+}
+
+:host([size='64']) .default-icon,
+:host([size='72']) .default-icon,
+:host([size='64']) ::slotted(svg),
+:host([size='72']) ::slotted(svg) {
+ width: 32px;
+ height: 32px;
+ font-size: 32px;
+}
+
+:host([size='64']) {
+ width: 64px;
+ height: 64px;
+}
+
+:host([size='72']) {
+ width: 72px;
+ height: 72px;
+}
+
+:host([size='96']) {
+ width: 96px;
+ height: 96px;
+}
+
+:host([size='96']) .default-icon,
+:host([size='120']) .default-icon,
+:host([size='128']) .default-icon,
+:host([size='96']) ::slotted(svg),
+:host([size='120']) ::slotted(svg),
+:host([size='128']) ::slotted(svg) {
+ width: 48px;
+ height: 48px;
+ font-size: 48px;
+}
+
+:host([size='120']),
+:host([size='128']) {
+ font-size: var(--fontSizeBase600);
+}
+
+:host([size='120']) {
+ width: 120px;
+ height: 120px;
+}
+
+:host([size='128']) {
+ width: 128px;
+ height: 128px;
+}
+
+:host([shape='square']) {
+ border-radius: var(--borderRadiusMedium);
+}
+
+:host([shape='square'][size='20']),
+:host([shape='square'][size='24']) {
+ border-radius: var(--borderRadiusSmall);
+}
+
+:host([shape='square'][size='56']),
+:host([shape='square'][size='64']),
+:host([shape='square'][size='72']) {
+ border-radius: var(--borderRadiusLarge);
+}
+:host([shape='square'][size='96']),
+:host([shape='square'][size='120']),
+:host([shape='square'][size='128']) {
+ border-radius: var(--borderRadiusXLarge);
+}
+
+:host([data-color='brand']) {
+ color: var(--colorNeutralForegroundStaticInverted);
+ background-color: var(--colorBrandBackgroundStatic);
+}
+
+:host([data-color='dark-red']) {
+ color: var(--colorPaletteDarkRedForeground2);
+ background-color: var(--colorPaletteDarkRedBackground2);
+}
+
+:host([data-color='cranberry']) {
+ color: var(--colorPaletteCranberryForeground2);
+ background-color: var(--colorPaletteCranberryBackground2);
+}
+
+:host([data-color='red']) {
+ color: var(--colorPaletteRedForeground2);
+ background-color: var(--colorPaletteRedBackground2);
+}
+
+:host([data-color='pumpkin']) {
+ color: var(--colorPalettePumpkinForeground2);
+ background-color: var(--colorPalettePumpkinBackground2);
+}
+
+:host([data-color='peach']) {
+ color: var(--colorPalettePeachForeground2);
+ background-color: var(--colorPalettePeachBackground2);
+}
+
+:host([data-color='marigold']) {
+ color: var(--colorPaletteMarigoldForeground2);
+ background-color: var(--colorPaletteMarigoldBackground2);
+}
+
+:host([data-color='gold']) {
+ color: var(--colorPaletteGoldForeground2);
+ background-color: var(--colorPaletteGoldBackground2);
+}
+
+:host([data-color='brass']) {
+ color: var(--colorPaletteBrassForeground2);
+ background-color: var(--colorPaletteBrassBackground2);
+}
+
+:host([data-color='brown']) {
+ color: var(--colorPaletteBrownForeground2);
+ background-color: var(--colorPaletteBrownBackground2);
+}
+
+:host([data-color='forest']) {
+ color: var(--colorPaletteForestForeground2);
+ background-color: var(--colorPaletteForestBackground2);
+}
+
+:host([data-color='seafoam']) {
+ color: var(--colorPaletteSeafoamForeground2);
+ background-color: var(--colorPaletteSeafoamBackground2);
+}
+
+:host([data-color='dark-green']) {
+ color: var(--colorPaletteDarkGreenForeground2);
+ background-color: var(--colorPaletteDarkGreenBackground2);
+}
+
+:host([data-color='light-teal']) {
+ color: var(--colorPaletteLightTealForeground2);
+ background-color: var(--colorPaletteLightTealBackground2);
+}
+
+:host([data-color='teal']) {
+ color: var(--colorPaletteTealForeground2);
+ background-color: var(--colorPaletteTealBackground2);
+}
+
+:host([data-color='steel']) {
+ color: var(--colorPaletteSteelForeground2);
+ background-color: var(--colorPaletteSteelBackground2);
+}
+
+:host([data-color='blue']) {
+ color: var(--colorPaletteBlueForeground2);
+ background-color: var(--colorPaletteBlueBackground2);
+}
+
+:host([data-color='royal-blue']) {
+ color: var(--colorPaletteRoyalBlueForeground2);
+ background-color: var(--colorPaletteRoyalBlueBackground2);
+}
+
+:host([data-color='cornflower']) {
+ color: var(--colorPaletteCornflowerForeground2);
+ background-color: var(--colorPaletteCornflowerBackground2);
+}
+
+:host([data-color='navy']) {
+ color: var(--colorPaletteNavyForeground2);
+ background-color: var(--colorPaletteNavyBackground2);
+}
+
+:host([data-color='lavender']) {
+ color: var(--colorPaletteLavenderForeground2);
+ background-color: var(--colorPaletteLavenderBackground2);
+}
+
+:host([data-color='purple']) {
+ color: var(--colorPalettePurpleForeground2);
+ background-color: var(--colorPalettePurpleBackground2);
+}
+
+:host([data-color='grape']) {
+ color: var(--colorPaletteGrapeForeground2);
+ background-color: var(--colorPaletteGrapeBackground2);
+}
+
+:host([data-color='lilac']) {
+ color: var(--colorPaletteLilacForeground2);
+ background-color: var(--colorPaletteLilacBackground2);
+}
+
+:host([data-color='pink']) {
+ color: var(--colorPalettePinkForeground2);
+ background-color: var(--colorPalettePinkBackground2);
+}
+
+:host([data-color='magenta']) {
+ color: var(--colorPaletteMagentaForeground2);
+ background-color: var(--colorPaletteMagentaBackground2);
+}
+
+:host([data-color='plum']) {
+ color: var(--colorPalettePlumForeground2);
+ background-color: var(--colorPalettePlumBackground2);
+}
+
+:host([data-color='beige']) {
+ color: var(--colorPaletteBeigeForeground2);
+ background-color: var(--colorPaletteBeigeBackground2);
+}
+
+:host([data-color='mink']) {
+ color: var(--colorPaletteMinkForeground2);
+ background-color: var(--colorPaletteMinkBackground2);
+}
+
+:host([data-color='platinum']) {
+ color: var(--colorPalettePlatinumForeground2);
+ background-color: var(--colorPalettePlatinumBackground2);
+}
+
+:host([data-color='anchor']) {
+ color: var(--colorPaletteAnchorForeground2);
+ background-color: var(--colorPaletteAnchorBackground2);
+}
+
+:host([active]) {
+ /* Work-around for text pixel snapping at the end of the animation */
+ transform: perspective(1px);
+ transition-property: transform, opacity;
+ transition-duration: var(--durationUltraSlow), var(--durationFaster);
+ transition-delay: var(--curveEasyEaseMax), var(--curveLinear);
+}
+
+:host([active])::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-radius: inherit;
+ transition-property: margin, opacity;
+ transition-duration: var(--durationUltraSlow), var(--durationSlower);
+ transition-delay: var(--curveEasyEaseMax), var(--curveLinear);
+}
+:host([active])::before {
+ box-shadow: var(--shadow8);
+ border-style: solid;
+ border-color: var(--colorBrandBackgroundStatic);
+}
+
+:host([active][appearance='shadow'])::before {
+ border-style: none;
+ border-color: none;
+}
+
+:host([active]:not([appearance='shadow']))::before {
+ margin: calc(-2 * var(--strokeWidthThick));
+ border-width: var(--strokeWidthThick);
+}
+
+:host([size='56'][active]:not([appearance='shadow']))::before,
+:host([size='64'][active]:not([appearance='shadow']))::before {
+ margin: calc(-2 * var(--strokeWidthThicker));
+ border-width: var(--strokeWidthThicker);
+}
+
+:host([size='72'][active]:not([appearance='shadow']))::before,
+:host([size='96'][active]:not([appearance='shadow']))::before,
+:host([size='120'][active]:not([appearance='shadow']))::before,
+:host([size='128'][active]:not([appearance='shadow']))::before {
+ margin: calc(-2 * var(--strokeWidthThickest));
+ border-width: var(--strokeWidthThickest);
+}
+
+:host([size='20'][active][appearance])::before,
+:host([size='24'][active][appearance])::before,
+:host([size='28'][active][appearance])::before {
+ box-shadow: var(--shadow4);
+}
+
+:host([size='56'][active][appearance])::before,
+:host([size='64'][active][appearance])::before {
+ box-shadow: var(--shadow16);
+}
+
+:host([size='72'][active][appearance])::before,
+:host([size='96'][active][appearance])::before,
+:host([size='120'][active][appearance])::before,
+:host([size='128'][active][appearance])::before {
+ box-shadow: var(--shadow28);
+}
+
+:host([active][appearance='ring'])::before {
+ box-shadow: none;
+}
+
+:host([active='inactive']) {
+ opacity: 0.8;
+ transform: scale(0.875);
+ transition-property: transform, opacity;
+ transition-duration: var(--durationUltraSlow), var(--durationFaster);
+ transition-delay: var(--curveDecelerateMin), var(--curveLinear);
+}
+
+:host([active='inactive'])::before {
+ margin: 0;
+ opacity: 0;
+ transition-property: margin, opacity;
+ transition-duration: var(--durationUltraSlow), var(--durationSlower);
+ transition-delay: var(--curveDecelerateMin), var(--curveLinear);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host([active]) {
+ transition-duration: 0.01ms;
+ }
+
+ :host([active])::before {
+ transition-duration: 0.01ms;
+ transition-delay: 0.01ms;
+ }
+}
diff --git a/packages/web-components/src/avatar/avatar.template.html b/packages/web-components/src/avatar/avatar.template.html
new file mode 100644
index 00000000000000..96b118e4a5b2dd
--- /dev/null
+++ b/packages/web-components/src/avatar/avatar.template.html
@@ -0,0 +1,13 @@
+
+
+ {{styles}}
+
+ {{initials}}
+
+
+
+
diff --git a/packages/web-components/src/badge/badge.styles.css b/packages/web-components/src/badge/badge.styles.css
new file mode 100644
index 00000000000000..c5a21814f8b41b
--- /dev/null
+++ b/packages/web-components/src/badge/badge.styles.css
@@ -0,0 +1,266 @@
+:host([shape='square']) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([shape='rounded']) {
+ border-radius: var(--borderRadiusMedium);
+}
+
+:host([shape='rounded']:is([size='tiny'], [size='extra-small'], [size='small'])) {
+ border-radius: var(--borderRadiusSmall);
+}
+
+:host([appearance='tint']) {
+ background-color: var(--colorBrandBackground2);
+ color: var(--colorBrandForeground2);
+ border-color: var(--colorBrandStroke2);
+}
+
+:host([appearance='tint'][color='danger']) {
+ background-color: var(--colorPaletteRedBackground1);
+ color: var(--colorPaletteRedForeground1);
+ border-color: var(--colorPaletteRedBorder1);
+}
+
+:host([appearance='tint'][color='important']) {
+ background-color: var(--colorNeutralForeground3);
+ color: var(--colorNeutralBackground1);
+ border-color: var(--colorTransparentStroke);
+}
+
+:host([appearance='tint'][color='informative']) {
+ background-color: var(--colorNeutralBackground4);
+ color: var(--colorNeutralForeground3);
+ border-color: var(--colorNeutralStroke2);
+}
+
+:host([appearance='tint'][color='severe']) {
+ background-color: var(--colorPaletteDarkOrangeBackground1);
+ color: var(--colorPaletteDarkOrangeForeground1);
+ border-color: var(--colorPaletteDarkOrangeBorder1);
+}
+
+:host([appearance='tint'][color='subtle']) {
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground3);
+ border-color: var(--colorNeutralStroke2);
+}
+
+:host([appearance='tint'][color='success']) {
+ background-color: var(--colorPaletteGreenBackground1);
+ color: var(--colorPaletteGreenForeground1);
+ border-color: var(--colorPaletteGreenBorder2);
+}
+
+:host([appearance='tint'][color='warning']) {
+ background-color: var(--colorPaletteYellowBackground1);
+ color: var(--colorPaletteYellowForeground2);
+ border-color: var(--colorPaletteYellowBorder1);
+}
+
+:host([appearance='outline']) {
+ border-color: currentColor;
+ color: var(--colorBrandForeground1);
+ background-color: initial;
+}
+
+:host([appearance='outline'][color='danger']) {
+ color: var(--colorPaletteRedForeground3);
+}
+
+:host([appearance='outline'][color='important']) {
+ color: var(--colorNeutralForeground3);
+ border-color: var(--colorNeutralStrokeAccessible);
+}
+
+:host([appearance='outline'][color='informative']) {
+ color: var(--colorNeutralForeground3);
+ border-color: var(--colorNeutralStroke2);
+}
+
+:host([appearance='outline'][color='severe']) {
+ color: var(--colorPaletteDarkOrangeForeground3);
+}
+
+:host([appearance='outline'][color='subtle']) {
+ color: var(--colorNeutralForegroundStaticInverted);
+}
+
+:host([appearance='outline'][color='success']) {
+ color: var(--colorPaletteGreenForeground2);
+}
+
+:host([appearance='outline'][color='warning']) {
+ color: var(--colorPaletteYellowForeground2);
+}
+
+:host([appearance='ghost']) {
+ color: var(--colorBrandForeground1);
+ background-color: initial;
+}
+
+:host([appearance='ghost'][color='danger']) {
+ color: var(--colorPaletteRedForeground3);
+}
+
+:host([appearance='ghost'][color='important']) {
+ color: var(--colorNeutralForeground1);
+}
+
+:host([appearance='ghost'][color='informative']) {
+ color: var(--colorNeutralForeground3);
+}
+
+:host([appearance='ghost'][color='severe']) {
+ color: var(--colorPaletteDarkOrangeForeground3);
+}
+
+:host([appearance='ghost'][color='subtle']) {
+ color: var(--colorNeutralForegroundInverted);
+}
+
+:host([appearance='ghost'][color='success']) {
+ color: var(--colorPaletteGreenForeground3);
+}
+
+:host([appearance='ghost'][color='warning']) {
+ color: var(--colorPaletteYellowForeground2);
+}
+
+:host([color='danger']) {
+ background-color: var(--colorPaletteRedBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='important']) {
+ background-color: var(--colorNeutralForeground1);
+ color: var(--colorNeutralBackground1);
+}
+
+:host([color='informative']) {
+ background-color: var(--colorNeutralBackground5);
+ color: var(--colorNeutralForeground3);
+}
+
+:host([color='severe']) {
+ background-color: var(--colorPaletteDarkOrangeBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='subtle']) {
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+}
+
+:host([color='success']) {
+ background-color: var(--colorPaletteGreenBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='warning']) {
+ background-color: var(--colorPaletteYellowBackground3);
+ color: var(--colorNeutralForeground1Static);
+}
+
+:host([size='tiny']) {
+ width: 6px;
+ height: 6px;
+ font-size: 4px;
+ line-height: 4px;
+ padding-inline: 0;
+ min-width: unset;
+}
+:host([size='tiny']) ::slotted(svg) {
+ font-size: 6px;
+}
+:host([size='extra-small']) {
+ width: 10px;
+ height: 10px;
+ font-size: 6px;
+ line-height: 6px;
+ padding-inline: 0;
+ min-width: unset;
+}
+:host([size='extra-small']) ::slotted(svg) {
+ font-size: 10px;
+}
+:host([size='small']) {
+ min-width: 16px;
+ height: 16px;
+ font-size: var(--fontSizeBase100);
+ line-height: var(--lineHeightBase100);
+ padding-inline: calc(var(--spacingHorizontalXXS) + var(--spacingHorizontalXXS));
+}
+:host([size='small']) ::slotted(svg) {
+ font-size: 12px;
+}
+:host([size='large']) {
+ min-width: 24px;
+ height: 24px;
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ padding-inline: calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS));
+}
+:host([size='large']) ::slotted(svg) {
+ font-size: 16px;
+}
+:host([size='extra-large']) {
+ min-width: 32px;
+ height: 32px;
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ padding-inline: calc(var(--spacingHorizontalSNudge) + var(--spacingHorizontalXXS));
+}
+:host([size='extra-large']) ::slotted(svg) {
+ font-size: 20px;
+}
+
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+:host {
+ position: relative;
+ box-sizing: border-box;
+ align-items: center;
+ justify-content: center;
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ min-width: 20px;
+ height: 20px;
+ padding-inline: calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS));
+ border-radius: var(--borderRadiusCircular);
+ border-color: var(--colorTransparentStroke);
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ contain: content;
+}
+
+::slotted(svg) {
+ font-size: 12px;
+}
+
+:host(:not([appearance='ghost']))::after {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-style: solid;
+ border-width: var(--strokeWidthThin);
+ border-color: inherit;
+ border-radius: inherit;
+}
+
+@media (forced-colors: active) {
+ :host,
+ :host([appearance='outline']),
+ :host([appearance='tint']) {
+ border-color: CanvasText;
+ }
+}
diff --git a/packages/web-components/src/badge/badge.template.html b/packages/web-components/src/badge/badge.template.html
new file mode 100644
index 00000000000000..e7d9cc36640edc
--- /dev/null
+++ b/packages/web-components/src/badge/badge.template.html
@@ -0,0 +1,8 @@
+
+
+ {{styles}}
+
+
+
+
+
diff --git a/packages/web-components/src/button/button.styles.css b/packages/web-components/src/button/button.styles.css
new file mode 100644
index 00000000000000..15bddfefdbf8a4
--- /dev/null
+++ b/packages/web-components/src/button/button.styles.css
@@ -0,0 +1,268 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --icon-spacing: var(--spacingHorizontalSNudge);
+ position: relative;
+ contain: layout style;
+ vertical-align: middle;
+ align-items: center;
+ box-sizing: border-box;
+ justify-content: center;
+ text-align: center;
+ text-decoration-line: none;
+ margin: 0;
+ min-height: 32px;
+ outline-style: none;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ padding: 0 var(--spacingHorizontalM);
+ min-width: 96px;
+ border-radius: var(--borderRadiusMedium);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ line-height: var(--lineHeightBase300);
+ transition-duration: var(--durationFaster);
+ transition-property: background, border, color;
+ transition-timing-function: var(--curveEasyEase);
+ cursor: pointer;
+ user-select: none;
+}
+
+.content {
+ display: inherit;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground1Hover);
+ border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:hover:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ border-color: var(--colorNeutralStroke1Pressed);
+ color: var(--colorNeutralForeground1Pressed);
+ outline-style: none;
+}
+
+:host(:focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host {
+ transition-duration: 0.01ms;
+ }
+}
+
+::slotted(svg) {
+ font-size: 20px;
+ height: 20px;
+ width: 20px;
+ fill: currentColor;
+}
+
+::slotted([slot='start']) {
+ margin-inline-end: var(--icon-spacing);
+}
+
+::slotted([slot='end']),
+[slot='end'] {
+ flex-shrink: 0;
+ margin-inline-start: var(--icon-spacing);
+}
+
+:host([icon-only]) {
+ min-width: 32px;
+ max-width: 32px;
+}
+
+:host([size='small']) {
+ --icon-spacing: var(--spacingHorizontalXS);
+ min-height: 24px;
+ min-width: 64px;
+ padding: 0 var(--spacingHorizontalS);
+ border-radius: var(--borderRadiusSmall);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small'][icon-only]) {
+ min-width: 24px;
+ max-width: 24px;
+}
+
+:host([size='large']) {
+ min-height: 40px;
+ border-radius: var(--borderRadiusLarge);
+ padding: 0 var(--spacingHorizontalL);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large'][icon-only]) {
+ min-width: 40px;
+ max-width: 40px;
+}
+
+:host([size='large']) ::slotted(svg) {
+ font-size: 24px;
+ height: 24px;
+ width: 24px;
+}
+
+:host(:is([shape='circular'], [shape='circular']:focus-visible)) {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:is([shape='square'], [shape='square']:focus-visible)) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='primary']) {
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ border-color: transparent;
+}
+
+:host([appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host([appearance='primary']:is(:hover, :hover:active):not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host([appearance='primary']:is(:hover, :hover:active)) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([appearance='primary']:hover:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host([appearance='primary']:focus-visible) {
+ border-color: var(--colorNeutralForegroundOnBrand);
+ box-shadow: var(--shadow2), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+:host([appearance='outline']) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='outline']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='outline']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='subtle']) {
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='subtle']:hover:active) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host([appearance='transparent']) {
+ background-color: var(--colorTransparentBackground);
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is([appearance='transparent'], [appearance='transparent']:is(:hover, :active))) {
+ border-color: transparent;
+}
+
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover:active) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+ cursor: not-allowed;
+}
+
+:host([appearance='primary']:is(:disabled, [disabled-focusable])),
+:host([appearance='primary']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+}
+
+:host([appearance='outline']:is(:disabled, [disabled-focusable])),
+:host([appearance='outline']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='subtle']:is(:disabled, [disabled-focusable])),
+:host([appearance='subtle']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+ border-color: transparent;
+}
+
+:host([appearance='transparent']:is(:disabled, [disabled-focusable])),
+:host([appearance='transparent']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+ background-color: var(--colorTransparentBackground);
+}
+
+@media (forced-colors: active) {
+ :host {
+ background-color: ButtonFace;
+ color: ButtonText;
+ }
+
+ :host(:is(:hover, :focus-visible)) {
+ border-color: Highlight !important;
+ }
+
+ :host([appearance='primary']:not(:is(:hover, :focus-visible))) {
+ background-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+
+ :host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])) {
+ background-color: ButtonFace;
+ color: GrayText;
+ border-color: ButtonText;
+ }
+}
diff --git a/packages/web-components/src/button/button.template.html b/packages/web-components/src/button/button.template.html
new file mode 100644
index 00000000000000..a9e479995cda87
--- /dev/null
+++ b/packages/web-components/src/button/button.template.html
@@ -0,0 +1,10 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/checkbox/checkbox.styles.css b/packages/web-components/src/checkbox/checkbox.styles.css
new file mode 100644
index 00000000000000..8ebe81e8520071
--- /dev/null
+++ b/packages/web-components/src/checkbox/checkbox.styles.css
@@ -0,0 +1,172 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --size: 16px;
+ background-color: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusSmall);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStrokeAccessible);
+ box-sizing: border-box;
+ cursor: pointer;
+ position: relative;
+ width: var(--size);
+}
+
+:host,
+.indeterminate-indicator,
+.checked-indicator {
+ aspect-ratio: 1;
+}
+
+:host(:hover) {
+ border-color: var(--colorNeutralStrokeAccessibleHover);
+}
+
+:host(:active) {
+ border-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+
+:host(:state(checked):hover) {
+ background-color: var(--colorCompoundBrandBackgroundHover);
+ border-color: var(--colorCompoundBrandStrokeHover);
+}
+
+:host(:state(checked):active) {
+ background-color: var(--colorCompoundBrandBackgroundPressed);
+ border-color: var(--colorCompoundBrandStrokePressed);
+}
+
+:host(:focus-visible) {
+ outline: none;
+}
+
+:host(:not([slot='input']))::after {
+ content: '';
+ position: absolute;
+ inset: -8px;
+ box-sizing: border-box;
+ outline: none;
+ border: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ border-radius: var(--borderRadiusMedium);
+}
+
+:host(:not([slot='input']):focus-visible)::after {
+ border-color: var(--colorStrokeFocus2);
+}
+
+.indeterminate-indicator,
+.checked-indicator {
+ color: var(--colorNeutralForegroundInverted);
+ inset: 0;
+ margin: auto;
+ position: absolute;
+}
+
+::slotted([slot='checked-indicator']),
+.checked-indicator {
+ fill: currentColor;
+ display: inline-flex;
+ flex: 1 0 auto;
+ width: 12px;
+}
+
+:host(:not(:state(checked))) *:is(::slotted([slot='checked-indicator']), .checked-indicator) {
+ display: none;
+}
+
+:host(:state(checked)),
+:host(:state(indeterminate)) {
+ border-color: var(--colorCompoundBrandStroke);
+}
+
+:host(:state(checked)),
+:host(:state(indeterminate)) .indeterminate-indicator {
+ background-color: var(--colorCompoundBrandBackground);
+}
+
+:host(:state(indeterminate)) .indeterminate-indicator {
+ border-radius: var(--borderRadiusSmall);
+ position: absolute;
+ width: calc(var(--size) / 2);
+ inset: 0;
+}
+
+:host([size='large']) {
+ --size: 20px;
+}
+
+:host([size='large']) ::slotted([slot='checked-indicator']),
+:host([size='large']) .checked-indicator {
+ width: 16px;
+}
+
+:host([shape='circular']),
+:host([shape='circular']) .indeterminate-indicator {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host([disabled]),
+:host([disabled]:state(checked)) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+}
+
+:host([disabled]) {
+ cursor: unset;
+}
+
+:host([disabled]:state(indeterminate)) .indeterminate-indicator {
+ background-color: var(--colorNeutralStrokeDisabled);
+}
+
+:host([disabled]:state(checked)) .checked-indicator {
+ color: var(--colorNeutralStrokeDisabled);
+}
+
+@media (forced-colors: active) {
+ :host {
+ border-color: FieldText;
+ }
+
+ :host(:not([slot='input']:focus-visible))::after {
+ border-color: Canvas;
+ }
+
+ :host(:not([disabled]):hover),
+ :host(:state(checked):not([disabled]):hover),
+ :host(:not([slot='input']):focus-visible)::after {
+ border-color: Highlight;
+ }
+
+ .indeterminate-indicator,
+ .checked-indicator {
+ color: HighlightText;
+ }
+
+ :host(:state(checked)),
+ :host(:state(indeterminate)) .indeterminate-indicator {
+ background-color: FieldText;
+ }
+
+ :host(:state(checked):not([disabled]):hover),
+ :host(:state(indeterminate):not([disabled]):hover) .indeterminate-indicator {
+ background-color: Highlight;
+ }
+
+ :host([disabled]) {
+ border-color: GrayText;
+ }
+
+ :host([disabled]:state(indeterminate)) .indeterminate-indicator {
+ background-color: GrayText;
+ }
+
+ :host([disabled]),
+ :host([disabled]:state(checked)) .checked-indicator {
+ color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/checkbox/checkbox.template.html b/packages/web-components/src/checkbox/checkbox.template.html
new file mode 100644
index 00000000000000..4300eb1e7afc4a
--- /dev/null
+++ b/packages/web-components/src/checkbox/checkbox.template.html
@@ -0,0 +1,29 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/compound-button/compound-button.styles.css b/packages/web-components/src/compound-button/compound-button.styles.css
new file mode 100644
index 00000000000000..5efe49e318540a
--- /dev/null
+++ b/packages/web-components/src/compound-button/compound-button.styles.css
@@ -0,0 +1,370 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --icon-spacing: var(--spacingHorizontalSNudge);
+ position: relative;
+ contain: layout style;
+ vertical-align: middle;
+ align-items: center;
+ box-sizing: border-box;
+ justify-content: center;
+ text-align: center;
+ text-decoration-line: none;
+ margin: 0;
+ min-height: 32px;
+ outline-style: none;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ padding: 0 var(--spacingHorizontalM);
+ min-width: 96px;
+ border-radius: var(--borderRadiusMedium);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ line-height: var(--lineHeightBase300);
+ transition-duration: var(--durationFaster);
+ transition-property: background, border, color;
+ transition-timing-function: var(--curveEasyEase);
+ cursor: pointer;
+ user-select: none;
+}
+
+.content {
+ display: inherit;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground1Hover);
+ border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:hover:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ border-color: var(--colorNeutralStroke1Pressed);
+ color: var(--colorNeutralForeground1Pressed);
+ outline-style: none;
+}
+
+:host(:focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host {
+ transition-duration: 0.01ms;
+ }
+}
+
+::slotted(svg) {
+ font-size: 20px;
+ height: 20px;
+ width: 20px;
+ fill: currentColor;
+}
+
+::slotted([slot='start']) {
+ margin-inline-end: var(--icon-spacing);
+}
+
+::slotted([slot='end']),
+[slot='end'] {
+ flex-shrink: 0;
+ margin-inline-start: var(--icon-spacing);
+}
+
+:host([icon-only]) {
+ min-width: 32px;
+ max-width: 32px;
+}
+
+:host([size='small']) {
+ --icon-spacing: var(--spacingHorizontalXS);
+ min-height: 24px;
+ min-width: 64px;
+ padding: 0 var(--spacingHorizontalS);
+ border-radius: var(--borderRadiusSmall);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small'][icon-only]) {
+ min-width: 24px;
+ max-width: 24px;
+}
+
+:host([size='large']) {
+ min-height: 40px;
+ border-radius: var(--borderRadiusLarge);
+ padding: 0 var(--spacingHorizontalL);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large'][icon-only]) {
+ min-width: 40px;
+ max-width: 40px;
+}
+
+:host([size='large']) ::slotted(svg) {
+ font-size: 24px;
+ height: 24px;
+ width: 24px;
+}
+
+:host(:is([shape='circular'], [shape='circular']:focus-visible)) {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:is([shape='square'], [shape='square']:focus-visible)) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='primary']) {
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ border-color: transparent;
+}
+
+:host([appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host([appearance='primary']:is(:hover, :hover:active):not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host([appearance='primary']:is(:hover, :hover:active)) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([appearance='primary']:hover:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host([appearance='primary']:focus-visible) {
+ border-color: var(--colorNeutralForegroundOnBrand);
+ box-shadow: var(--shadow2), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+:host([appearance='outline']) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='outline']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='outline']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='subtle']) {
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='subtle']:hover:active) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host([appearance='transparent']) {
+ background-color: var(--colorTransparentBackground);
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is([appearance='transparent'], [appearance='transparent']:is(:hover, :active))) {
+ border-color: transparent;
+}
+
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover:active) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+ cursor: not-allowed;
+}
+
+:host([appearance='primary']:is(:disabled, [disabled-focusable])),
+:host([appearance='primary']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+}
+
+:host([appearance='outline']:is(:disabled, [disabled-focusable])),
+:host([appearance='outline']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='subtle']:is(:disabled, [disabled-focusable])),
+:host([appearance='subtle']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+ border-color: transparent;
+}
+
+:host([appearance='transparent']:is(:disabled, [disabled-focusable])),
+:host([appearance='transparent']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+ background-color: var(--colorTransparentBackground);
+}
+
+@media (forced-colors: active) {
+ :host {
+ background-color: ButtonFace;
+ color: ButtonText;
+ }
+
+ :host(:is(:hover, :focus-visible)) {
+ border-color: Highlight !important;
+ }
+
+ :host([appearance='primary']:not(:is(:hover, :focus-visible))) {
+ background-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+
+ :host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])) {
+ background-color: ButtonFace;
+ color: GrayText;
+ border-color: ButtonText;
+ }
+}
+
+:host,
+:host(:is([size])) {
+ gap: 12px;
+ height: auto;
+ padding-top: 14px;
+ padding-inline: 12px;
+ padding-bottom: 16px;
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ text-align: start;
+}
+
+::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2);
+ line-height: 100%;
+ font-size: var(--fontSizeBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+::slotted(svg),
+:host([size='large']) ::slotted(svg) {
+ font-size: 40px;
+ height: 40px;
+ width: 40px;
+}
+
+:host(:hover) ::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2Hover);
+}
+
+:host(:active) ::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2Pressed);
+}
+
+:host(:is([appearance='primary'], [appearance='primary']:is(:hover, :active))) ::slotted([slot='description']) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host(:is([appearance='transparent'], [appearance='subtle'], [appearance='subtle']:is(:hover, :active)))
+ ::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) ::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:active) ::slotted([slot='description']) {
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is(:disabled, :disabled[appearance], [disabled-focusable], [disabled-focusable][appearance]))
+ ::slotted([slot='description']) {
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([size='small']) {
+ padding: 8px;
+ padding-bottom: 10px;
+}
+
+:host([icon-only]) {
+ min-width: 52px;
+ max-width: 52px;
+ padding: var(--spacingHorizontalSNudge);
+}
+
+:host([icon-only][size='small']) {
+ min-width: 48px;
+ max-width: 48px;
+ padding: var(--spacingHorizontalXS);
+}
+
+:host([icon-only][size='large']) {
+ min-width: 56px;
+ max-width: 56px;
+ padding: var(--spacingHorizontalS);
+}
+
+:host([size='large']) {
+ padding-top: 18px;
+ padding-inline: 16px;
+ padding-bottom: 20px;
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+:host([size='large']) ::slotted([slot='description']) {
+ font-size: var(--fontSizeBase300);
+}
+
+@media (forced-colors: active) {
+ :host([appearance='primary']:not(:hover, :focus-visible, :disabled, [disabled-focusable]))
+ ::slotted([slot='description']) {
+ color: HighlightText;
+ }
+}
diff --git a/packages/web-components/src/compound-button/compound-button.template.html b/packages/web-components/src/compound-button/compound-button.template.html
new file mode 100644
index 00000000000000..51a90b0ff37b55
--- /dev/null
+++ b/packages/web-components/src/compound-button/compound-button.template.html
@@ -0,0 +1,11 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/counter-badge/counter-badge.styles.css b/packages/web-components/src/counter-badge/counter-badge.styles.css
new file mode 100644
index 00000000000000..f36391b6c850a1
--- /dev/null
+++ b/packages/web-components/src/counter-badge/counter-badge.styles.css
@@ -0,0 +1,177 @@
+:host([shape='rounded']) {
+ border-radius: var(--borderRadiusMedium);
+}
+
+:host([shape='rounded']:is([size='tiny'], [size='extra-small'], [size='small'])) {
+ border-radius: var(--borderRadiusSmall);
+}
+
+:host([size='tiny']) {
+ width: 6px;
+ height: 6px;
+ font-size: 4px;
+ line-height: 4px;
+ padding-inline: 0;
+ min-width: unset;
+}
+:host([size='tiny']) ::slotted(svg) {
+ font-size: 6px;
+}
+:host([size='extra-small']) {
+ width: 10px;
+ height: 10px;
+ font-size: 6px;
+ line-height: 6px;
+ padding-inline: 0;
+ min-width: unset;
+}
+:host([size='extra-small']) ::slotted(svg) {
+ font-size: 10px;
+}
+:host([size='small']) {
+ min-width: 16px;
+ height: 16px;
+ font-size: var(--fontSizeBase100);
+ line-height: var(--lineHeightBase100);
+ padding-inline: calc(var(--spacingHorizontalXXS) + var(--spacingHorizontalXXS));
+}
+:host([size='small']) ::slotted(svg) {
+ font-size: 12px;
+}
+:host([size='large']) {
+ min-width: 24px;
+ height: 24px;
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ padding-inline: calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS));
+}
+:host([size='large']) ::slotted(svg) {
+ font-size: 16px;
+}
+:host([size='extra-large']) {
+ min-width: 32px;
+ height: 32px;
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ padding-inline: calc(var(--spacingHorizontalSNudge) + var(--spacingHorizontalXXS));
+}
+:host([size='extra-large']) ::slotted(svg) {
+ font-size: 20px;
+}
+
+:host([color='danger']) {
+ background-color: var(--colorPaletteRedBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='important']) {
+ background-color: var(--colorNeutralForeground1);
+ color: var(--colorNeutralBackground1);
+}
+
+:host([color='informative']) {
+ background-color: var(--colorNeutralBackground5);
+ color: var(--colorNeutralForeground3);
+}
+
+:host([color='severe']) {
+ background-color: var(--colorPaletteDarkOrangeBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='subtle']) {
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+}
+
+:host([color='success']) {
+ background-color: var(--colorPaletteGreenBackground3);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([color='warning']) {
+ background-color: var(--colorPaletteYellowBackground3);
+ color: var(--colorNeutralForeground1Static);
+}
+
+:host([appearance='ghost']) {
+ color: var(--colorBrandForeground1);
+ background-color: initial;
+}
+
+:host([appearance='ghost'][color='danger']) {
+ color: var(--colorPaletteRedForeground3);
+}
+
+:host([appearance='ghost'][color='important']) {
+ color: var(--colorNeutralForeground1);
+}
+
+:host([appearance='ghost'][color='informative']) {
+ color: var(--colorNeutralForeground3);
+}
+
+:host([appearance='ghost'][color='severe']) {
+ color: var(--colorPaletteDarkOrangeForeground3);
+}
+
+:host([appearance='ghost'][color='subtle']) {
+ color: var(--colorNeutralForegroundInverted);
+}
+
+:host([appearance='ghost'][color='success']) {
+ color: var(--colorPaletteGreenForeground3);
+}
+
+:host([appearance='ghost'][color='warning']) {
+ color: var(--colorPaletteYellowForeground2);
+}
+
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+:host {
+ position: relative;
+ box-sizing: border-box;
+ align-items: center;
+ justify-content: center;
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ min-width: 20px;
+ height: 20px;
+ padding-inline: calc(var(--spacingHorizontalXS) + var(--spacingHorizontalXXS));
+ border-radius: var(--borderRadiusCircular);
+ border-color: var(--colorTransparentStroke);
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ contain: content;
+}
+
+::slotted(svg) {
+ font-size: 12px;
+}
+
+:host(:not([appearance='ghost']))::after {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-style: solid;
+ border-width: var(--strokeWidthThin);
+ border-color: inherit;
+ border-radius: inherit;
+}
+
+:host(:is([dot], [dot][appearance][size])) {
+ min-width: auto;
+ width: 6px;
+ height: 6px;
+ padding: 0;
+}
diff --git a/packages/web-components/src/counter-badge/counter-badge.template.html b/packages/web-components/src/counter-badge/counter-badge.template.html
new file mode 100644
index 00000000000000..c87df64f4b6337
--- /dev/null
+++ b/packages/web-components/src/counter-badge/counter-badge.template.html
@@ -0,0 +1,8 @@
+
+
+ {{styles}}
+
+ {{displayValue}}
+
+
+
diff --git a/packages/web-components/src/dialog-body/dialog-body.styles.css b/packages/web-components/src/dialog-body/dialog-body.styles.css
new file mode 100644
index 00000000000000..add183a4e11d2a
--- /dev/null
+++ b/packages/web-components/src/dialog-body/dialog-body.styles.css
@@ -0,0 +1,92 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: grid;
+}
+
+:host {
+ background: var(--colorNeutralBackground1);
+ box-sizing: border-box;
+ gap: var(--spacingVerticalS);
+ padding: var(--spacingVerticalXXL) var(--spacingHorizontalXXL);
+ container: dialog-body / inline-size;
+}
+
+.title {
+ box-sizing: border-box;
+ align-items: flex-start;
+ background: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ column-gap: 8px;
+ display: flex;
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase500);
+ font-weight: var(--fontWeightSemibold);
+ inset-block-start: 0;
+ justify-content: space-between;
+ line-height: var(--lineHeightBase500);
+ margin-block-end: calc(var(--spacingVerticalS) * -1);
+ margin-block-start: calc(var(--spacingVerticalXXL) * -1);
+ padding-block-end: var(--spacingVerticalS);
+ padding-block-start: var(--spacingVerticalXXL);
+}
+
+.content {
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground1);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase300);
+ min-height: 32px;
+}
+
+.actions {
+ box-sizing: border-box;
+ background: var(--colorNeutralBackground1);
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacingVerticalS);
+ inset-block-end: 0;
+ margin-block-end: calc(var(--spacingVerticalXXL) * -1);
+ padding-block-end: var(--spacingVerticalXXL);
+ padding-block-start: var(--spacingVerticalL);
+}
+
+::slotted([slot='title-action']) {
+ margin-inline-start: auto;
+}
+
+::slotted([slot='title']) {
+ font: inherit;
+ padding: 0;
+ margin: 0;
+}
+
+/* align title content to the end when there is no title*/
+:not(:has(:is([slot='title'], [slot='title-action']))) .title {
+ justify-content: end;
+}
+
+@container (min-width: 480px) {
+ .actions {
+ align-items: center;
+ flex-direction: row;
+ justify-content: flex-end;
+ margin-block-start: calc(var(--spacingVerticalS) * -1);
+ padding-block-start: var(--spacingVerticalS);
+ }
+}
+
+/* For a11y, set sticky position for title and actions when the viewport is tall enough */
+@media (min-height: 480px) {
+ .title {
+ position: sticky;
+ z-index: 1;
+ }
+ .actions {
+ position: sticky;
+ z-index: 2;
+ }
+}
diff --git a/packages/web-components/src/dialog-body/dialog-body.styles.ts b/packages/web-components/src/dialog-body/dialog-body.styles.ts
index 9109a57ce4895e..fc3586996228b0 100644
--- a/packages/web-components/src/dialog-body/dialog-body.styles.ts
+++ b/packages/web-components/src/dialog-body/dialog-body.styles.ts
@@ -106,4 +106,5 @@ export const styles = css`
position: sticky;
z-index: 2;
}
+ }
`;
diff --git a/packages/web-components/src/dialog-body/dialog-body.template.html b/packages/web-components/src/dialog-body/dialog-body.template.html
new file mode 100644
index 00000000000000..16605d782db4d8
--- /dev/null
+++ b/packages/web-components/src/dialog-body/dialog-body.template.html
@@ -0,0 +1,12 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/dialog/dialog.styles.css b/packages/web-components/src/dialog/dialog.styles.css
new file mode 100644
index 00000000000000..3e9d9d8bd9f0d3
--- /dev/null
+++ b/packages/web-components/src/dialog/dialog.styles.css
@@ -0,0 +1,84 @@
+@layer base {
+ :host {
+ --dialog-backdrop: var(--colorBackgroundOverlay);
+ --dialog-starting-scale: 0.85;
+ }
+
+ ::backdrop {
+ background: var(--dialog-backdrop, rgba(0, 0, 0, 0.4));
+ }
+
+ dialog {
+ background: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusXLarge);
+ border: none;
+ box-shadow: var(--shadow64);
+ color: var(--colorNeutralForeground1);
+ max-height: 100vh;
+ padding: 0;
+ width: 100%;
+ max-width: 600px;
+ }
+
+ :host([type='non-modal']) dialog {
+ inset: 0;
+ z-index: 2;
+ overflow: auto;
+ }
+
+ @supports (max-height: 1dvh) {
+ dialog {
+ max-height: 100dvh;
+ }
+ }
+}
+
+@layer animations {
+ /* Disable animations for reduced motion */
+ @media (prefers-reduced-motion: no-preference) {
+ dialog,
+ ::backdrop {
+ transition: display allow-discrete, opacity, overlay allow-discrete, scale;
+ transition-duration: var(--durationGentle);
+ transition-timing-function: var(--curveDecelerateMid);
+ /* Set opacity to 0 when closed */
+ opacity: 0;
+ }
+ ::backdrop {
+ transition-timing-function: var(--curveLinear);
+ }
+
+ /* Set opacity to 1 when open */
+ [open],
+ [open]::backdrop {
+ opacity: 1;
+ }
+
+ /* Exit styles for dialog */
+ dialog:not([open]) {
+ /* Make small when leaving */
+ scale: var(--dialog-starting-scale);
+ /* Faster leaving the stage then entering */
+ transition-timing-function: var(--curveAccelerateMid);
+ }
+ }
+
+ @starting-style {
+ [open],
+ [open]::backdrop {
+ opacity: 0;
+ }
+
+ dialog {
+ scale: var(--dialog-starting-scale);
+ }
+ }
+}
+
+@media (forced-colors: active) {
+ @layer base {
+ dialog {
+ border: var(--strokeWidthThin) solid var(--colorTransparentStroke);
+ }
+ }
+}
diff --git a/packages/web-components/src/dialog/dialog.template.html b/packages/web-components/src/dialog/dialog.template.html
new file mode 100644
index 00000000000000..790033f1145f86
--- /dev/null
+++ b/packages/web-components/src/dialog/dialog.template.html
@@ -0,0 +1,19 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/divider/divider.styles.css b/packages/web-components/src/divider/divider.styles.css
new file mode 100644
index 00000000000000..5692609d5174e9
--- /dev/null
+++ b/packages/web-components/src/divider/divider.styles.css
@@ -0,0 +1,123 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: flex;
+}
+
+:host {
+ contain: content;
+}
+
+:host::after,
+:host::before {
+ align-self: center;
+ background: var(--colorNeutralStroke2);
+ box-sizing: border-box;
+ content: '';
+ display: flex;
+ flex-grow: 1;
+ height: var(--strokeWidthThin);
+}
+
+:host([inset]) {
+ padding: 0 12px;
+}
+
+:host ::slotted(*) {
+ color: var(--colorNeutralForeground2);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ font-weight: var(--fontWeightRegular);
+ margin: 0;
+ padding: 0 12px;
+}
+
+:host([align-content='start'])::before,
+:host([align-content='end'])::after {
+ flex-basis: 12px;
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+:host([orientation='vertical']) {
+ align-items: center;
+ flex-direction: column;
+ height: 100%;
+ min-height: 84px;
+}
+
+:host([orientation='vertical']):empty {
+ min-height: 20px;
+}
+
+:host([orientation='vertical'][inset])::before {
+ margin-top: 12px;
+}
+:host([orientation='vertical'][inset])::after {
+ margin-bottom: 12px;
+}
+
+:host([orientation='vertical']):empty::before,
+:host([orientation='vertical']):empty::after {
+ height: 10px;
+ min-height: 10px;
+ flex-grow: 0;
+}
+
+:host([orientation='vertical'])::before,
+:host([orientation='vertical'])::after {
+ width: var(--strokeWidthThin);
+ min-height: 20px;
+ height: 100%;
+}
+
+:host([orientation='vertical']) ::slotted(*) {
+ display: flex;
+ flex-direction: column;
+ padding: 12px 0;
+ line-height: 20px;
+}
+
+:host([orientation='vertical'][align-content='start'])::before {
+ min-height: 8px;
+}
+:host([orientation='vertical'][align-content='end'])::after {
+ min-height: 8px;
+}
+
+:host([appearance='strong'])::before,
+:host([appearance='strong'])::after {
+ background: var(--colorNeutralStroke1);
+}
+:host([appearance='strong']) ::slotted(*) {
+ color: var(--colorNeutralForeground1);
+}
+:host([appearance='brand'])::before,
+:host([appearance='brand'])::after {
+ background: var(--colorBrandStroke1);
+}
+:host([appearance='brand']) ::slotted(*) {
+ color: var(--colorBrandForeground1);
+}
+:host([appearance='subtle'])::before,
+:host([appearance='subtle'])::after {
+ background: var(--colorNeutralStroke3);
+}
+:host([appearance='subtle']) ::slotted(*) {
+ color: var(--colorNeutralForeground3);
+}
+
+@media (forced-colors: active) {
+ :host([appearance='strong'])::before,
+ :host([appearance='strong'])::after,
+ :host([appearance='brand'])::before,
+ :host([appearance='brand'])::after,
+ :host([appearance='subtle'])::before,
+ :host([appearance='subtle'])::after,
+ :host::after,
+ :host::before {
+ background: WindowText;
+ color: WindowText;
+ }
+}
diff --git a/packages/web-components/src/divider/divider.template.html b/packages/web-components/src/divider/divider.template.html
new file mode 100644
index 00000000000000..5661b5eec61b92
--- /dev/null
+++ b/packages/web-components/src/divider/divider.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/drawer-body/drawer-body.styles.css b/packages/web-components/src/drawer-body/drawer-body.styles.css
new file mode 100644
index 00000000000000..c5596462ee3555
--- /dev/null
+++ b/packages/web-components/src/drawer-body/drawer-body.styles.css
@@ -0,0 +1,36 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: grid;
+}
+:host {
+ box-sizing: border-box;
+ grid-template-rows: min-content auto min-content;
+ position: relative;
+ height: 100%;
+ padding: var(--spacingHorizontalXL);
+ max-height: 100svh;
+}
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase500);
+ line-height: var(--lineHeightBase500);
+ font-weight: var(--fontWeightSemibold);
+}
+
+.footer {
+ display: flex;
+ justify-content: flex-start;
+ gap: var(--spacingHorizontalM);
+}
+
+::slotted([slot='title']) {
+ font: inherit;
+ padding: 0;
+ margin: 0;
+}
diff --git a/packages/web-components/src/drawer-body/drawer-body.template.html b/packages/web-components/src/drawer-body/drawer-body.template.html
new file mode 100644
index 00000000000000..96ca06a3fae36f
--- /dev/null
+++ b/packages/web-components/src/drawer-body/drawer-body.template.html
@@ -0,0 +1,15 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/drawer/drawer.styles.css b/packages/web-components/src/drawer/drawer.styles.css
new file mode 100644
index 00000000000000..111b3b9fce8639
--- /dev/null
+++ b/packages/web-components/src/drawer/drawer.styles.css
@@ -0,0 +1,134 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ --dialog-backdrop: var(--colorBackgroundOverlay);
+}
+
+:host([type='non-modal']) dialog[open]::backdrop {
+ display: none;
+}
+
+:host([type='non-modal']) dialog {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+}
+
+:host([type='inline']) {
+ height: 100%;
+ width: fit-content;
+}
+
+:host([type='inline']) dialog[open] {
+ box-shadow: none;
+ position: relative;
+}
+
+:host([size='small']) dialog {
+ width: 320px;
+ max-width: 320px;
+}
+
+:host([size='large']) dialog {
+ width: 940px;
+ max-width: 940px;
+}
+
+:host([size='full']) dialog {
+ width: 100%;
+ max-width: 100%;
+}
+
+:host([position='end']) dialog {
+ margin-inline-start: auto;
+ margin-inline-end: 0;
+}
+
+dialog {
+ box-sizing: border-box;
+ z-index: var(--drawer-elevation, 1000);
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightRegular);
+ color: var(--colorNeutralForeground1);
+ max-width: var(--drawer-width, 592px);
+ max-height: 100vh;
+ height: 100%;
+ margin-inline-start: 0;
+ margin-inline-end: auto;
+ border-inline-end-color: var(--colorTransparentStroke);
+ border-inline-start-color: var(--drawer-separator, var(--colorTransparentStroke));
+ outline: none;
+ top: 0;
+ bottom: 0;
+ width: var(--drawer-width, 592px);
+ border-radius: 0;
+ padding: 0;
+ max-width: var(--drawer-width, 592px);
+ box-shadow: var(--shadow64);
+ border: var(--strokeWidthThin) solid var(--colorTransparentStroke);
+ background: var(--colorNeutralBackground1);
+}
+
+dialog::backdrop {
+ background: var(--dialog-backdrop);
+}
+
+@layer animations {
+ /* Disable animations for reduced motion */
+ @media (prefers-reduced-motion: no-preference) {
+ dialog {
+ transition: display allow-discrete, opacity, overlay allow-discrete, transform;
+ transition-duration: var(--durationGentle);
+ transition-timing-function: var(--curveDecelerateMid);
+ }
+
+ /* Exit styles for dialog */
+ :host dialog:not([open]) {
+ transform: translateX(-100%);
+ transition-timing-function: var(--curveAccelerateMid);
+ }
+ :host([position='end']) dialog:not([open]) {
+ transform: translateX(100%);
+ transition-timing-function: var(--curveAccelerateMid);
+ }
+
+ dialog[open] {
+ transform: translateX(0);
+ }
+
+ dialog::backdrop {
+ transition: display allow-discrete, opacity, overlay allow-discrete, scale;
+ transition-duration: var(--durationGentle);
+ transition-timing-function: var(--curveDecelerateMid);
+ background: var(--dialog-backdrop, var(--colorBackgroundOverlay));
+ opacity: 0;
+ }
+
+ dialog[open]::backdrop {
+ opacity: 1;
+ }
+
+ dialog::backdrop {
+ transition-timing-function: var(--curveLinear);
+ }
+ }
+
+ @starting-style {
+ dialog[open] {
+ transform: translateX(-100%);
+ }
+ :host([position='end']) dialog[open] {
+ transform: translateX(100%);
+ }
+ dialog[open]::backdrop {
+ opacity: 0;
+ }
+ }
+}
diff --git a/packages/web-components/src/drawer/drawer.template.html b/packages/web-components/src/drawer/drawer.template.html
new file mode 100644
index 00000000000000..6b0f2ae2b54b8f
--- /dev/null
+++ b/packages/web-components/src/drawer/drawer.template.html
@@ -0,0 +1,21 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/dropdown/dropdown.styles.css b/packages/web-components/src/dropdown/dropdown.styles.css
new file mode 100644
index 00000000000000..12bd0156cac306
--- /dev/null
+++ b/packages/web-components/src/dropdown/dropdown.styles.css
@@ -0,0 +1,222 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground1);
+ cursor: pointer;
+}
+
+:host(:state(placeholder-shown)) {
+ color: var(--colorNeutralForeground4);
+}
+
+.control {
+ appearance: none;
+ background-color: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusMedium);
+ border: var(--strokeWidthThin) solid var(--colorTransparentStroke);
+ box-shadow: inset 0 0 0 var(--strokeWidthThin) var(--control-border-color);
+ box-sizing: border-box;
+ color: inherit;
+ column-gap: var(--spacingHorizontalXXS);
+ display: inline-flex;
+ justify-content: space-between;
+ min-width: 160px;
+ overflow: hidden;
+ padding: var(--spacingVerticalSNudge) var(--spacingHorizontalMNudge);
+ white-space: normal;
+ position: relative;
+ text-align: start;
+ width: 100%;
+ z-index: 1;
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small']) .control {
+ column-gap: var(--spacingHorizontalXXS);
+ padding: var(--spacingVerticalXS) var(--spacingHorizontalSNudge);
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='large']) .control {
+ column-gap: var(--spacingHorizontalS);
+ padding: var(--spacingVerticalS) var(--spacingHorizontalM);
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+ font-weight: var(--fontWeightRegular);
+}
+
+::slotted(:is(input, button)) {
+ all: unset;
+ flex: 1 1 auto;
+}
+
+::slotted(button) {
+ cursor: pointer;
+}
+
+::slotted(input) {
+ cursor: text;
+}
+
+:where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
+ all: unset;
+ align-items: center;
+ appearance: none;
+ aspect-ratio: 1;
+ color: var(--colorNeutralForeground3);
+ display: inline-flex;
+ justify-content: center;
+ width: 20px;
+}
+
+:host([size='small']) :where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
+ width: 16px;
+}
+
+:host([size='large']) :where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
+ width: 24px;
+}
+
+.control::after,
+.control::before {
+ content: '' / '';
+ inset: auto 0 0;
+ pointer-events: none;
+ position: absolute;
+}
+
+.control::before {
+ height: var(--strokeWidthThin);
+}
+
+.control::after {
+ background-color: var(--colorCompoundBrandStroke);
+ height: var(--strokeWidthThick);
+ scale: 0 1;
+ transition: scale var(--durationUltraFast) var(--curveDecelerateMid);
+}
+
+/**
+ * focus-ring style uses lingering :focus-within selector due to platform limitations
+ * TODO: Convert selector to `:host(:has(:focus-visible)) .control` when browser support increases
+ * ISSUE: https://issues.chromium.org/issues/40062355
+ */
+:host(:where(:focus-within)) .control {
+ border-radius: var(--borderRadiusMedium);
+ box-shadow: inset 0 0 0 1px var(--colorStrokeFocus1);
+ outline: var(--strokeWidthThick) solid var(--colorStrokeFocus2);
+}
+
+:host(:where(:state(open), :focus-within)) .control::after {
+ scale: 1 1;
+ transition-duration: var(--durationNormal);
+ transition-timing-function: var(--curveAccelerateMid);
+}
+
+:host(:where([appearance='outline'], [appearance='transparent'])) .control::before {
+ background-color: var(--colorNeutralStrokeAccessible);
+}
+
+:host([appearance='transparent']) .control {
+ --control-border-color: var(--colorTransparentStrokeInteractive);
+ background-color: var(--colorTransparentBackground);
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='outline']) .control {
+ --control-border-color: var(--colorNeutralStroke1);
+}
+
+:host([appearance='outline']) .control:hover {
+ --control-border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:where([appearance='outline'], [appearance='transparent'])) .control:hover::before {
+ background-color: var(--colorNeutralStrokeAccessibleHover);
+}
+
+:host([appearance='outline']) .control:hover::after {
+ background-color: var(--colorCompoundBrandBackgroundHover);
+}
+
+:host([appearance='outline']) .control:active {
+ --control-border-color: var(--colorNeutralStroke1Pressed);
+}
+
+:host(:where([appearance='outline'], [appearance='transparent'])) .control:active::before {
+ background-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+
+:host(:where([appearance='outline'], [appearance='transparent'])) .control:active::after {
+ background-color: var(--colorCompoundBrandBackgroundPressed);
+}
+
+:host([appearance='filled-darker']) .control {
+ background-color: var(--colorNeutralBackground3);
+}
+
+:host(:where([appearance='filled-lighter'], [appearance='filled-darker'])) .control {
+ --control-border-color: var(--colorTransparentStroke);
+}
+
+:host(:disabled),
+:host(:disabled) ::slotted(:where(button, input)) {
+ cursor: not-allowed;
+}
+
+:host(:disabled) .control::before,
+:host(:disabled) .control::after {
+ content: none;
+}
+
+:host(:disabled) .control:is(*, :active, :hover),
+:host(:disabled) :where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
+ --control-border-color: var(--colorNeutralStrokeDisabled);
+ background-color: var(--colorNeutralBackgroundDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+::slotted(:not([slot]):not([popover])),
+::slotted([popover]:not(:popover-open)) {
+ display: none;
+}
+
+@supports not (anchor-name: --anchor) {
+ :host {
+ --listbox-max-height: 50vh;
+ --margin-offset: calc(var(--lineHeightBase300) + (var(--spacingVerticalSNudge) * 2) + var(--strokeWidthThin));
+ }
+
+ :host([size='small']) {
+ --margin-offset: calc(var(--lineHeightBase200) + (var(--spacingVerticalXS) * 2) + var(--strokeWidthThin));
+ }
+
+ :host([size='large']) {
+ --margin-offset: calc(var(--lineHeightBase400) + (var(--spacingVerticalS) * 2) + var(--strokeWidthThin));
+ }
+}
+
+@media (forced-colors: active) {
+ :host(:disabled) .control {
+ border-color: GrayText;
+ }
+ :host(:disabled) :where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
+ color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/dropdown/dropdown.styles.ts b/packages/web-components/src/dropdown/dropdown.styles.ts
index 5e840d06ab6b22..0e52c6e03a7fee 100644
--- a/packages/web-components/src/dropdown/dropdown.styles.ts
+++ b/packages/web-components/src/dropdown/dropdown.styles.ts
@@ -260,4 +260,5 @@ export const styles = css`
:host(:disabled) :where(slot[name='indicator'] > *, ::slotted([slot='indicator'])) {
color: GrayText;
}
+ }
`;
diff --git a/packages/web-components/src/dropdown/dropdown.template.html b/packages/web-components/src/dropdown/dropdown.template.html
new file mode 100644
index 00000000000000..e09ea75a95f8dd
--- /dev/null
+++ b/packages/web-components/src/dropdown/dropdown.template.html
@@ -0,0 +1,28 @@
+
+
+ {{styles}}
+
+
+
+
diff --git a/packages/web-components/src/field/field.styles.css b/packages/web-components/src/field/field.styles.css
new file mode 100644
index 00000000000000..ef680ab42aeb98
--- /dev/null
+++ b/packages/web-components/src/field/field.styles.css
@@ -0,0 +1,125 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-grid;
+}
+
+:host {
+ color: var(--colorNeutralForeground1);
+ align-items: center;
+ gap: 0 var(--spacingHorizontalM);
+ justify-items: start;
+}
+
+:has([slot='message']) {
+ color: var(--colorNeutralForeground1);
+ row-gap: var(--spacingVerticalS);
+}
+
+:not(::slotted([slot='label'])) {
+ gap: 0;
+}
+
+:host([label-position='before']) {
+ grid-template-areas: 'label input' 'label message';
+}
+
+:host([label-position='after']) {
+ gap: 0;
+ grid-template-areas: 'input label' 'message message';
+ grid-template-columns: auto 1fr;
+}
+
+:host([label-position='after']) ::slotted([slot='input']) {
+ margin-inline-end: var(--spacingHorizontalM);
+}
+
+:host([label-position='above']) {
+ grid-template-areas: 'label' 'input' 'message';
+ row-gap: var(--spacingVerticalXXS);
+}
+
+:host([label-position='below']) {
+ grid-template-areas: 'input' 'label' 'message';
+ justify-items: center;
+}
+
+:host([label-position='below']) ::slotted([slot='label']) {
+ margin-block-start: var(--spacingVerticalM);
+}
+
+:host(:state(required)) ::slotted([slot='label'])::after {
+ content: '*' / '';
+ color: var(--colorPaletteRedForeground1);
+ margin-inline-start: var(--spacingHorizontalXS);
+}
+
+::slotted([slot='input']) {
+ grid-area: input;
+}
+
+::slotted([slot='message']) {
+ color: var(--colorNeutralForeground3);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ font-weight: var(--fontWeightRegular);
+ grid-area: message;
+ line-height: var(--lineHeightBase200);
+ margin-block-start: var(--spacingVerticalXXS);
+}
+
+:host(:state(focus-visible):focus-within) {
+ border-radius: var(--borderRadiusMedium);
+ outline: var(--strokeWidthThick) solid var(--colorStrokeFocus2);
+}
+
+::slotted(label),
+::slotted([slot='label']) {
+ cursor: inherit;
+ display: inline-flex;
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ grid-area: label;
+ line-height: var(--lineHeightBase300);
+ justify-self: stretch;
+ user-select: none;
+}
+
+:host([size='small']) ::slotted(label) {
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+}
+
+:host([size='large']) ::slotted(label) {
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large']) ::slotted(label),
+:host([weight='semibold']) ::slotted(label) {
+ font-weight: var(--fontWeightSemibold);
+}
+
+:host(:state(disabled)) {
+ cursor: default;
+}
+
+::slotted([flag]) {
+ display: none;
+}
+
+:host(:state(bad-input)) ::slotted([flag='bad-input']),
+:host(:state(custom-error)) ::slotted([flag='custom-error']),
+:host(:state(pattern-mismatch)) ::slotted([flag='pattern-mismatch']),
+:host(:state(range-overflow)) ::slotted([flag='range-overflow']),
+:host(:state(range-underflow)) ::slotted([flag='range-underflow']),
+:host(:state(step-mismatch)) ::slotted([flag='step-mismatch']),
+:host(:state(too-long)) ::slotted([flag='too-long']),
+:host(:state(too-short)) ::slotted([flag='too-short']),
+:host(:state(type-mismatch)) ::slotted([flag='type-mismatch']),
+:host(:state(value-missing)) ::slotted([flag='value-missing']),
+:host(:state(valid)) ::slotted([flag='valid']) {
+ display: block;
+}
diff --git a/packages/web-components/src/field/field.template.html b/packages/web-components/src/field/field.template.html
new file mode 100644
index 00000000000000..ebf8f7bdbd961b
--- /dev/null
+++ b/packages/web-components/src/field/field.template.html
@@ -0,0 +1,13 @@
+
+
+ {{styles}}
+
+
+
+
+
diff --git a/packages/web-components/src/image/image.styles.css b/packages/web-components/src/image/image.styles.css
new file mode 100644
index 00000000000000..421669e2ed2f7e
--- /dev/null
+++ b/packages/web-components/src/image/image.styles.css
@@ -0,0 +1,50 @@
+:host {
+ contain: content;
+}
+
+:host ::slotted(img) {
+ box-sizing: border-box;
+ min-height: 8px;
+ min-width: 8px;
+ display: inline-block;
+}
+:host([block]) ::slotted(img) {
+ width: 100%;
+ height: auto;
+}
+:host([bordered]) ::slotted(img) {
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke2);
+}
+:host([fit='none']) ::slotted(img) {
+ object-fit: none;
+ object-position: top left;
+ height: 100%;
+ width: 100%;
+}
+:host([fit='center']) ::slotted(img) {
+ object-fit: none;
+ object-position: center;
+ height: 100%;
+ width: 100%;
+}
+:host([fit='contain']) ::slotted(img) {
+ object-fit: contain;
+ object-position: center;
+ height: 100%;
+ width: 100%;
+}
+:host([fit='cover']) ::slotted(img) {
+ object-fit: cover;
+ object-position: center;
+ height: 100%;
+ width: 100%;
+}
+:host([shadow]) ::slotted(img) {
+ box-shadow: var(--shadow4);
+}
+:host([shape='circular']) ::slotted(img) {
+ border-radius: var(--borderRadiusCircular);
+}
+:host([shape='rounded']) ::slotted(img) {
+ border-radius: var(--borderRadiusMedium);
+}
diff --git a/packages/web-components/src/image/image.template.html b/packages/web-components/src/image/image.template.html
new file mode 100644
index 00000000000000..9a0ea89ffec375
--- /dev/null
+++ b/packages/web-components/src/image/image.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/label/label.styles.css b/packages/web-components/src/label/label.styles.css
new file mode 100644
index 00000000000000..7d521f999ab0ca
--- /dev/null
+++ b/packages/web-components/src/label/label.styles.css
@@ -0,0 +1,40 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ color: var(--colorNeutralForeground1);
+ cursor: pointer;
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase300);
+ user-select: none;
+}
+
+.asterisk {
+ color: var(--colorPaletteRedForeground1);
+ margin-inline-start: var(--spacingHorizontalXS);
+}
+
+:host([size='small']) {
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+}
+
+:host([size='large']) {
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host(:is([size='large'], [weight='semibold'])) {
+ font-weight: var(--fontWeightSemibold);
+}
+
+:host([disabled]),
+:host([disabled]) .asterisk {
+ color: var(--colorNeutralForegroundDisabled);
+}
diff --git a/packages/web-components/src/label/label.template.html b/packages/web-components/src/label/label.template.html
new file mode 100644
index 00000000000000..ba1bbf7493ab3c
--- /dev/null
+++ b/packages/web-components/src/label/label.template.html
@@ -0,0 +1,7 @@
+
+
+ {{styles}}
+
+ *
+
+
diff --git a/packages/web-components/src/link/link.styles.css b/packages/web-components/src/link/link.styles.css
new file mode 100644
index 00000000000000..3270cd6b093db0
--- /dev/null
+++ b/packages/web-components/src/link/link.styles.css
@@ -0,0 +1,72 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline;
+}
+
+:host {
+ position: relative;
+ box-sizing: border-box;
+ background-color: transparent;
+ color: var(--colorBrandForegroundLink);
+ cursor: pointer;
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ overflow: inherit;
+ text-align: start;
+ text-decoration: none;
+ text-decoration-thickness: var(--strokeWidthThin);
+ text-overflow: inherit;
+ user-select: text;
+}
+
+:host(:is(:hover, :focus-visible)) {
+ outline: none;
+ text-decoration-line: underline;
+}
+
+@media (hover: hover) {
+ :host(:hover) {
+ color: var(--colorBrandForegroundLinkHover);
+ }
+
+ :host(:active) {
+ color: var(--colorBrandForegroundLinkPressed);
+ }
+
+ :host([appearance='subtle']:hover) {
+ color: var(--colorNeutralForeground2LinkHover);
+ }
+
+ :host([appearance='subtle']:active) {
+ color: var(--colorNeutralForeground2LinkPressed);
+ }
+}
+
+:host([appearance='subtle']) {
+ color: var(--colorNeutralForeground2Link);
+}
+
+:host-context(:is(h1, h2, h3, h4, h5, h6, p, fluent-text)),
+:host([inline]) {
+ font: inherit;
+ text-decoration: underline;
+}
+
+:host(:not([href])) {
+ color: inherit;
+ text-decoration: none;
+}
+
+::slotted(a) {
+ position: absolute;
+ inset: 0;
+}
+
+@media (forced-colors: active) {
+ :host {
+ color: LinkText;
+ }
+}
diff --git a/packages/web-components/src/link/link.template.html b/packages/web-components/src/link/link.template.html
new file mode 100644
index 00000000000000..6014bf970c3e7b
--- /dev/null
+++ b/packages/web-components/src/link/link.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/listbox/listbox.styles.css b/packages/web-components/src/listbox/listbox.styles.css
new file mode 100644
index 00000000000000..6d5232349532a0
--- /dev/null
+++ b/packages/web-components/src/listbox/listbox.styles.css
@@ -0,0 +1,49 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ background-color: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusMedium);
+ border: var(--strokeWidthThin) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow16);
+ box-sizing: border-box;
+ flex-direction: column;
+ margin: 0;
+ min-inline-size: 160px;
+ padding: var(--spacingHorizontalXS);
+ row-gap: var(--spacingHorizontalXXS);
+ width: auto;
+}
+
+:host([popover]) {
+ inset: unset;
+ overflow: auto;
+}
+
+@supports (anchor-name: --anchor) {
+ :host([popover]) {
+ position: fixed;
+ max-block-size: var(--listbox-max-height, calc(50vh - anchor-size(self-block)));
+ min-inline-size: anchor-size(inline);
+ inset-block-start: anchor(end);
+ inset-inline-start: anchor(start);
+ position-try-fallbacks: flip-block, flip-inline, flip-inline flip-block;
+ }
+}
+
+@supports not (anchor-name: --anchor) {
+ :host([popover]) {
+ margin-block-start: var(--margin-offset, 0);
+ max-block-size: var(--listbox-max-height, 50vh);
+ position: absolute;
+ }
+
+ :host([popover]:state(flip-block)) {
+ margin-block-start: revert;
+ translate: 0 -100%;
+ }
+}
diff --git a/packages/web-components/src/listbox/listbox.template.html b/packages/web-components/src/listbox/listbox.template.html
new file mode 100644
index 00000000000000..c4717d05fdb6ec
--- /dev/null
+++ b/packages/web-components/src/listbox/listbox.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/menu-button/menu-button.styles.css b/packages/web-components/src/menu-button/menu-button.styles.css
new file mode 100644
index 00000000000000..15bddfefdbf8a4
--- /dev/null
+++ b/packages/web-components/src/menu-button/menu-button.styles.css
@@ -0,0 +1,268 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --icon-spacing: var(--spacingHorizontalSNudge);
+ position: relative;
+ contain: layout style;
+ vertical-align: middle;
+ align-items: center;
+ box-sizing: border-box;
+ justify-content: center;
+ text-align: center;
+ text-decoration-line: none;
+ margin: 0;
+ min-height: 32px;
+ outline-style: none;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ padding: 0 var(--spacingHorizontalM);
+ min-width: 96px;
+ border-radius: var(--borderRadiusMedium);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ line-height: var(--lineHeightBase300);
+ transition-duration: var(--durationFaster);
+ transition-property: background, border, color;
+ transition-timing-function: var(--curveEasyEase);
+ cursor: pointer;
+ user-select: none;
+}
+
+.content {
+ display: inherit;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground1Hover);
+ border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:hover:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ border-color: var(--colorNeutralStroke1Pressed);
+ color: var(--colorNeutralForeground1Pressed);
+ outline-style: none;
+}
+
+:host(:focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host {
+ transition-duration: 0.01ms;
+ }
+}
+
+::slotted(svg) {
+ font-size: 20px;
+ height: 20px;
+ width: 20px;
+ fill: currentColor;
+}
+
+::slotted([slot='start']) {
+ margin-inline-end: var(--icon-spacing);
+}
+
+::slotted([slot='end']),
+[slot='end'] {
+ flex-shrink: 0;
+ margin-inline-start: var(--icon-spacing);
+}
+
+:host([icon-only]) {
+ min-width: 32px;
+ max-width: 32px;
+}
+
+:host([size='small']) {
+ --icon-spacing: var(--spacingHorizontalXS);
+ min-height: 24px;
+ min-width: 64px;
+ padding: 0 var(--spacingHorizontalS);
+ border-radius: var(--borderRadiusSmall);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small'][icon-only]) {
+ min-width: 24px;
+ max-width: 24px;
+}
+
+:host([size='large']) {
+ min-height: 40px;
+ border-radius: var(--borderRadiusLarge);
+ padding: 0 var(--spacingHorizontalL);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large'][icon-only]) {
+ min-width: 40px;
+ max-width: 40px;
+}
+
+:host([size='large']) ::slotted(svg) {
+ font-size: 24px;
+ height: 24px;
+ width: 24px;
+}
+
+:host(:is([shape='circular'], [shape='circular']:focus-visible)) {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:is([shape='square'], [shape='square']:focus-visible)) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='primary']) {
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ border-color: transparent;
+}
+
+:host([appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host([appearance='primary']:is(:hover, :hover:active):not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host([appearance='primary']:is(:hover, :hover:active)) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([appearance='primary']:hover:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host([appearance='primary']:focus-visible) {
+ border-color: var(--colorNeutralForegroundOnBrand);
+ box-shadow: var(--shadow2), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+:host([appearance='outline']) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='outline']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='outline']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='subtle']) {
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='subtle']:hover:active) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host([appearance='transparent']) {
+ background-color: var(--colorTransparentBackground);
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is([appearance='transparent'], [appearance='transparent']:is(:hover, :active))) {
+ border-color: transparent;
+}
+
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover:active) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+ cursor: not-allowed;
+}
+
+:host([appearance='primary']:is(:disabled, [disabled-focusable])),
+:host([appearance='primary']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+}
+
+:host([appearance='outline']:is(:disabled, [disabled-focusable])),
+:host([appearance='outline']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='subtle']:is(:disabled, [disabled-focusable])),
+:host([appearance='subtle']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+ border-color: transparent;
+}
+
+:host([appearance='transparent']:is(:disabled, [disabled-focusable])),
+:host([appearance='transparent']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+ background-color: var(--colorTransparentBackground);
+}
+
+@media (forced-colors: active) {
+ :host {
+ background-color: ButtonFace;
+ color: ButtonText;
+ }
+
+ :host(:is(:hover, :focus-visible)) {
+ border-color: Highlight !important;
+ }
+
+ :host([appearance='primary']:not(:is(:hover, :focus-visible))) {
+ background-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+
+ :host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])) {
+ background-color: ButtonFace;
+ color: GrayText;
+ border-color: ButtonText;
+ }
+}
diff --git a/packages/web-components/src/menu-button/menu-button.template.html b/packages/web-components/src/menu-button/menu-button.template.html
new file mode 100644
index 00000000000000..18c8a1e2b13e81
--- /dev/null
+++ b/packages/web-components/src/menu-button/menu-button.template.html
@@ -0,0 +1,25 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/menu-item/menu-item.styles.css b/packages/web-components/src/menu-item/menu-item.styles.css
new file mode 100644
index 00000000000000..66e0ccb9721259
--- /dev/null
+++ b/packages/web-components/src/menu-item/menu-item.styles.css
@@ -0,0 +1,154 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: grid;
+}
+
+:host {
+ --indent: 0;
+ align-items: center;
+ background: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusMedium);
+ color: var(--colorNeutralForeground2);
+ contain: layout;
+ cursor: pointer;
+ /* Prevent shrinking of MenuItems when max-height is applied to MenuList */
+ flex-shrink: 0;
+ font: var(--fontWeightRegular) var(--fontSizeBase300) / var(--lineHeightBase300) var(--fontFamilyBase);
+ grid-gap: 4px;
+ grid-template-columns: 20px 20px auto 20px;
+ height: 32px;
+ overflow: visible;
+ padding: 0 10px;
+}
+
+:host(:hover) {
+ background: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground2Hover);
+}
+
+:host(:active) {
+ background-color: var(--colorNeutralBackground1Selected);
+ color: var(--colorNeutralForeground2Pressed);
+}
+
+:host(:active) ::slotted([slot='start']) {
+ color: var(--colorCompoundBrandForeground1Pressed);
+}
+
+:host(:state(disabled)) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host(:state(disabled)) ::slotted([slot='start']),
+:host(:state(disabled)) ::slotted([slot='end']) {
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host(:focus-visible) {
+ border-radius: var(--borderRadiusMedium);
+ outline: 2px solid var(--colorStrokeFocus2);
+}
+
+.content {
+ white-space: nowrap;
+ flex-grow: 1;
+ grid-column: auto / span 2;
+ padding: 0 2px;
+}
+
+:host(:not(:state(checked))) .indicator,
+:host(:not(:state(checked))) ::slotted([slot='indicator']),
+:host(:not(:state(submenu))) .submenu-glyph,
+:host(:not(:state(submenu))) ::slotted([slot='submenu-glyph']) {
+ display: none;
+}
+
+::slotted([slot='end']) {
+ color: var(--colorNeutralForeground3);
+ font: var(--fontWeightRegular) var(--fontSizeBase200) / var(--lineHeightBase200) var(--fontFamilyBase);
+ white-space: nowrap;
+}
+
+:host([data-indent='1']) {
+ --indent: 1;
+}
+
+:host([data-indent='2']) {
+ --indent: 2;
+ grid-template-columns: 20px 20px auto auto;
+}
+
+:host(:state(submenu)) {
+ grid-template-columns: 20px auto auto 20px;
+}
+
+:host([data-indent='2']:state(submenu)) {
+ grid-template-columns: 20px 20px auto auto 20px;
+}
+
+.indicator,
+::slotted([slot='indicator']) {
+ grid-column: 1 / span 1;
+ width: 20px;
+}
+
+::slotted([slot='start']) {
+ display: inline-flex;
+ grid-column: calc(var(--indent)) / span 1;
+}
+
+.content {
+ grid-column: calc(var(--indent) + 1) / span 1;
+}
+
+::slotted([slot='end']) {
+ grid-column: calc(var(--indent) + 2) / span 1;
+ justify-self: end;
+}
+
+.submenu-glyph,
+::slotted([slot='submenu-glyph']) {
+ grid-column: -2 / span 1;
+ justify-self: end;
+}
+
+@layer popover {
+ :host {
+ anchor-name: --menu-trigger;
+ position: relative;
+ }
+
+ ::slotted([popover]) {
+ margin: 0;
+ max-height: var(--menu-max-height, auto);
+ position: fixed;
+ position-anchor: --menu-trigger;
+ inset: unset;
+ inset-block-start: anchor(start);
+ inset-inline-start: anchor(end);
+ position-try-fallbacks: flip-inline, block-start, block-end;
+ z-index: 1;
+ }
+
+ ::slotted([popover]:not(:popover-open)) {
+ display: none;
+ }
+
+ /* Fallback for no anchor-positioning */
+ @supports not (anchor-name: --menu-trigger) {
+ ::slotted([popover]) {
+ align-self: start;
+ }
+ }
+}
+
+@media (forced-colors: active) {
+ :host(:state(disabled)),
+ :host(:state(disabled)) ::slotted([slot='start']),
+ :host(:state(disabled)) ::slotted([slot='end']) {
+ color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/menu-item/menu-item.template.html b/packages/web-components/src/menu-item/menu-item.template.html
new file mode 100644
index 00000000000000..668491e6f3c70e
--- /dev/null
+++ b/packages/web-components/src/menu-item/menu-item.template.html
@@ -0,0 +1,50 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/menu-list/menu-list.styles.css b/packages/web-components/src/menu-list/menu-list.styles.css
new file mode 100644
index 00000000000000..f3fe401c6df15d
--- /dev/null
+++ b/packages/web-components/src/menu-list/menu-list.styles.css
@@ -0,0 +1,20 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: flex;
+}
+
+:host {
+ flex-direction: column;
+ height: fit-content;
+ max-width: 300px;
+ min-width: 160px;
+ width: auto;
+ background-color: var(--colorNeutralBackground1);
+ border: 1px solid var(--colorTransparentStroke);
+ border-radius: var(--borderRadiusMedium);
+ box-shadow: var(--shadow16);
+ padding: 4px;
+ row-gap: 2px;
+}
diff --git a/packages/web-components/src/menu-list/menu-list.template.html b/packages/web-components/src/menu-list/menu-list.template.html
new file mode 100644
index 00000000000000..8438a79c6cc9ff
--- /dev/null
+++ b/packages/web-components/src/menu-list/menu-list.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/menu/menu.styles.css b/packages/web-components/src/menu/menu.styles.css
new file mode 100644
index 00000000000000..f8c38f74652962
--- /dev/null
+++ b/packages/web-components/src/menu/menu.styles.css
@@ -0,0 +1,56 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-block;
+}
+
+::slotted([slot='trigger']) {
+ anchor-name: --menu-trigger;
+}
+
+::slotted([popover]) {
+ margin: 0;
+ max-height: var(--menu-max-height, auto);
+ position-anchor: --menu-trigger;
+ inset: unset;
+ inset-block-start: anchor(end);
+ inset-inline-start: anchor(start);
+ position-try-fallbacks: flip-block;
+ position: fixed;
+ z-index: 1;
+}
+
+:host([split]) ::slotted([popover]) {
+ inset-inline-start: auto;
+ inset-inline-end: anchor(end);
+}
+
+::slotted([popover]:not(:popover-open)) {
+ display: none;
+}
+
+:host([split]) {
+ display: inline-flex;
+}
+
+:host([split]) ::slotted([slot='primary-action']) {
+ border-inline-end: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ border-start-end-radius: 0;
+ border-end-end-radius: 0;
+}
+
+/* Keeps focus visible visuals above trigger slot*/
+:host([split]) ::slotted([slot='primary-action']:focus-visible) {
+ z-index: 1;
+}
+
+:host([split]) ::slotted([slot='primary-action'][appearance='primary']) {
+ border-inline-end: var(--strokeWidthThin) solid white;
+}
+
+:host([split]) ::slotted([slot='trigger']) {
+ border-inline-start: 0;
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+}
diff --git a/packages/web-components/src/menu/menu.template.html b/packages/web-components/src/menu/menu.template.html
new file mode 100644
index 00000000000000..a161e2a932ccbf
--- /dev/null
+++ b/packages/web-components/src/menu/menu.template.html
@@ -0,0 +1,8 @@
+
+
+ {{styles}}
+
+
+
+
+
diff --git a/packages/web-components/src/message-bar/message-bar.styles.css b/packages/web-components/src/message-bar/message-bar.styles.css
new file mode 100644
index 00000000000000..0396ff80154197
--- /dev/null
+++ b/packages/web-components/src/message-bar/message-bar.styles.css
@@ -0,0 +1,97 @@
+:host {
+ display: grid;
+ box-sizing: border-box;
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ width: 100%;
+ background: var(--colorNeutralBackground3);
+ border: 1px solid var(--colorNeutralStroke1);
+ padding-inline: var(--spacingHorizontalM);
+ border-radius: var(--borderRadiusMedium);
+ min-height: 36px;
+ align-items: center;
+ grid-template: 'icon body actions dismiss' / auto 1fr auto auto;
+ contain: layout style paint;
+}
+
+:host([shape='square']) {
+ border-radius: 0;
+}
+
+:host([intent='success']) {
+ background-color: var(--colorPaletteGreenBackground1);
+ border-color: var(--colorPaletteGreenBorder1);
+}
+
+:host([intent='warning']) {
+ background-color: var(--colorPaletteDarkOrangeBackground1);
+ border-color: var(--colorPaletteDarkOrangeBorder1);
+}
+
+:host([intent='error']) {
+ background-color: var(--colorPaletteRedBackground1);
+ border-color: var(--colorPaletteRedBorder1);
+}
+
+:host([layout='multiline']) {
+ grid-template-areas:
+ 'icon body dismiss'
+ 'actions actions actions';
+ grid-template-columns: auto 1fr auto;
+ grid-template-rows: auto auto 1fr;
+ padding-block: var(--spacingVerticalMNudge);
+ padding-inline: var(--spacingHorizontalM);
+}
+
+.content {
+ grid-area: body;
+ max-width: 520px;
+ padding-block: var(--spacingVerticalMNudge);
+ padding-inline: 0;
+}
+
+:host([layout='multiline']) .content {
+ padding: 0;
+}
+
+::slotted([slot='icon']) {
+ display: flex;
+ grid-area: icon;
+ flex-direction: column;
+ align-items: center;
+ color: var(--colorNeutralForeground3);
+ margin-inline-end: var(--spacingHorizontalS);
+}
+
+:host([layout='multiline']) ::slotted([slot='icon']) {
+ align-items: start;
+ height: 100%;
+}
+
+::slotted([slot='dismiss']) {
+ grid-area: dismiss;
+}
+
+.actions {
+ grid-area: actions;
+ display: flex;
+ justify-self: end;
+ margin-inline-end: var(--spacingHorizontalS);
+ gap: var(--spacingHorizontalS);
+}
+
+:host([layout='multiline']) .actions {
+ margin-block-start: var(--spacingVerticalMNudge);
+ margin-inline-end: 0;
+}
+
+:host([layout='multiline']) ::slotted([slot='dismiss']) {
+ align-items: start;
+ height: 100%;
+ padding-block-start: var(--spacingVerticalS);
+}
+
+::slotted(*) {
+ font-size: inherit;
+}
diff --git a/packages/web-components/src/message-bar/message-bar.template.html b/packages/web-components/src/message-bar/message-bar.template.html
new file mode 100644
index 00000000000000..ad121b73950a93
--- /dev/null
+++ b/packages/web-components/src/message-bar/message-bar.template.html
@@ -0,0 +1,13 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/option/option.styles.css b/packages/web-components/src/option/option.styles.css
new file mode 100644
index 00000000000000..cedee7d592ca3b
--- /dev/null
+++ b/packages/web-components/src/option/option.styles.css
@@ -0,0 +1,134 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-grid;
+}
+
+:host {
+ -webkit-tap-highlight-color: transparent;
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+ font-weight: var(--fontWeightRegular);
+
+ align-items: center;
+ background-color: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusMedium);
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground2);
+ column-gap: var(--spacingHorizontalXS);
+ cursor: pointer;
+ grid-template-areas: 'indicator start content';
+ grid-template-columns: auto auto 1fr;
+ min-height: 32px;
+ padding: var(--spacingHorizontalSNudge);
+ text-align: start;
+}
+
+.content {
+ grid-area: content;
+ line-height: 1;
+}
+
+::slotted([slot='start']) {
+ grid-area: start;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground2Hover);
+}
+
+:host(:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ color: var(--colorNeutralForeground2Pressed);
+}
+
+:host(:disabled) {
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForegroundDisabled);
+ cursor: default;
+}
+
+.checkmark-16-filled {
+ fill: currentColor;
+ width: 16px;
+}
+
+slot[name='checked-indicator'] > *,
+::slotted([slot='checked-indicator']) {
+ aspect-ratio: 1;
+ flex: 0 0 auto;
+ grid-area: indicator;
+ visibility: hidden;
+}
+
+:host(:state(selected)) :is(slot[name='checked-indicator'] > *, ::slotted([slot='checked-indicator'])) {
+ visibility: visible;
+}
+
+:host(:state(multiple)) .checkmark-16-filled,
+:host(:not(:state(multiple))) .checkmark-12-regular {
+ display: none;
+}
+
+:host(:state(multiple)) .checkmark-12-regular {
+ background-color: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusSmall);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStrokeAccessible);
+ box-sizing: border-box;
+ cursor: pointer;
+ fill: transparent;
+ position: relative;
+ visibility: visible;
+ width: 16px;
+}
+
+:host(:state(multiple):state(selected)) .checkmark-12-regular {
+ background-color: var(--colorCompoundBrandBackground);
+ border-color: var(--colorCompoundBrandStroke);
+ fill: var(--colorNeutralForegroundInverted);
+}
+
+:host(:disabled:state(multiple)) .checkmark-12-regular {
+ border-color: var(--colorNeutralStrokeDisabled);
+}
+
+:host(:disabled:state(multiple):state(selected)) .checkmark-12-regular {
+ background-color: var(--colorNeutralBackgroundDisabled);
+}
+
+:host(:state(active)) {
+ border: var(--strokeWidthThick) solid var(--colorStrokeFocus2);
+}
+
+@supports (selector(:host(:has(*)))) {
+ :host(:has([slot='start']:not([size='16']))) {
+ column-gap: var(--spacingHorizontalSNudge);
+ }
+}
+
+:host(:state(description)) {
+ column-gap: var(--spacingHorizontalSNudge);
+ grid-template-areas:
+ 'indicator start content'
+ 'indicator start description';
+}
+
+::slotted([slot='description']) {
+ color: var(--colorNeutralForeground3);
+ grid-area: description;
+
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+@media (forced-colors: active) {
+ :host(:disabled) {
+ color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/option/option.template.html b/packages/web-components/src/option/option.template.html
new file mode 100644
index 00000000000000..e35a86ae20b6f4
--- /dev/null
+++ b/packages/web-components/src/option/option.template.html
@@ -0,0 +1,24 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/progress-bar/progress-bar.styles.css b/packages/web-components/src/progress-bar/progress-bar.styles.css
new file mode 100644
index 00000000000000..e8dd83b7e5e887
--- /dev/null
+++ b/packages/web-components/src/progress-bar/progress-bar.styles.css
@@ -0,0 +1,103 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ width: 100%;
+ height: 2px;
+ overflow-x: hidden;
+ background-color: var(--colorNeutralBackground6);
+ border-radius: var(--borderRadiusMedium);
+ contain: content;
+
+ @supports (width: attr(value type())) {
+ --max: attr(max type(), 100);
+ --min: attr(min type(), 0);
+ --value: attr(value type(), 0);
+ --indicator-width: clamp(0%, calc((var(--value) - var(--min)) / (var(--max) - var(--min)) * 100%), 100%);
+ }
+}
+
+:host([thickness='large']) {
+ height: 4px;
+}
+
+:host([shape='square']) {
+ border-radius: var(--borderRadiusNone);
+}
+
+.indicator {
+ background-color: var(--colorCompoundBrandBackground);
+ border-radius: inherit;
+ height: 100%;
+}
+
+:host([value]) .indicator {
+ transition: all 0.2s ease-in-out;
+
+ @supports (width: attr(value type())) {
+ width: var(--indicator-width);
+ }
+}
+
+:host(:not([value])) .indicator {
+ position: relative;
+ width: 33%;
+ background-image: linear-gradient(
+ to right,
+ var(--colorNeutralBackground6) 0%,
+ var(--colorTransparentBackground) 50%,
+ var(--colorNeutralBackground6) 100%
+ );
+ animation-name: indeterminate;
+ animation-duration: 3s;
+ animation-timing-function: linear;
+ animation-iteration-count: infinite;
+}
+
+:host([validation-state='error']) .indicator {
+ background-color: var(--colorPaletteRedBackground3);
+}
+
+:host([validation-state='warning']) .indicator {
+ background-color: var(--colorPaletteDarkOrangeBackground3);
+}
+
+:host([validation-state='success']) .indicator {
+ background-color: var(--colorPaletteGreenBackground3);
+}
+
+@layer animations {
+ /* Disable animations for reduced motion */
+ @media (prefers-reduced-motion: no-preference) {
+ :host([value]) {
+ transition: none;
+ }
+ :host(:not([value])) .indicator {
+ animation-duration: 0.01ms;
+ animation-iteration-count: 1;
+ }
+ }
+}
+
+@keyframes indeterminate {
+ 0% {
+ inset-inline-start: -33%;
+ }
+ 100% {
+ inset-inline-start: 100%;
+ }
+}
+
+@media (forced-colors: active) {
+ :host {
+ background-color: CanvasText;
+ }
+ .indicator,
+ :host(:is([validation-state='success'], [validation-state='warning'], [validation-state='error'])) .indicator {
+ background-color: Highlight;
+ }
+}
diff --git a/packages/web-components/src/progress-bar/progress-bar.template.html b/packages/web-components/src/progress-bar/progress-bar.template.html
new file mode 100644
index 00000000000000..7ae32b218b0856
--- /dev/null
+++ b/packages/web-components/src/progress-bar/progress-bar.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/radio-group/radio-group.styles.css b/packages/web-components/src/radio-group/radio-group.styles.css
new file mode 100644
index 00000000000000..fbf9149f2f7f57
--- /dev/null
+++ b/packages/web-components/src/radio-group/radio-group.styles.css
@@ -0,0 +1,45 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: flex;
+}
+
+:host {
+ -webkit-tap-highlight-color: transparent;
+ cursor: pointer;
+ gap: var(--spacingVerticalL);
+}
+
+:host([orientation='vertical']) {
+ flex-direction: column;
+ justify-content: flex-start;
+}
+
+:host([orientation='horizontal']) {
+ flex-direction: row;
+}
+
+::slotted(*) {
+ color: var(--colorNeutralForeground3);
+}
+
+::slotted(:hover) {
+ color: var(--colorNeutralForeground2);
+}
+
+::slotted(:active) {
+ color: var(--colorNeutralForeground1);
+}
+
+::slotted(:state(disabled)) {
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+::slotted(:state(checked)) {
+ color: var(--colorNeutralForeground1);
+}
+
+:host([slot='input']) {
+ margin: var(--spacingVerticalS) var(--spacingHorizontalS);
+}
diff --git a/packages/web-components/src/radio-group/radio-group.template.html b/packages/web-components/src/radio-group/radio-group.template.html
new file mode 100644
index 00000000000000..12026df49510b3
--- /dev/null
+++ b/packages/web-components/src/radio-group/radio-group.template.html
@@ -0,0 +1,13 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/radio/radio.styles.css b/packages/web-components/src/radio/radio.styles.css
new file mode 100644
index 00000000000000..44c8056cf5de4e
--- /dev/null
+++ b/packages/web-components/src/radio/radio.styles.css
@@ -0,0 +1,119 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --size: 16px;
+ aspect-ratio: 1;
+ background-color: var(--colorNeutralBackground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStrokeAccessible);
+ border-radius: var(--borderRadiusCircular);
+ box-sizing: border-box;
+ position: relative;
+ width: var(--size);
+}
+
+:host([size='large']) {
+ --size: 20px;
+}
+
+.checked-indicator {
+ aspect-ratio: 1;
+ border-radius: var(--borderRadiusCircular);
+ color: var(--colorNeutralForegroundInverted);
+ inset: 0;
+ margin: auto;
+ position: absolute;
+ width: calc(var(--size) * 0.625);
+}
+
+:host(:not([slot='input']))::after {
+ content: '' / '';
+ position: absolute;
+ display: block;
+ inset: -8px;
+ box-sizing: border-box;
+ outline: none;
+ border: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ border-radius: var(--borderRadiusMedium);
+}
+
+:host(:not([slot='input']):focus-visible)::after {
+ border-color: var(--colorStrokeFocus2);
+}
+
+:host(:hover) {
+ border-color: var(--colorNeutralStrokeAccessibleHover);
+}
+
+:host(:state(checked)) {
+ border-color: var(--colorCompoundBrandStroke);
+}
+
+:host(:state(checked)) .checked-indicator {
+ background-color: var(--colorCompoundBrandBackground);
+}
+
+:host(:state(checked):hover) .checked-indicator {
+ background-color: var(--colorCompoundBrandBackgroundHover);
+}
+
+:host(:active) {
+ border-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+
+:host(:state(checked):active) .checked-indicator {
+ background-color: var(--colorCompoundBrandBackgroundPressed);
+}
+
+:host(:focus-visible) {
+ outline: none;
+}
+
+:host(:state(disabled)) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+}
+
+:host(:state(checked):state(disabled)) .checked-indicator {
+ background-color: var(--colorNeutralStrokeDisabled);
+}
+
+@media (forced-colors: active) {
+ :host {
+ border-color: FieldText;
+ }
+
+ :host(:not([slot='input']:focus-visible))::after {
+ border-color: Canvas;
+ }
+
+ :host(:not(:state(disabled)):hover),
+ :host(:not([slot='input']):focus-visible)::after {
+ border-color: Highlight;
+ }
+
+ .checked-indicator {
+ color: HighlightText;
+ }
+
+ :host(:state(checked)) .checked-indicator {
+ background-color: FieldText;
+ }
+
+ :host(:state(checked):not(:state(disabled)):hover) .checked-indicator {
+ background-color: Highlight;
+ }
+
+ :host(:state(disabled)) {
+ border-color: GrayText;
+ color: GrayText;
+ }
+
+ :host(:state(disabled):state(checked)) .checked-indicator {
+ background-color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/radio/radio.template.html b/packages/web-components/src/radio/radio.template.html
new file mode 100644
index 00000000000000..264fc63357fc62
--- /dev/null
+++ b/packages/web-components/src/radio/radio.template.html
@@ -0,0 +1,8 @@
+
+
+ {{styles}}
+
+
+
+
+
diff --git a/packages/web-components/src/rating-display/rating-display.styles.css b/packages/web-components/src/rating-display/rating-display.styles.css
new file mode 100644
index 00000000000000..38ce65999637fb
--- /dev/null
+++ b/packages/web-components/src/rating-display/rating-display.styles.css
@@ -0,0 +1,142 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --_icon-size: 16px;
+ --_icon-gradient-degree: 90deg;
+ --_icon-color-value: var(--colorPaletteMarigoldBorderActive);
+ --_icon-color-empty: var(--colorPaletteMarigoldBackground2);
+ --_default-value: 0;
+ --_default-max: 5;
+ --_mask-image-filled: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2012%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5.28347%201.54605C5.57692%200.951448%206.42479%200.951449%206.71825%201.54605L7.82997%203.79866L10.3159%204.15988C10.9721%204.25523%2011.2341%205.0616%2010.7592%205.52443L8.96043%207.27785L9.38507%209.7537C9.49716%2010.4072%208.81122%2010.9056%208.22431%2010.597L6.00086%209.4281L3.7774%2010.597C3.19049%2010.9056%202.50455%2010.4072%202.61664%209.7537L3.04128%207.27784L1.24246%205.52443C0.767651%205.0616%201.02966%204.25523%201.68584%204.15988L4.17174%203.79865L5.28347%201.54605Z%22%20%2F%3E%3C%2Fsvg%3E);
+ --_mask-image-outlined: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2012%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%3E%3Cpath%20d%3D%22M5.28347%201.54605C5.57692%200.951448%206.42479%200.951449%206.71825%201.54605L7.82997%203.79866L10.3159%204.15988C10.9721%204.25523%2011.2341%205.0616%2010.7592%205.52443L8.96043%207.27785L9.38507%209.7537C9.49716%2010.4072%208.81122%2010.9056%208.22431%2010.597L6.00086%209.4281L3.7774%2010.597C3.19049%2010.9056%202.50455%2010.4072%202.61664%209.7537L3.04128%207.27784L1.24246%205.52443C0.767651%205.0616%201.02966%204.25523%201.68584%204.15988L4.17174%203.79865L5.28347%201.54605Z%22%20%2F%3E%3C%2Fsvg%3E);
+ --_mask-position-x: left;
+
+ align-items: center;
+ color: var(--colorNeutralForeground1);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ contain: layout style;
+ user-select: none;
+}
+
+:host(:dir(rtl)) {
+ --_icon-gradient-degree: -90deg;
+ --_mask-position-x: right;
+}
+
+:host([size='small']) {
+ --_icon-size: 12px;
+}
+
+:host([size='large']) {
+ --_icon-size: 20px;
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+}
+
+::slotted([slot='icon']) {
+ display: none;
+}
+
+:host([color='neutral']) {
+ --_icon-color-value: var(--colorNeutralForeground1);
+ --_icon-color-empty: var(--colorNeutralBackground6);
+}
+
+:host([color='brand']) {
+ --_icon-color-value: var(--colorBrandForeground1);
+ --_icon-color-empty: var(--colorBrandBackground2);
+}
+
+@supports (width: attr(value type())) {
+ :host {
+ --_attr-value: attr(value type());
+ --_attr-max: attr(max type());
+ }
+}
+
+:host([compact]) .display {
+ --_max: 1;
+}
+
+.display {
+ --_value: max(0, round(var(--_attr-value, var(--_default-value)) * 2) / 2);
+ --_max: max(1, var(--_attr-max, var(--_default-max)));
+ --_mask-inline-size: calc(var(--_icon-size) + var(--spacingHorizontalXXS));
+ --_icon-gradient-stop-visual-adjustment: 0px;
+ --_icon-gradient-stop: calc(var(--_mask-inline-size) * var(--_value) - var(--_icon-gradient-stop-visual-adjustment));
+
+ background-image: linear-gradient(
+ var(--_icon-gradient-degree),
+ var(--_icon-color-value) var(--_icon-gradient-stop),
+ var(--_icon-color-empty) calc(var(--_icon-gradient-stop) + 0.5px)
+ );
+ block-size: var(--_icon-size);
+ display: grid;
+ inline-size: calc(var(--_max) * var(--_mask-inline-size) - var(--spacingHorizontalXXS) / 2);
+ mask-image: var(--_mask-image-filled);
+ mask-repeat: repeat no-repeat;
+ mask-size: var(--_mask-inline-size) var(--_icon-size);
+ mask-position: var(--_mask-position-x) center;
+}
+
+.value-label,
+::slotted([slot='value']) {
+ display: block;
+ margin-inline-start: var(--spacingHorizontalXS);
+ font-weight: var(--fontWeightSemibold);
+}
+
+:host([size='small']) .value-label,
+:host([size='small']) ::slotted([slot='value']) {
+ margin-inline-start: var(--spacingHorizontalXXS);
+}
+
+:host([size='large']) .value-label,
+:host([size='large']) ::slotted([slot='value']) {
+ margin-inline-start: var(--spacingHorizontalSNudge);
+}
+
+:host(:not([count])) .count-label {
+ display: none;
+}
+
+.count-label::before,
+::slotted([slot='count'])::before {
+ content: '·';
+ margin-inline: var(--spacingHorizontalXS);
+}
+
+:host([size='small']) .count-label::before,
+:host([size='small']) ::slotted([slot='count'])::before {
+ margin-inline: var(--spacingHorizontalXXS);
+}
+
+:host([size='large']) .count-label::before,
+:host([size='large']) ::slotted([slot='count'])::before {
+ margin-inline: var(--spacingHorizontalSNudge);
+}
+
+@media (forced-colors: active) {
+ .display {
+ --_icon-color-value: CanvasText;
+ --_icon-color-empty: Canvas;
+ --_icon-gradient-stop-visual-adjustment: 0.5px;
+
+ forced-color-adjust: none;
+ }
+
+ .display::before {
+ background-color: var(--_icon-color-value);
+ content: '';
+ grid-area: 1 / 1 / -1 / -1;
+ mask: inherit;
+ mask-image: var(--_mask-image-outlined);
+ }
+}
diff --git a/packages/web-components/src/rating-display/rating-display.template.html b/packages/web-components/src/rating-display/rating-display.template.html
new file mode 100644
index 00000000000000..9d90f91bb4402c
--- /dev/null
+++ b/packages/web-components/src/rating-display/rating-display.template.html
@@ -0,0 +1,9 @@
+
+
+ {{styles}}
+
+
+ {{value}}
+ {{formattedCount}}
+
+
diff --git a/packages/web-components/src/slider/slider.styles.css b/packages/web-components/src/slider/slider.styles.css
new file mode 100644
index 00000000000000..2bbf60a4e9abf0
--- /dev/null
+++ b/packages/web-components/src/slider/slider.styles.css
@@ -0,0 +1,193 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-grid;
+}
+
+:host {
+ --thumb-size: 20px;
+ --track-margin-inline: calc(var(--thumb-size) / 2);
+ --track-size: 4px;
+ --track-overhang: calc(var(--track-size) / -2);
+ --rail-color: var(--colorCompoundBrandBackground);
+ --track-color: var(--colorNeutralStrokeAccessible);
+ --slider-direction: 90deg;
+ --border-radius: var(--borderRadiusMedium);
+ --step-marker-inset: var(--track-overhang) -1px;
+
+ position: relative;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ outline: none;
+ user-select: none;
+ touch-action: none;
+ min-width: 120px;
+ min-height: 32px;
+ grid-template-rows: 1fr var(--thumb-size) 1fr;
+ grid-template-columns: var(--track-margin-inline) 1fr var(--track-margin-inline);
+}
+
+:host(:hover) {
+ --rail-color: var(--colorCompoundBrandBackgroundHover);
+}
+
+:host(:active) {
+ --rail-color: var(--colorCompoundBrandBackgroundPressed);
+}
+
+:host(:disabled) {
+ --rail-color: var(--colorNeutralForegroundDisabled);
+ --track-color: var(--colorNeutralBackgroundDisabled);
+}
+
+:host(:not(:disabled)) {
+ cursor: pointer;
+}
+
+:host(:dir(rtl)) {
+ --slider-direction: -90deg;
+}
+
+:host([size='small']) {
+ --thumb-size: 16px;
+ --track-overhang: -1px;
+ --track-size: 2px;
+ --border-radius: var(--borderRadiusSmall);
+}
+
+:host([orientation='vertical']) {
+ --slider-direction: 0deg;
+ --step-marker-inset: -1px var(--track-overhang);
+ min-height: 120px;
+ grid-template-rows: var(--track-margin-inline) 1fr var(--track-margin-inline);
+ grid-template-columns: 1fr var(--thumb-size) 1fr;
+ width: unset;
+ min-width: 32px;
+ justify-items: center;
+}
+
+:host(:not([slot='input']):focus-visible) {
+ box-shadow: 0 0 0 2pt var(--colorStrokeFocus2);
+ outline: 1px solid var(--colorStrokeFocus1);
+}
+
+:host:after,
+.track {
+ height: var(--track-size);
+ width: 100%;
+}
+
+:host:after {
+ background-image: linear-gradient(
+ var(--slider-direction),
+ var(--rail-color) 0%,
+ var(--rail-color) 50%,
+ var(--track-color) 50.1%,
+ var(--track-color) 100%
+ );
+ border-radius: var(--border-radius);
+ content: '';
+ grid-row: 1 / -1;
+ grid-column: 1 / -1;
+}
+
+.track {
+ position: relative;
+ background-color: var(--track-color);
+ grid-row: 2 / 2;
+ grid-column: 2 / 2;
+ forced-color-adjust: none;
+ overflow: hidden;
+}
+
+:host([orientation='vertical'])::after,
+:host([orientation='vertical']) .track {
+ height: 100%;
+ width: var(--track-size);
+}
+
+.track::before {
+ content: '';
+ position: absolute;
+ height: 100%;
+ border-radius: inherit;
+ inset-inline-start: 0;
+ width: var(--slider-progress);
+}
+
+:host(:dir(rtl)) .track::before {
+ width: calc(100% - var(--slider-progress));
+}
+
+:host([orientation='vertical']) .track::before {
+ width: 100%;
+ bottom: 0;
+ height: var(--slider-progress);
+}
+
+:host([step]) .track::after {
+ content: '';
+ position: absolute;
+ border-radius: inherit;
+ inset: var(--step-marker-inset);
+ background-image: repeating-linear-gradient(
+ var(--slider-direction),
+ #0000 0%,
+ #0000 calc(var(--step-rate) - 1px),
+ var(--colorNeutralBackground1) calc(var(--step-rate) - 1px),
+ var(--colorNeutralBackground1) var(--step-rate)
+ );
+}
+
+.thumb-container {
+ position: absolute;
+ grid-row: 2 / 2;
+ grid-column: 2 / 2;
+ transform: translateX(-50%);
+ left: var(--slider-thumb);
+}
+
+:host([orientation='vertical']) .thumb-container {
+ transform: translateY(50%);
+ left: unset;
+ bottom: var(--slider-thumb);
+}
+
+:host(:not(:active)) :is(.thumb-container, .track::before) {
+ transition: all 0.2s ease;
+}
+
+.thumb {
+ width: var(--thumb-size);
+ height: var(--thumb-size);
+ border-radius: var(--borderRadiusCircular);
+ box-shadow: 0 0 0 calc(var(--thumb-size) * 0.2) var(--colorNeutralBackground1) inset;
+ border: calc(var(--thumb-size) * 0.05) solid var(--colorNeutralStroke1);
+ box-sizing: border-box;
+}
+
+.thumb,
+.track::before {
+ background-color: var(--rail-color);
+}
+
+@media (forced-colors: active) {
+ .track:hover,
+ .track:active,
+ .track {
+ background: WindowText;
+ }
+ .thumb:hover,
+ .thumb:active,
+ .thumb {
+ background: ButtonText;
+ }
+
+ :host(:hover) .track::before,
+ :host(:active) .track::before,
+ .track::before {
+ background: Highlight;
+ }
+}
diff --git a/packages/web-components/src/slider/slider.template.html b/packages/web-components/src/slider/slider.template.html
new file mode 100644
index 00000000000000..c22e67a795ab96
--- /dev/null
+++ b/packages/web-components/src/slider/slider.template.html
@@ -0,0 +1,15 @@
+
+
+ {{styles}}
+
+
+
+
diff --git a/packages/web-components/src/spinner/spinner.styles.css b/packages/web-components/src/spinner/spinner.styles.css
new file mode 100644
index 00000000000000..c6917a81357622
--- /dev/null
+++ b/packages/web-components/src/spinner/spinner.styles.css
@@ -0,0 +1,159 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --duration: 1.5s;
+ --indicatorSize: var(--strokeWidthThicker);
+ --size: 32px;
+ height: var(--size);
+ width: var(--size);
+ contain: strict;
+ content-visibility: auto;
+}
+
+:host([size='tiny']) {
+ --indicatorSize: var(--strokeWidthThick);
+ --size: 20px;
+}
+:host([size='extra-small']) {
+ --indicatorSize: var(--strokeWidthThick);
+ --size: 24px;
+}
+:host([size='small']) {
+ --indicatorSize: var(--strokeWidthThick);
+ --size: 28px;
+}
+:host([size='large']) {
+ --indicatorSize: var(--strokeWidthThicker);
+ --size: 36px;
+}
+:host([size='extra-large']) {
+ --indicatorSize: var(--strokeWidthThicker);
+ --size: 40px;
+}
+:host([size='huge']) {
+ --indicatorSize: var(--strokeWidthThickest);
+ --size: 44px;
+}
+
+.progress,
+.background,
+.spinner,
+.start,
+.end,
+.indicator {
+ position: absolute;
+ inset: 0;
+}
+
+.progress,
+.spinner,
+.indicator {
+ animation: none var(--duration) infinite var(--curveEasyEase);
+}
+
+.progress {
+ animation-timing-function: linear;
+ animation-name: spin-linear;
+}
+
+.background {
+ border: var(--indicatorSize) solid var(--colorBrandStroke2);
+ border-radius: 50%;
+}
+
+:host([appearance='inverted']) .background {
+ border-color: rgba(255, 255, 255, 0.2);
+}
+
+.spinner {
+ animation-name: spin-swing;
+}
+
+.start {
+ overflow: hidden;
+ right: 50%;
+}
+
+.end {
+ overflow: hidden;
+ left: 50%;
+}
+
+.indicator {
+ color: var(--colorBrandStroke1);
+ box-sizing: border-box;
+ border-radius: 50%;
+ border: var(--indicatorSize) solid transparent;
+ border-block-start-color: currentcolor;
+ border-right-color: currentcolor;
+}
+
+:host([appearance='inverted']) .indicator {
+ color: var(--colorNeutralStrokeOnBrand2);
+}
+
+.start .indicator {
+ rotate: 135deg; /* Starts 9 o'clock */
+ inset: 0 -100% 0 0;
+ animation-name: spin-start;
+}
+
+.end .indicator {
+ rotate: 135deg; /* Ends at 3 o'clock */
+ inset: 0 0 0 -100%;
+ animation-name: spin-end;
+}
+
+@keyframes spin-linear {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes spin-swing {
+ 0% {
+ transform: rotate(-135deg);
+ }
+ 50% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(225deg);
+ }
+}
+
+@keyframes spin-start {
+ 0%,
+ 100% {
+ transform: rotate(0deg);
+ }
+ 50% {
+ transform: rotate(-80deg);
+ }
+}
+
+@keyframes spin-end {
+ 0%,
+ 100% {
+ transform: rotate(0deg);
+ }
+ 50% {
+ transform: rotate(70deg);
+ }
+}
+
+@media (forced-colors: active) {
+ .background {
+ display: none;
+ }
+ .indicator {
+ border-color: Canvas;
+ border-block-start-color: Highlight;
+ border-right-color: Highlight;
+ }
+}
diff --git a/packages/web-components/src/spinner/spinner.template.html b/packages/web-components/src/spinner/spinner.template.html
new file mode 100644
index 00000000000000..fdd76233d952a0
--- /dev/null
+++ b/packages/web-components/src/spinner/spinner.template.html
@@ -0,0 +1,18 @@
+
+
+ {{styles}}
+
+
+
+
+
+
diff --git a/packages/web-components/src/switch/switch.styles.css b/packages/web-components/src/switch/switch.styles.css
new file mode 100644
index 00000000000000..822b4a1d2908d1
--- /dev/null
+++ b/packages/web-components/src/switch/switch.styles.css
@@ -0,0 +1,125 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ box-sizing: border-box;
+ align-items: center;
+ flex-direction: row;
+ outline: none;
+ user-select: none;
+ contain: content;
+ padding: 0 var(--spacingHorizontalXXS);
+ width: 40px;
+ height: 20px;
+ background-color: var(--colorTransparentBackground);
+ border: 1px solid var(--colorNeutralStrokeAccessible);
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:enabled) {
+ cursor: pointer;
+}
+
+:host(:hover) {
+ background: none;
+ border-color: var(--colorNeutralStrokeAccessibleHover);
+}
+:host(:active) {
+ border-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+:host(:disabled),
+:host([readonly]) {
+ border: 1px solid var(--colorNeutralStrokeDisabled);
+ background-color: none;
+ pointer: default;
+}
+:host(:state(checked)) {
+ background: var(--colorCompoundBrandBackground);
+ border-color: var(--colorCompoundBrandBackground);
+}
+:host(:state(checked):hover) {
+ background: var(--colorCompoundBrandBackgroundHover);
+ border-color: var(--colorCompoundBrandBackgroundHover);
+}
+:host(:state(checked):active) {
+ background: var(--colorCompoundBrandBackgroundPressed);
+ border-color: var(--colorCompoundBrandBackgroundPressed);
+}
+:host(:state(checked):disabled) {
+ background: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+}
+.checked-indicator {
+ height: 14px;
+ width: 14px;
+ border-radius: 50%;
+ margin-inline-start: 0;
+ background-color: var(--colorNeutralForeground3);
+ transition-duration: var(--durationNormal);
+ transition-timing-function: var(--curveEasyEase);
+ transition-property: margin-inline-start;
+}
+:host(:state(checked)) .checked-indicator {
+ background-color: var(--colorNeutralForegroundInverted);
+ margin-inline-start: calc(100% - 14px);
+}
+:host(:state(checked):hover) .checked-indicator {
+ background: var(--colorNeutralForegroundInvertedHover);
+}
+:host(:state(checked):active) .checked-indicator {
+ background: var(--colorNeutralForegroundInvertedPressed);
+}
+:host(:hover) .checked-indicator {
+ background-color: var(--colorNeutralForeground3Hover);
+}
+:host(:active) .checked-indicator {
+ background-color: var(--colorNeutralForeground3Pressed);
+}
+:host(:disabled) .checked-indicator,
+:host([readonly]) .checked-indicator {
+ background: var(--colorNeutralForegroundDisabled);
+}
+:host(:state(checked):disabled) .checked-indicator {
+ background: var(--colorNeutralForegroundDisabled);
+}
+
+:host(:focus-visible) {
+ outline: none;
+}
+
+:host(:not([slot='input']):focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ outline-offset: 1px;
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media (forced-colors: active) {
+ :host {
+ border-color: InactiveBorder;
+ }
+ :host(:state(checked)),
+ :host(:state(checked):active),
+ :host(:state(checked):hover) {
+ background: Highlight;
+ border-color: Highlight;
+ }
+ .checked-indicator,
+ :host(:hover) .checked-indicator,
+ :host(:active) .checked-indicator {
+ background-color: ActiveCaption;
+ }
+ :host(:state(checked)) .checked-indicator,
+ :host(:state(checked):hover) .checked-indicator,
+ :host(:state(checked):active) .checked-indicator {
+ background-color: ButtonFace;
+ }
+ :host(:disabled) .checked-indicator,
+ :host(:state(checked):disabled) .checked-indicator {
+ background-color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/switch/switch.template.html b/packages/web-components/src/switch/switch.template.html
new file mode 100644
index 00000000000000..d1c16abd84f018
--- /dev/null
+++ b/packages/web-components/src/switch/switch.template.html
@@ -0,0 +1,11 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/tab/tab.styles.css b/packages/web-components/src/tab/tab.styles.css
new file mode 100644
index 00000000000000..a22fc5f5173a18
--- /dev/null
+++ b/packages/web-components/src/tab/tab.styles.css
@@ -0,0 +1,122 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ position: relative;
+ flex-direction: row;
+ align-items: center;
+ cursor: pointer;
+ box-sizing: border-box;
+ justify-content: center;
+ line-height: var(--lineHeightBase300);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ color: var(--colorNeutralForeground2);
+ fill: currentcolor;
+ grid-row: 1;
+ padding: var(--spacingHorizontalM) var(--spacingHorizontalMNudge);
+ border-radius: var(--borderRadiusMedium);
+ gap: 4px;
+}
+:host .tab-content {
+ display: inline-flex;
+ flex-direction: column;
+ padding: 0 2px;
+}
+
+:host([aria-selected='true']) {
+ color: var(--colorNeutralForeground1);
+ font-weight: var(--fontWeightSemibold);
+}
+
+/* adds hidden textContent to prevent shifting ui on bold / unbolding of text */
+:host .tab-content::after {
+ content: var(--textContent);
+ visibility: hidden;
+ height: 0;
+ line-height: var(--lineHeightBase300);
+ font-weight: var(--fontWeightSemibold);
+}
+
+:host([aria-selected='true'])::after {
+ background-color: var(--colorCompoundBrandStroke);
+ border-radius: var(--borderRadiusCircular);
+ content: '';
+ inset: 0;
+ position: absolute;
+ z-index: 2;
+}
+
+:host([aria-selected='false']:hover)::after {
+ background-color: var(--colorNeutralStroke1Hover);
+ border-radius: var(--borderRadiusCircular);
+ content: '';
+ inset: 0;
+ position: absolute;
+ z-index: 1;
+}
+
+/*
+ * TODO: Remove '(text-size-adjust: auto)' after this bug is fixed:
+ * https://bugs.webkit.org/show_bug.cgi?id=298646
+ * Also remove the same trick from tablist.styles.ts.
+ * Using '@supports (text-size-adjust: auto)' here to exclude Safari 26 from
+ * using CSS Anchor Positioning here because it crashes.
+ */
+@supports (anchor-name: --a) and (text-size-adjust: auto) {
+ :host([aria-selected='true'])::after {
+ background-color: transparent;
+ }
+
+ :host([aria-selected='true']:hover)::after {
+ background-color: var(--colorNeutralStroke1Hover);
+ }
+}
+
+:host([aria-selected='true'][disabled])::after {
+ background-color: var(--colorNeutralForegroundDisabled);
+}
+
+::slotted([slot='start']),
+::slotted([slot='end']) {
+ display: flex;
+}
+:host([disabled]) {
+ cursor: not-allowed;
+ fill: var(--colorNeutralForegroundDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+ pointer-events: none;
+}
+
+:host([disabled]:hover)::after {
+ background-color: unset;
+}
+
+:host(:focus) {
+ outline: none;
+}
+
+:host(:focus-visible) {
+ border-radius: var(--borderRadiusSmall);
+ box-shadow: 0 0 0 3px var(--colorStrokeFocus2);
+ outline: 1px solid var(--colorStrokeFocus1);
+}
+
+:host([data-hasIndent]) {
+ display: grid;
+ grid-template-columns: 20px 1fr auto;
+}
+
+:host([data-hasIndent]) .tab-content {
+ grid-column: 2;
+}
+
+@media (forced-colors: active) {
+ :host([aria-selected='true'])::after {
+ background-color: Highlight;
+ }
+}
diff --git a/packages/web-components/src/tab/tab.template.html b/packages/web-components/src/tab/tab.template.html
new file mode 100644
index 00000000000000..94f56b8b924208
--- /dev/null
+++ b/packages/web-components/src/tab/tab.template.html
@@ -0,0 +1,8 @@
+
+
+ {{styles}}
+
+
+
+
+
diff --git a/packages/web-components/src/tablist/tablist.styles.css b/packages/web-components/src/tablist/tablist.styles.css
new file mode 100644
index 00000000000000..71072de4988047
--- /dev/null
+++ b/packages/web-components/src/tablist/tablist.styles.css
@@ -0,0 +1,207 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: flex;
+}
+
+:host {
+ --tabPaddingInline: var(--spacingHorizontalMNudge);
+ --tabPaddingBlock: var(--spacingHorizontalM);
+ --tabIndicatorInsetInline: var(--tabPaddingInline);
+ --tabIndicatorInsetBlock: 0;
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground2);
+ flex-direction: row;
+ position: relative;
+}
+
+:host([size='small']) {
+ --tabPaddingBlock: var(--spacingVerticalSNudge);
+ --tabPaddingInline: var(--spacingHorizontalSNudge);
+}
+
+:host([size='large']) {
+ --tabPaddingBlock: var(--spacingVerticalL);
+ --tabPaddingInline: var(--spacingHorizontalMNudge);
+}
+
+:host([orientation='vertical']) {
+ --tabPaddingBlock: var(--spacingVerticalS);
+ --tabIndicatorInsetBlock: var(--spacingVerticalS);
+ flex-direction: column;
+}
+
+:host([orientation='vertical'][size='small']) {
+ --tabPaddingBlock: var(--spacingVerticalXXS);
+ --tabIndicatorInsetBlock: var(--spacingVerticalSNudge);
+}
+
+:host([orientation='vertical'][size='large']) {
+ --tabPaddingBlock: var(--spacingVerticalS);
+ --tabIndicatorInsetBlock: var(--spacingVerticalMNudge);
+}
+
+::slotted([slot='tab']) {
+ padding-inline: var(--tabPaddingInline);
+ padding-block: var(--tabPaddingBlock);
+}
+
+:host([orientation='vertical']) ::slotted([role='tab']) {
+ justify-content: flex-start;
+}
+
+:host ::slotted([slot='tab'])::after {
+ height: var(--strokeWidthThicker);
+ margin-block-start: auto;
+}
+
+:host([orientation='vertical']) ::slotted([slot='tab'])::after {
+ width: var(--strokeWidthThicker);
+ height: unset;
+ margin-block-start: unset;
+}
+
+/* ::before adds a secondary indicator placeholder that appears right after click on the active tab */
+:host ::slotted([slot='tab'])::before {
+ height: var(--strokeWidthThicker);
+ border-radius: var(--borderRadiusCircular);
+ content: '';
+ inset-inline: var(--tabIndicatorInsetInline);
+ inset-block: var(--tabIndicatorInsetBlock);
+ position: absolute;
+ margin-top: auto;
+}
+
+:host ::slotted([slot='tab'])::before {
+ inset-inline: var(--tabIndicatorInsetInline);
+ inset-block: var(--tabIndicatorInsetBlock);
+}
+
+:host ::slotted([slot='tab'][aria-selected='true'])::before {
+ background-color: var(--colorNeutralForegroundDisabled);
+}
+
+:host ::slotted([slot='tab'][aria-selected='false']:hover)::after {
+ height: var(--strokeWidthThicker);
+ margin-block-start: auto;
+ transform-origin: left;
+}
+
+:host([orientation='vertical']) ::slotted([slot='tab'])::before,
+:host([orientation='vertical']) ::slotted([slot='tab'][aria-selected='false']:hover)::after {
+ height: unset;
+ width: var(--strokeWidthThicker);
+ margin-inline-end: auto;
+ transform-origin: top;
+}
+
+:host([size='small']) ::slotted([slot='tab']) {
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+}
+
+:host([size='large']) ::slotted([slot='tab']) {
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+/* horizontal spacing for indicator */
+:host ::slotted([slot='tab'])::after,
+:host ::slotted([slot='tab'])::before,
+:host ::slotted([slot='tab']:hover)::after {
+ inset-inline: var(--tabIndicatorInsetInline);
+}
+
+:host([orientation='vertical']) ::slotted([slot='tab'])::after,
+:host([orientation='vertical']) ::slotted([slot='tab'])::before,
+:host([orientation='vertical']) ::slotted([slot='tab']:hover)::after {
+ inset-inline: 0;
+ inset-block: var(--tabIndicatorInsetBlock);
+}
+
+/* disabled styles */
+:host([disabled]) {
+ cursor: not-allowed;
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([disabled]) ::slotted([slot='tab']) {
+ pointer-events: none;
+ cursor: not-allowed;
+ color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([disabled]) ::slotted([slot='tab']:after) {
+ background-color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([disabled]) ::slotted([slot='tab'][aria-selected='true'])::after {
+ background-color: var(--colorNeutralForegroundDisabled);
+}
+
+:host([disabled]) ::slotted([slot='tab']:hover):before {
+ content: unset;
+}
+
+:host([appearance='subtle']) ::slotted([slot='tab']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground1Hover);
+ fill: var(--colorCompoundBrandForeground1Hover);
+}
+
+:host([appearance='subtle']) ::slotted([slot='tab']:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ fill: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground1);
+}
+
+/*
+ * TODO: Remove '(text-size-adjust: auto)' after this bug is fixed:
+ * https://bugs.webkit.org/show_bug.cgi?id=298646
+ * Also remove the same trick from tab.styles.ts.
+ * Using '@supports (text-size-adjust: auto)' here to exclude Safari 26 from
+ * using CSS Anchor Positioning here because it crashes.
+ */
+@supports (anchor-name: --a) and (text-size-adjust: auto) {
+ ::slotted([slot='tab'][aria-selected='true']) {
+ anchor-name: --tab;
+ }
+
+ :host::after {
+ background-color: var(--colorCompoundBrandStroke);
+ content: '';
+ inline-size: 100%;
+ inset: auto auto anchor(end) anchor(center);
+ position: fixed;
+ position-anchor: --tab;
+ transform: translateX(-50%);
+ transition-property: inset-inline, width;
+ transition-duration: var(--durationSlow);
+ transition-timing-function: var(--curveDecelerateMax);
+ z-index: 3;
+
+ /* These styles should be in sync with tab.styles.ts’s :host::after */
+ border-radius: var(--borderRadiusCircular);
+ width: calc(anchor-size() - var(--tabIndicatorInsetInline) * 2);
+ height: var(--strokeWidthThicker);
+ }
+
+ :host([orientation='vertical'])::after {
+ inset: anchor(center) anchor(end) auto 0;
+ transform: translateY(-50%);
+ transition-property: inset-block, height;
+
+ /* These styles should be in sync with #vertical-tab-highlight above */
+ width: var(--strokeWidthThicker);
+ height: calc(anchor-size() - var(--tabIndicatorInsetBlock) * 2);
+ }
+
+ :host(:dir(rtl)[orientation='vertical'])::after {
+ inset: anchor(center) anchor(start) auto 0;
+ }
+
+ :host([disabled])::after {
+ background-color: var(--colorNeutralForegroundDisabled);
+ }
+}
diff --git a/packages/web-components/src/tablist/tablist.template.html b/packages/web-components/src/tablist/tablist.template.html
new file mode 100644
index 00000000000000..f436038c4e8aba
--- /dev/null
+++ b/packages/web-components/src/tablist/tablist.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/text-input/text-input.styles.css b/packages/web-components/src/text-input/text-input.styles.css
new file mode 100644
index 00000000000000..9a6e4d09ee3b83
--- /dev/null
+++ b/packages/web-components/src/text-input/text-input.styles.css
@@ -0,0 +1,204 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase300);
+ max-width: 400px;
+}
+.label {
+ display: flex;
+ color: var(--colorNeutralForeground1);
+ padding-bottom: var(--spacingVerticalXS);
+ flex-shrink: 0;
+ padding-inline-end: var(--spacingHorizontalXS);
+}
+
+.label[hidden],
+:host(:empty) .label {
+ display: none;
+}
+
+.root {
+ align-items: center;
+ background-color: var(--colorNeutralBackground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ border-bottom-color: var(--colorNeutralStrokeAccessible);
+ border-radius: var(--borderRadiusMedium);
+ box-sizing: border-box;
+ height: 32px;
+ display: inline-flex;
+ flex-direction: row;
+ gap: var(--spacingHorizontalXXS);
+ padding: 0 var(--spacingHorizontalMNudge);
+ position: relative;
+ width: 100%;
+}
+
+:has(.control:user-invalid) {
+ border-color: var(--colorPaletteRedBorder2);
+}
+
+.root::after {
+ box-sizing: border-box;
+ content: '';
+ position: absolute;
+ left: -1px;
+ bottom: 0px;
+ right: -1px;
+ height: max(2px, var(--borderRadiusMedium));
+ border-radius: 0 0 var(--borderRadiusMedium) var(--borderRadiusMedium);
+ border-bottom: 2px solid var(--colorCompoundBrandStroke);
+ clip-path: inset(calc(100% - 2px) 1px 0px);
+ transform: scaleX(0);
+ transition-property: transform;
+ transition-duration: var(--durationUltraFast);
+ transition-delay: var(--curveAccelerateMid);
+}
+.control {
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground1);
+ border-radius: var(--borderRadiusMedium);
+ background: var(--colorTransparentBackground);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightRegular);
+ font-size: var(--fontSizeBase300);
+ border: none;
+ vertical-align: center;
+}
+.control:focus-visible {
+ outline: 0;
+ border: 0;
+}
+.control::placeholder {
+ color: var(--colorNeutralForeground4);
+}
+:host ::slotted([slot='start']),
+:host ::slotted([slot='end']) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--colorNeutralForeground3);
+ font-size: var(--fontSizeBase500);
+}
+:host ::slotted([slot='start']) {
+ padding-right: var(--spacingHorizontalXXS);
+}
+:host ::slotted([slot='end']) {
+ padding-left: var(--spacingHorizontalXXS);
+ gap: var(--spacingHorizontalXS);
+}
+:host(:hover) .root {
+ border-color: var(--colorNeutralStroke1Hover);
+ border-bottom-color: var(--colorNeutralStrokeAccessibleHover);
+}
+:host(:active) .root {
+ border-color: var(--colorNeutralStroke1Pressed);
+}
+:host(:focus-within) .root {
+ outline: transparent solid 2px;
+ border-bottom: 0;
+}
+:host(:focus-within) .root::after {
+ transform: scaleX(1);
+ transition-property: transform;
+ transition-duration: var(--durationNormal);
+ transition-delay: var(--curveDecelerateMid);
+}
+:host(:focus-within:active) .root:after {
+ border-bottom-color: var(--colorCompoundBrandStrokePressed);
+}
+:host([appearance='outline']:focus-within) .root {
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+}
+:host(:focus-within) .control {
+ color: var(--colorNeutralForeground1);
+}
+:host([disabled]) .root {
+ background: var(--colorTransparentBackground);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStrokeDisabled);
+}
+:host([disabled]) .control::placeholder,
+:host([disabled]) ::slotted([slot='start']),
+:host([disabled]) ::slotted([slot='end']) {
+ color: var(--colorNeutralForegroundDisabled);
+}
+::selection {
+ color: var(--colorNeutralForegroundInverted);
+ background-color: var(--colorNeutralBackgroundInverted);
+}
+:host([control-size='small']) .control {
+ font-size: var(--fontSizeBase200);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase200);
+}
+:host([control-size='small']) .root {
+ height: 24px;
+ gap: var(--spacingHorizontalXXS);
+ padding: 0 var(--spacingHorizontalSNudge);
+}
+:host([control-size='small']) ::slotted([slot='start']),
+:host([control-size='small']) ::slotted([slot='end']) {
+ font-size: var(--fontSizeBase400);
+}
+:host([control-size='large']) .control {
+ font-size: var(--fontSizeBase400);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--lineHeightBase400);
+}
+:host([control-size='large']) .root {
+ height: 40px;
+ gap: var(--spacingHorizontalS);
+ padding: 0 var(--spacingHorizontalM);
+}
+:host([control-size='large']) ::slotted([slot='start']),
+:host([control-size='large']) ::slotted([slot='end']) {
+ font-size: var(--fontSizeBase600);
+}
+:host([appearance='underline']) .root {
+ background: var(--colorTransparentBackground);
+ border: 0;
+ border-radius: 0;
+ border-bottom: var(--strokeWidthThin) solid var(--colorNeutralStrokeAccessible);
+}
+:host([appearance='underline']:hover) .root {
+ border-bottom-color: var(--colorNeutralStrokeAccessibleHover);
+}
+:host([appearance='underline']:active) .root {
+ border-bottom-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+:host([appearance='underline']:focus-within) .root {
+ border: 0;
+ border-bottom-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+:host([appearance='underline'][disabled]) .root {
+ border-bottom-color: var(--colorNeutralStrokeDisabled);
+}
+:host([appearance='filled-lighter']) .root,
+:host([appearance='filled-darker']) .root {
+ border: var(--strokeWidthThin) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow2);
+}
+:host([appearance='filled-lighter']) .root {
+ background: var(--colorNeutralBackground1);
+}
+:host([appearance='filled-darker']) .root {
+ background: var(--colorNeutralBackground3);
+}
+:host([appearance='filled-lighter']:hover) .root,
+:host([appearance='filled-darker']:hover) .root {
+ border-color: var(--colorTransparentStrokeInteractive);
+}
+:host([appearance='filled-lighter']:active) .root,
+:host([appearance='filled-darker']:active) .root {
+ border-color: var(--colorTransparentStrokeInteractive);
+ background: var(--colorNeutralBackground3);
+}
diff --git a/packages/web-components/src/text-input/text-input.template.html b/packages/web-components/src/text-input/text-input.template.html
new file mode 100644
index 00000000000000..838b1bd2c548a3
--- /dev/null
+++ b/packages/web-components/src/text-input/text-input.template.html
@@ -0,0 +1,36 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/text/text.styles.css b/packages/web-components/src/text/text.styles.css
new file mode 100644
index 00000000000000..8320322aea1bfb
--- /dev/null
+++ b/packages/web-components/src/text/text.styles.css
@@ -0,0 +1,108 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline;
+}
+
+:host {
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+ font-weight: var(--fontWeightRegular);
+ text-align: start;
+}
+
+:host([nowrap]),
+:host([nowrap]) ::slotted(*) {
+ white-space: nowrap;
+ overflow: hidden;
+}
+:host([truncate]),
+:host([truncate]) ::slotted(*) {
+ text-overflow: ellipsis;
+}
+:host([block]) {
+ display: block;
+}
+:host([italic]) {
+ font-style: italic;
+}
+:host([underline]) {
+ text-decoration-line: underline;
+}
+:host([strikethrough]) {
+ text-decoration-line: line-through;
+}
+:host([underline][strikethrough]) {
+ text-decoration-line: line-through underline;
+}
+:host([size='100']) {
+ font-size: var(--fontSizeBase100);
+ line-height: var(--lineHeightBase100);
+}
+:host([size='200']) {
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+}
+:host([size='400']) {
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+:host([size='500']) {
+ font-size: var(--fontSizeBase500);
+ line-height: var(--lineHeightBase500);
+}
+:host([size='600']) {
+ font-size: var(--fontSizeBase600);
+ line-height: var(--lineHeightBase600);
+}
+:host([size='700']) {
+ font-size: var(--fontSizeHero700);
+ line-height: var(--lineHeightHero700);
+}
+:host([size='800']) {
+ font-size: var(--fontSizeHero800);
+ line-height: var(--lineHeightHero800);
+}
+:host([size='900']) {
+ font-size: var(--fontSizeHero900);
+ line-height: var(--lineHeightHero900);
+}
+:host([size='1000']) {
+ font-size: var(--fontSizeHero1000);
+ line-height: var(--lineHeightHero1000);
+}
+:host([font='monospace']) {
+ font-family: var(--fontFamilyMonospace);
+}
+:host([font='numeric']) {
+ font-family: var(--fontFamilyNumeric);
+}
+:host([weight='medium']) {
+ font-weight: var(--fontWeightMedium);
+}
+:host([weight='semibold']) {
+ font-weight: var(--fontWeightSemibold);
+}
+:host([weight='bold']) {
+ font-weight: var(--fontWeightBold);
+}
+:host([align='center']) {
+ text-align: center;
+}
+:host([align='end']) {
+ text-align: end;
+}
+:host([align='justify']) {
+ text-align: justify;
+}
+
+::slotted(*) {
+ font: inherit;
+ line-height: inherit;
+ text-decoration-line: inherit;
+ text-align: inherit;
+ text-decoration-line: inherit;
+ margin: 0;
+}
diff --git a/packages/web-components/src/text/text.template.html b/packages/web-components/src/text/text.template.html
new file mode 100644
index 00000000000000..1985e9c8cccacc
--- /dev/null
+++ b/packages/web-components/src/text/text.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/textarea/textarea.styles.css b/packages/web-components/src/textarea/textarea.styles.css
new file mode 100644
index 00000000000000..dd49fb6e1b0655
--- /dev/null
+++ b/packages/web-components/src/textarea/textarea.styles.css
@@ -0,0 +1,262 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-block;
+}
+
+:host {
+ /* typography */
+ --font-size: var(--fontSizeBase300);
+ --line-height: var(--lineHeightBase300);
+
+ /* layout */
+ --padding-inline: var(--spacingHorizontalMNudge);
+ --padding-block: var(--spacingVerticalSNudge);
+ --min-block-size: 52px;
+ --block-size: var(--min-block-size);
+ --inline-size: 18rem;
+ --border-width: var(--strokeWidthThin);
+ --control-padding-inline: var(--spacingHorizontalXXS);
+
+ /* colors */
+ --color: var(--colorNeutralForeground1);
+ --background-color: var(--colorNeutralBackground1);
+ --border-color: var(--colorNeutralStroke1);
+ --border-block-end-color: var(--colorNeutralStrokeAccessible);
+ --placeholder-color: var(--colorNeutralForeground4);
+ --focus-indicator-color: var(--colorCompoundBrandStroke);
+
+ /* elevations */
+ --box-shadow: none;
+
+ /* others */
+ --contain-size: size;
+ --resize: none;
+
+ color: var(--color);
+ font-family: var(--fontFamilyBase);
+ font-size: var(--font-size);
+ font-weight: var(--fontWeightRegular);
+ line-height: var(--line-height);
+ position: relative;
+}
+
+:host(:hover) {
+ --border-color: var(--colorNeutralStroke1Hover);
+ --border-block-end-color: var(--colorNeutralStrokeAccessibleHover);
+}
+
+:host(:active) {
+ --border-color: var(--colorNeutralStroke1Pressed);
+ --border-block-end-color: var(--colorNeutralStrokeAccessiblePressed);
+}
+
+:host(:focus-within) {
+ outline: none;
+}
+
+:host([block]:not([hidden])) {
+ display: block;
+}
+
+:host([size='small']) {
+ --font-size: var(--fontSizeBase200);
+ --line-height: var(--lineHeightBase200);
+ --min-block-size: 40px;
+ --padding-block: var(--spacingVerticalXS);
+ --padding-inline: var(--spacingHorizontalSNudge);
+ --control-padding-inline: var(--spacingHorizontalXXS);
+}
+
+:host([size='large']) {
+ --font-size: var(--fontSizeBase400);
+ --line-height: var(--lineHeightBase400);
+ --min-block-size: 64px;
+ --padding-block: var(--spacingVerticalS);
+ --padding-inline: var(--spacingHorizontalM);
+ --control-padding-inline: var(--spacingHorizontalSNudge);
+}
+
+:host([resize='both']:not(:disabled)) {
+ --resize: both;
+}
+
+:host([resize='horizontal']:not(:disabled)) {
+ --resize: horizontal;
+}
+
+:host([resize='vertical']:not(:disabled)) {
+ --resize: vertical;
+}
+
+:host([auto-resize]) {
+ --block-size: auto;
+ --contain-size: inline-size;
+}
+
+:host([appearance='filled-darker']) {
+ --background-color: var(--colorNeutralBackground3);
+ --border-color: var(--background-color);
+ --border-block-end-color: var(--border-color);
+}
+
+:host([appearance='filled-lighter']) {
+ --border-color: var(--background-color);
+ --border-block-end-color: var(--border-color);
+}
+
+:host([appearance='filled-darker'][display-shadow]),
+:host([appearance='filled-lighter'][display-shadow]) {
+ --box-shadow: var(--shadow2);
+}
+
+:host(:state(user-invalid)) {
+ --border-color: var(--colorPaletteRedBorder2);
+ --border-block-end-color: var(--colorPaletteRedBorder2);
+}
+
+:host(:disabled) {
+ --color: var(--colorNeutralForegroundDisabled);
+ --background-color: var(--colorTransparentBackground);
+ --border-color: var(--colorNeutralStrokeDisabled);
+ --border-block-end-color: var(--border-color);
+ --box-shadow: none;
+ --placeholder-color: var(--colorNeutralForegroundDisabled);
+
+ cursor: no-drop;
+ user-select: none;
+}
+
+.root {
+ background-color: var(--background-color);
+ border: var(--border-width) solid var(--border-color);
+ border-block-end-color: var(--border-block-end-color);
+ border-radius: var(--borderRadiusMedium);
+ box-sizing: border-box;
+ box-shadow: var(--box-shadow);
+ contain: paint layout style var(--contain-size);
+ display: grid;
+ grid-template: 1fr / 1fr;
+ inline-size: var(--inline-size);
+ min-block-size: var(--min-block-size);
+ block-size: var(--block-size);
+ overflow: hidden;
+ padding: var(--padding-block) var(--padding-inline);
+ position: relative;
+ resize: var(--resize);
+}
+
+:host([block]) .root {
+ inline-size: auto;
+}
+
+.root::after {
+ border-bottom: 2px solid var(--focus-indicator-color);
+ border-radius: 0 0 var(--borderRadiusMedium) var(--borderRadiusMedium);
+ box-sizing: border-box;
+ clip-path: inset(calc(100% - 2px) 1px 0px);
+ content: '';
+ height: max(2px, var(--borderRadiusMedium));
+ inset: auto -1px 0;
+ position: absolute;
+ transform: scaleX(0);
+ transition-delay: var(--curveAccelerateMid);
+ transition-duration: var(--durationUltraFast);
+ transition-property: transform;
+}
+
+:host(:focus-within) .root::after {
+ transform: scaleX(1);
+ transition-property: transform;
+ transition-duration: var(--durationNormal);
+ transition-delay: var(--curveDecelerateMid);
+}
+
+:host([readonly]) .root::after,
+:host(:disabled) .root::after {
+ content: none;
+}
+
+label {
+ color: var(--color);
+ display: flex;
+ inline-size: fit-content;
+ padding-block-end: var(--spacingVerticalXS);
+ padding-inline-end: var(--spacingHorizontalXS);
+}
+
+:host(:empty) label,
+label[hidden] {
+ display: none;
+}
+
+.auto-sizer,
+.control {
+ box-sizing: border-box;
+ font: inherit;
+ grid-column: 1 / -1;
+ grid-row: 1 / -1;
+ letter-space: inherit;
+ padding: 0 var(--control-padding-inline);
+}
+
+.auto-sizer {
+ display: none;
+ padding-block-end: 2px; /* avoid scroll bar in Firefox */
+ pointer-events: none;
+ visibility: hidden;
+ white-space: pre-wrap;
+}
+
+:host([auto-resize]) .auto-sizer {
+ display: block;
+}
+
+.control {
+ appearance: none;
+ background-color: transparent;
+ border: 0;
+ color: inherit;
+ field-sizing: content;
+ max-block-size: 100%;
+ outline: 0;
+ resize: none;
+ text-align: inherit;
+}
+
+.control:disabled {
+ cursor: inherit;
+}
+
+.control::placeholder {
+ color: var(--placeholder-color);
+}
+
+::selection {
+ color: var(--colorNeutralForegroundInverted);
+ background-color: var(--colorNeutralBackgroundInverted);
+}
+
+@media (forced-colors: active) {
+ :host {
+ --border-color: FieldText;
+ --border-block-end-color: FieldText;
+ --focus-indicator-color: Highlight;
+ --placeholder-color: FieldText;
+ }
+
+ :host(:hover),
+ :host(:active),
+ :host(:focus-within) {
+ --border-color: Highlight;
+ --border-block-end-color: Highlight;
+ }
+
+ :host(:disabled) {
+ --color: GrayText;
+ --border-color: GrayText;
+ --border-block-end-color: GrayText;
+ --placeholder-color: GrayText;
+ }
+}
diff --git a/packages/web-components/src/textarea/textarea.template.html b/packages/web-components/src/textarea/textarea.template.html
new file mode 100644
index 00000000000000..83216b4cecdf6e
--- /dev/null
+++ b/packages/web-components/src/textarea/textarea.template.html
@@ -0,0 +1,30 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/toggle-button/toggle-button.styles.css b/packages/web-components/src/toggle-button/toggle-button.styles.css
new file mode 100644
index 00000000000000..adf5b9833e8848
--- /dev/null
+++ b/packages/web-components/src/toggle-button/toggle-button.styles.css
@@ -0,0 +1,361 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host {
+ --icon-spacing: var(--spacingHorizontalSNudge);
+ position: relative;
+ contain: layout style;
+ vertical-align: middle;
+ align-items: center;
+ box-sizing: border-box;
+ justify-content: center;
+ text-align: center;
+ text-decoration-line: none;
+ margin: 0;
+ min-height: 32px;
+ outline-style: none;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+ border: var(--strokeWidthThin) solid var(--colorNeutralStroke1);
+ padding: 0 var(--spacingHorizontalM);
+ min-width: 96px;
+ border-radius: var(--borderRadiusMedium);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ font-weight: var(--fontWeightSemibold);
+ line-height: var(--lineHeightBase300);
+ transition-duration: var(--durationFaster);
+ transition-property: background, border, color;
+ transition-timing-function: var(--curveEasyEase);
+ cursor: pointer;
+ user-select: none;
+}
+
+.content {
+ display: inherit;
+}
+
+:host(:hover) {
+ background-color: var(--colorNeutralBackground1Hover);
+ color: var(--colorNeutralForeground1Hover);
+ border-color: var(--colorNeutralStroke1Hover);
+}
+
+:host(:hover:active) {
+ background-color: var(--colorNeutralBackground1Pressed);
+ border-color: var(--colorNeutralStroke1Pressed);
+ color: var(--colorNeutralForeground1Pressed);
+ outline-style: none;
+}
+
+:host(:focus-visible) {
+ border-color: var(--colorTransparentStroke);
+ outline: var(--strokeWidthThick) solid var(--colorTransparentStroke);
+ box-shadow: var(--shadow4), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ :host {
+ transition-duration: 0.01ms;
+ }
+}
+
+::slotted(svg) {
+ font-size: 20px;
+ height: 20px;
+ width: 20px;
+ fill: currentColor;
+}
+
+::slotted([slot='start']) {
+ margin-inline-end: var(--icon-spacing);
+}
+
+::slotted([slot='end']),
+[slot='end'] {
+ flex-shrink: 0;
+ margin-inline-start: var(--icon-spacing);
+}
+
+:host([icon-only]) {
+ min-width: 32px;
+ max-width: 32px;
+}
+
+:host([size='small']) {
+ --icon-spacing: var(--spacingHorizontalXS);
+ min-height: 24px;
+ min-width: 64px;
+ padding: 0 var(--spacingHorizontalS);
+ border-radius: var(--borderRadiusSmall);
+ font-size: var(--fontSizeBase200);
+ line-height: var(--lineHeightBase200);
+ font-weight: var(--fontWeightRegular);
+}
+
+:host([size='small'][icon-only]) {
+ min-width: 24px;
+ max-width: 24px;
+}
+
+:host([size='large']) {
+ min-height: 40px;
+ border-radius: var(--borderRadiusLarge);
+ padding: 0 var(--spacingHorizontalL);
+ font-size: var(--fontSizeBase400);
+ line-height: var(--lineHeightBase400);
+}
+
+:host([size='large'][icon-only]) {
+ min-width: 40px;
+ max-width: 40px;
+}
+
+:host([size='large']) ::slotted(svg) {
+ font-size: 24px;
+ height: 24px;
+ width: 24px;
+}
+
+:host(:is([shape='circular'], [shape='circular']:focus-visible)) {
+ border-radius: var(--borderRadiusCircular);
+}
+
+:host(:is([shape='square'], [shape='square']:focus-visible)) {
+ border-radius: var(--borderRadiusNone);
+}
+
+:host([appearance='primary']) {
+ background-color: var(--colorBrandBackground);
+ color: var(--colorNeutralForegroundOnBrand);
+ border-color: transparent;
+}
+
+:host([appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host([appearance='primary']:is(:hover, :hover:active):not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host([appearance='primary']:is(:hover, :hover:active)) {
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host([appearance='primary']:hover:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host([appearance='primary']:focus-visible) {
+ border-color: var(--colorNeutralForegroundOnBrand);
+ box-shadow: var(--shadow2), 0 0 0 2px var(--colorStrokeFocus2);
+}
+
+:host([appearance='outline']) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='outline']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='outline']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='subtle']) {
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+ border-color: transparent;
+}
+
+:host([appearance='subtle']:hover) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='subtle']:hover:active) ::slotted(svg) {
+ fill: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host([appearance='transparent']) {
+ background-color: var(--colorTransparentBackground);
+ color: var(--colorNeutralForeground2);
+}
+
+:host([appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host([appearance='transparent']:hover:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+:host(:is([appearance='transparent'], [appearance='transparent']:is(:hover, :active))) {
+ border-color: transparent;
+}
+
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover),
+:host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable]):hover:active) {
+ background-color: var(--colorNeutralBackgroundDisabled);
+ border-color: var(--colorNeutralStrokeDisabled);
+ color: var(--colorNeutralForegroundDisabled);
+ cursor: not-allowed;
+}
+
+:host([appearance='primary']:is(:disabled, [disabled-focusable])),
+:host([appearance='primary']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+}
+
+:host([appearance='outline']:is(:disabled, [disabled-focusable])),
+:host([appearance='outline']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='subtle']:is(:disabled, [disabled-focusable])),
+:host([appearance='subtle']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ background-color: var(--colorTransparentBackground);
+ border-color: transparent;
+}
+
+:host([appearance='transparent']:is(:disabled, [disabled-focusable])),
+:host([appearance='transparent']:is(:disabled, [disabled-focusable]):is(:hover, :hover:active)) {
+ border-color: transparent;
+ background-color: var(--colorTransparentBackground);
+}
+
+@media (forced-colors: active) {
+ :host {
+ background-color: ButtonFace;
+ color: ButtonText;
+ }
+
+ :host(:is(:hover, :focus-visible)) {
+ border-color: Highlight !important;
+ }
+
+ :host([appearance='primary']:not(:is(:hover, :focus-visible))) {
+ background-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+
+ :host(:is(:disabled, [disabled-focusable], [appearance]:disabled, [appearance][disabled-focusable])) {
+ background-color: ButtonFace;
+ color: GrayText;
+ border-color: ButtonText;
+ }
+}
+
+:host(:state(pressed)) {
+ border-color: var(--colorNeutralStroke1);
+ background-color: var(--colorNeutralBackground1Selected);
+ color: var(--colorNeutralForeground1);
+ border-width: var(--strokeWidthThin);
+}
+
+:host(:state(pressed):hover) {
+ border-color: var(--colorNeutralStroke1Hover);
+ background-color: var(--colorNeutralBackground1Hover);
+}
+
+:host(:state(pressed):active) {
+ border-color: var(--colorNeutralStroke1Pressed);
+ background-color: var(--colorNeutralBackground1Pressed);
+}
+
+:host(:state(pressed)[appearance='primary']:not(:focus-visible)) {
+ border-color: transparent;
+}
+
+:host(:state(pressed)[appearance='primary']) {
+ background-color: var(--colorBrandBackgroundSelected);
+ color: var(--colorNeutralForegroundOnBrand);
+}
+
+:host(:state(pressed)[appearance='primary']:hover) {
+ background-color: var(--colorBrandBackgroundHover);
+}
+
+:host(:state(pressed)[appearance='primary']:active) {
+ background-color: var(--colorBrandBackgroundPressed);
+}
+
+:host(:state(pressed)[appearance='subtle']) {
+ border-color: transparent;
+ background-color: var(--colorSubtleBackgroundSelected);
+ color: var(--colorNeutralForeground2Selected);
+}
+
+:host(:state(pressed)[appearance='subtle']:hover) {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+}
+
+:host(:state(pressed)[appearance='subtle']:active) {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+}
+
+:host(:state(pressed)[appearance='outline']),
+:host(:state(pressed)[appearance='transparent']) {
+ background-color: var(--colorTransparentBackgroundSelected);
+}
+
+:host(:state(pressed)[appearance='outline']:hover),
+:host(:state(pressed)[appearance='transparent']:hover) {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host(:state(pressed)[appearance='outline']:active),
+:host(:state(pressed)[appearance='transparent']:active) {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host(:state(pressed)[appearance='transparent']) {
+ border-color: transparent;
+ color: var(--colorNeutralForeground2BrandSelected);
+}
+
+:host(:state(pressed)[appearance='transparent']:hover) {
+ color: var(--colorNeutralForeground2BrandHover);
+}
+
+:host(:state(pressed)[appearance='transparent']:active) {
+ color: var(--colorNeutralForeground2BrandPressed);
+}
+
+@media (forced-colors: active) {
+ :host(:state(pressed)),
+ :host(
+ :state(pressed):is(
+ [appearance='primary'],
+ [appearance='subtle'],
+ [appearance='outline'],
+ [appearance='transparent']
+ )
+ ) {
+ background: SelectedItem;
+ color: SelectedItemText;
+ }
+}
diff --git a/packages/web-components/src/toggle-button/toggle-button.template.html b/packages/web-components/src/toggle-button/toggle-button.template.html
new file mode 100644
index 00000000000000..c95388c7c2b0a8
--- /dev/null
+++ b/packages/web-components/src/toggle-button/toggle-button.template.html
@@ -0,0 +1,10 @@
+
+
+ {{styles}}
+
+
+
+
+
+
+
diff --git a/packages/web-components/src/tooltip/tooltip.styles.css b/packages/web-components/src/tooltip/tooltip.styles.css
new file mode 100644
index 00000000000000..ecf0ff7b9a69f6
--- /dev/null
+++ b/packages/web-components/src/tooltip/tooltip.styles.css
@@ -0,0 +1,90 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: inline-flex;
+}
+
+:host(:not(:popover-open)) {
+ display: none;
+}
+
+:host {
+ --position-area: block-start;
+ --position-try-options: flip-block;
+ --block-offset: var(--spacingVerticalXS);
+ --inline-offset: var(--spacingHorizontalXS);
+ background: var(--colorNeutralBackground1);
+ border-radius: var(--borderRadiusMedium);
+ border: 1px solid var(--colorTransparentStroke);
+ box-sizing: border-box;
+ color: var(--colorNeutralForeground1);
+ display: inline-flex;
+ filter: drop-shadow(0 0 2px var(--colorNeutralShadowAmbient)) drop-shadow(0 4px 8px var(--colorNeutralShadowKey));
+ font-family: var(--fontFamilyBase);
+ font-size: var(--fontSizeBase200);
+ inset: unset;
+ line-height: var(--lineHeightBase200);
+ margin: unset; /* Remove browser default for [popover] */
+ max-width: 240px;
+ overflow: visible;
+ padding: 4px var(--spacingHorizontalMNudge) 6px;
+ position: absolute;
+ position-area: var(--position-area);
+ position-try-fallbacks: var(--position-try-options);
+ width: auto;
+ z-index: 1;
+}
+
+@supports (inset-area: block-start) {
+ :host {
+ inset-area: var(--position-area);
+ position-try-fallbacks: var(--position-try-options);
+ }
+}
+
+:host(:is([positioning^='above'], [positioning^='below'], :not([positioning]))) {
+ margin-block: var(--block-offset);
+}
+
+:host(:is([positioning^='before'], [positioning^='after'])) {
+ margin-inline: var(--inline-offset);
+ --position-try-options: flip-inline;
+}
+
+:host([positioning='above-start']) {
+ --position-area: block-start span-inline-end;
+}
+:host([positioning='above']) {
+ --position-area: block-start;
+}
+:host([positioning='above-end']) {
+ --position-area: block-start span-inline-start;
+}
+:host([positioning='below-start']) {
+ --position-area: block-end span-inline-end;
+}
+:host([positioning='below']) {
+ --position-area: block-end;
+}
+:host([positioning='below-end']) {
+ --position-area: block-end span-inline-start;
+}
+:host([positioning='before-top']) {
+ --position-area: inline-start span-block-end;
+}
+:host([positioning='before']) {
+ --position-area: inline-start;
+}
+:host([positioning='before-bottom']) {
+ --position-area: inline-start span-block-start;
+}
+:host([positioning='after-top']) {
+ --position-area: inline-end span-block-end;
+}
+:host([positioning='after']) {
+ --position-area: inline-end;
+}
+:host([positioning='after-bottom']) {
+ --position-area: inline-end span-block-start;
+}
diff --git a/packages/web-components/src/tooltip/tooltip.template.html b/packages/web-components/src/tooltip/tooltip.template.html
new file mode 100644
index 00000000000000..81399e9401f64a
--- /dev/null
+++ b/packages/web-components/src/tooltip/tooltip.template.html
@@ -0,0 +1,6 @@
+
+
+ {{styles}}
+
+
+
diff --git a/packages/web-components/src/tree-item/tree-item.styles.css b/packages/web-components/src/tree-item/tree-item.styles.css
new file mode 100644
index 00000000000000..e1889226efb1d3
--- /dev/null
+++ b/packages/web-components/src/tree-item/tree-item.styles.css
@@ -0,0 +1,161 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ outline: none;
+ font-size: var(--fontSizeBase300);
+ line-height: var(--lineHeightBase300);
+}
+
+:host(:focus-visible) .positioning-region {
+ box-shadow: var(--spacingVerticalNone) var(--spacingVerticalNone) var(--spacingVerticalNone) var(--spacingVerticalXXS)
+ var(--colorStrokeFocus2) inset;
+}
+
+/**
+ * Default variants:
+ * Size - medium
+ * Appearance - subtle
+ */
+.positioning-region {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ cursor: pointer;
+ height: var(--spacingVerticalXXXL);
+ padding-inline-start: calc(var(--indent) * var(--spacingHorizontalXXL));
+ padding-inline-end: var(--spacingVerticalS);
+ border-radius: var(--borderRadiusMedium);
+ background-color: var(--colorSubtleBackground);
+ color: var(--colorNeutralForeground2);
+ gap: var(--spacingHorizontalXS);
+}
+
+@media (prefers-contrast: more) {
+ :host(:focus-visible) .positioning-region {
+ outline: 1px solid var(--colorStrokeFocus2);
+ }
+}
+
+.content {
+ display: flex;
+ align-items: center;
+ gap: var(--spacingHorizontalXS);
+}
+
+.chevron {
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ justify-content: center;
+ width: var(--spacingHorizontalXXL);
+ height: var(--spacingVerticalXXL);
+ transition: transform var(--durationFaster) var(--curveEasyEaseMax);
+ transform: rotate(0deg);
+}
+
+.chevron:dir(rtl) {
+ transform: rotate(180deg);
+}
+
+.chevron svg {
+ inline-size: 12px;
+ block-size: 12px;
+}
+
+.aside {
+ display: flex;
+ align-items: center;
+}
+
+.positioning-region:hover {
+ background-color: var(--colorSubtleBackgroundHover);
+ color: var(--colorNeutralForeground2Hover);
+}
+
+.positioning-region:active {
+ background-color: var(--colorSubtleBackgroundPressed);
+ color: var(--colorNeutralForeground2Pressed);
+}
+
+::slotted([slot='start']),
+::slotted([slot='end']),
+::slotted(:not([slot])) {
+ display: flex;
+ align-items: center;
+ min-width: 0;
+}
+
+::slotted([slot='start']) {
+ flex-shrink: 0;
+}
+
+::slotted(:not([slot])) {
+ padding-inline: var(--spacingHorizontalXXS);
+}
+
+.items {
+ display: none;
+}
+
+:host([expanded]) .items {
+ display: block;
+}
+
+:host([empty]) .chevron,
+:host([empty]) .items {
+ visibility: hidden;
+}
+
+:host([selected]) .positioning-region {
+ background-color: var(--colorSubtleBackgroundSelected);
+ color: var(--colorNeutralForeground2Selected);
+}
+
+:host([selected]) .content,
+:host([selected]) .chevron {
+ color: var(--colorNeutralForeground3Selected);
+}
+
+:host([size='small']) .positioning-region {
+ height: var(--spacingVerticalXXL);
+ padding-inline-start: calc(var(--indent) * var(--spacingHorizontalM));
+}
+
+:host([appearance='subtle-alpha']) .positioning-region:hover {
+ background-color: var(--colorSubtleBackgroundLightAlphaHover);
+}
+
+:host([appearance='subtle-alpha']) .positioning-region:active {
+ background-color: var(--colorSubtleBackgroundLightAlphaPressed);
+}
+
+:host([appearance='subtle-alpha'][selected]) .positioning-region {
+ background-color: var(--colorSubtleBackgroundLightAlphaSelected);
+ color: var(--colorNeutralForeground2Selected);
+}
+
+:host([appearance='transparent']) .positioning-region {
+ background-color: var(--colorTransparentBackground);
+}
+
+:host([appearance='transparent']) .positioning-region:hover {
+ background-color: var(--colorTransparentBackgroundHover);
+}
+
+:host([appearance='transparent']) .positioning-region:active {
+ background-color: var(--colorTransparentBackgroundPressed);
+}
+
+:host([appearance='transparent'][selected]) .positioning-region {
+ background-color: var(--colorTransparentBackgroundSelected);
+ color: var(--colorNeutralForeground2Selected);
+}
+
+:host([expanded]) .chevron {
+ transform: rotate(90deg);
+}
diff --git a/packages/web-components/src/tree-item/tree-item.template.html b/packages/web-components/src/tree-item/tree-item.template.html
new file mode 100644
index 00000000000000..6e07aedefba33a
--- /dev/null
+++ b/packages/web-components/src/tree-item/tree-item.template.html
@@ -0,0 +1,27 @@
+
+
+ {{styles}}
+
+
+
+
+
+
diff --git a/packages/web-components/src/tree/tree.styles.css b/packages/web-components/src/tree/tree.styles.css
new file mode 100644
index 00000000000000..4369a99911f555
--- /dev/null
+++ b/packages/web-components/src/tree/tree.styles.css
@@ -0,0 +1,10 @@
+:host([hidden]) {
+ display: none;
+}
+:host {
+ display: block;
+}
+
+:host {
+ outline: none;
+}
diff --git a/packages/web-components/src/tree/tree.template.html b/packages/web-components/src/tree/tree.template.html
new file mode 100644
index 00000000000000..450b538fc68fed
--- /dev/null
+++ b/packages/web-components/src/tree/tree.template.html
@@ -0,0 +1,13 @@
+
+
+ {{styles}}
+
+
+
diff --git a/yarn.lock b/yarn.lock
index 9774592d8cc4e9..f17c7de2c74f2d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2747,25 +2747,25 @@
eslint-plugin-react "7.35.2"
eslint-plugin-security "1.4.0"
-"@microsoft/fast-build@0.6.0":
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/@microsoft/fast-build/-/fast-build-0.6.0.tgz#9791d6100d68ba7104a7727db44cf4fc27a6c939"
- integrity sha512-N5sApsoDETr4/iHyr99iy9lfAxHsNFIzyEezGmQyWa06rzXn8QK+pLF7EKtp0N4VUsB8i+s62dtIsCgz8kp/2g==
+"@microsoft/fast-build@0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@microsoft/fast-build/-/fast-build-0.7.0.tgz#a7167f8ae1bbd4a1ae379ac3b7bf84d68f464dd7"
+ integrity sha512-YKqjlwFwurd69dL6YWbvGdJ7TX8c2h4Ra7qUGUMTSQAhrnREXjtB6/cduPnkswxBfDOMwYBeaVJCDcMP5auLZg==
"@microsoft/fast-element@2.10.4", "@microsoft/fast-element@^2.0.0":
version "2.10.4"
resolved "https://registry.yarnpkg.com/@microsoft/fast-element/-/fast-element-2.10.4.tgz#12b8c6c90902f2a54d5b27f618d7d095e133546d"
integrity sha512-OkHIlMztq7+PgkRF1LscgBd/MVzMhGrWPkJRDvOEqdqEdZOKocKvaKcUKZubIBz4RpLIrhLD3lOJzCsspk6jXg==
-"@microsoft/fast-html@1.0.0-alpha.53":
- version "1.0.0-alpha.53"
- resolved "https://registry.yarnpkg.com/@microsoft/fast-html/-/fast-html-1.0.0-alpha.53.tgz#e656a38386a998640fd7af40bbcd5aae321092f9"
- integrity sha512-S6fUlNjk3aj9SP1U4sRWA1Cf1gns7FLJOed3NMvndWQBfmQczVX8CHXbfVKF55B7nKWRkAQwDHN0wOu7yxw+aw==
+"@microsoft/fast-html@1.0.0-alpha.54":
+ version "1.0.0-alpha.54"
+ resolved "https://registry.yarnpkg.com/@microsoft/fast-html/-/fast-html-1.0.0-alpha.54.tgz#66c670aad1dd2600941029d188ed63773baaed20"
+ integrity sha512-7GWGwaJSWD/nqafn/s1YTqc5CmHbRWwEC1BA/BJHSLrX+UQZGGbCugSQ0ArL4x7goDmB6rWLTPB7UZtqOcu/3g==
-"@microsoft/fast-test-harness@0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@microsoft/fast-test-harness/-/fast-test-harness-0.3.0.tgz#9d5536c8cbf1e4ecae9d70bfe0fe105b5e215caf"
- integrity sha512-EZ0iLxy/AEaOMthJmalD4fIp4rAM/ypBfqXmMJD4ZffVUVnLkfUw2NFZNUIsMbP/S4+tsfBnBlX5tyKSYD5TIQ==
+"@microsoft/fast-test-harness@0.3.1":
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/@microsoft/fast-test-harness/-/fast-test-harness-0.3.1.tgz#92c671ab9d76751b41a5dc447ec1fe74420796aa"
+ integrity sha512-BxwSSJhRbCJkyjJv9xsOl0ECAHjtU+zZk4PDse7jy/iqEb2wf51QLVrHZQAgWPZWAI6OlMTrjdZTRfiea3ciWA==
dependencies:
cheerio "1.2.0"