Skip to content

Commit d1a062a

Browse files
emogoogcopybara-github
authored andcommitted
feat(labs): add toolbar web component suite
PiperOrigin-RevId: 985457321
1 parent efeb031 commit d1a062a

7 files changed

Lines changed: 754 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//
2+
// Copyright 2026 Google LLC
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
@mixin root {
7+
// LINT.IfChange
8+
--button-container-color: var(--md-sys-color-surface-container);
9+
--container-color: var(--md-sys-color-surface-container);
10+
--container-elevation: var(--md-sys-elevation-shadow-3);
11+
--container-leading-space: var(--md-sys-space-100);
12+
--container-shape: calc(var(--horizontal-container-height) / 2);
13+
--container-spacing: var(--md-sys-space-50);
14+
--container-trailing-space: var(--md-sys-space-100);
15+
--docked-container-elevation: var(--md-sys-elevation-shadow-0);
16+
--docked-container-height: 64px;
17+
--docked-container-leading-space: var(--md-sys-space-200);
18+
--docked-container-max-spacing: 32px;
19+
--docked-container-min-spacing: 4px;
20+
--docked-container-shape: var(--md-sys-shape-corner-none);
21+
--docked-container-trailing-space: var(--md-sys-space-200);
22+
--horizontal-container-height: 64px;
23+
--icon-color: var(--md-sys-color-on-surface-variant);
24+
--label-text-color: var(--md-sys-color-on-surface-variant);
25+
--min-button-size: 40px;
26+
--motion-duration: var(--md-sys-motion-duration-short4);
27+
--motion-easing: var(--md-sys-motion-easing-emphasized);
28+
--selected-button-container-color: var(--md-sys-color-secondary-container);
29+
--selected-icon-color: var(--md-sys-color-on-secondary-container);
30+
--selected-label-text-color: var(--md-sys-color-on-secondary-container);
31+
--vertical-container-width: 64px;
32+
// LINT.ThenChange(toolbar-element.ts) keep in sync with `@cssprop` jsdoc tags
33+
}
34+
35+
@mixin standard {
36+
--button-container-color: var(--md-sys-color-surface-container);
37+
--container-color: var(--md-sys-color-surface-container);
38+
--icon-color: var(--md-sys-color-on-surface-variant);
39+
--label-text-color: var(--md-sys-color-on-surface-variant);
40+
--selected-button-container-color: var(--md-sys-color-secondary-container);
41+
--selected-icon-color: var(--md-sys-color-on-secondary-container);
42+
--selected-label-text-color: var(--md-sys-color-on-secondary-container);
43+
}
44+
45+
@mixin vibrant {
46+
--button-container-color: var(--md-sys-color-primary-container);
47+
--container-color: var(--md-sys-color-primary-container);
48+
--icon-color: var(--md-sys-color-primary);
49+
--label-text-color: var(--md-sys-color-primary);
50+
--selected-button-container-color: var(--md-sys-color-surface-container);
51+
--selected-icon-color: var(--md-sys-color-on-surface);
52+
--selected-label-text-color: var(--md-sys-color-on-surface);
53+
}
54+
55+
@mixin vertical {
56+
--container-shape: calc(var(--vertical-container-width) / 2);
57+
}
58+
59+
@mixin docked {
60+
--container-elevation: var(--docked-container-elevation);
61+
--container-leading-space: var(--docked-container-leading-space);
62+
--container-shape: var(--docked-container-shape);
63+
--container-spacing: clamp(
64+
var(--docked-container-min-spacing),
65+
4vw,
66+
var(--docked-container-max-spacing)
67+
);
68+
--container-trailing-space: var(--docked-container-trailing-space);
69+
--horizontal-container-height: var(--docked-container-height);
70+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import './material-collection.js';
8+
import './index.js';
9+
10+
import {
11+
KnobTypesToKnobs,
12+
MaterialCollection,
13+
materialInitsToStoryInits,
14+
setUpDemo,
15+
} from './material-collection.js';
16+
import {
17+
type ToolbarColor,
18+
type ToolbarOrientation,
19+
} from '@material/web/labs/gb/components/toolbar/toolbar.js';
20+
import {boolInput, Knob, selectDropdown} from './index.js';
21+
22+
import {stories, StoryKnobs} from './stories.js';
23+
24+
const collection = new MaterialCollection<KnobTypesToKnobs<StoryKnobs>>(
25+
'Toolbar',
26+
[
27+
new Knob('color', {
28+
ui: selectDropdown<ToolbarColor>({
29+
options: [
30+
{value: 'standard', label: 'Standard'},
31+
{value: 'vibrant', label: 'Vibrant'},
32+
],
33+
}),
34+
}),
35+
new Knob('orientation', {
36+
ui: selectDropdown<ToolbarOrientation>({
37+
options: [
38+
{value: 'horizontal', label: 'Horizontal'},
39+
{value: 'vertical', label: 'Vertical'},
40+
],
41+
}),
42+
}),
43+
new Knob('docked', {ui: boolInput()}),
44+
],
45+
);
46+
47+
collection.addStories(...materialInitsToStoryInits(stories));
48+
49+
setUpDemo(collection, {fonts: 'roboto', icons: 'material-symbols'});
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import '@material/web/labs/gb/components/button/md-gb-button.js';
8+
import '@material/web/labs/gb/components/iconbutton/md-gb-icon-button.js';
9+
import '@material/web/labs/gb/components/toolbar/md-gb-toolbar.js';
10+
import '@material/web/labs/gb/styles/icon/md-gb-icon.js';
11+
12+
import {MaterialStoryInit} from './material-collection.js';
13+
import {
14+
type ToolbarColor,
15+
type ToolbarOrientation,
16+
} from '@material/web/labs/gb/components/toolbar/toolbar.js';
17+
import {adoptStyles} from '@material/web/labs/gb/styles/adopt-styles.js';
18+
import {css, html} from 'lit';
19+
20+
import {styles as m3Styles} from '@material/web/labs/gb/styles/m3.css' with {type: 'css'}; // github-only
21+
// import {styles as m3Styles} from '@material/web/labs/gb/styles/m3.cssresult.js'; // google3-only
22+
23+
/** Knob types for toolbar stories. */
24+
export interface StoryKnobs {
25+
color?: ToolbarColor;
26+
orientation?: ToolbarOrientation;
27+
docked: boolean;
28+
}
29+
30+
adoptStyles(document, [
31+
m3Styles,
32+
css`
33+
:root {
34+
--md-icon-font: 'Material Symbols Outlined';
35+
}
36+
`,
37+
]);
38+
39+
const styles = css`
40+
.demo-container {
41+
align-items: center;
42+
background-color: var(--md-sys-color-surface);
43+
border: 1px solid var(--md-sys-color-outline-variant);
44+
border-radius: 16px;
45+
box-shadow: var(--md-sys-elevation-shadow-1);
46+
display: flex;
47+
justify-content: center;
48+
margin-bottom: 24px;
49+
min-height: 140px;
50+
overflow: hidden;
51+
padding: 24px;
52+
}
53+
54+
.demo-stack {
55+
display: flex;
56+
flex-direction: column;
57+
gap: 24px;
58+
}
59+
`;
60+
61+
const playground: MaterialStoryInit<StoryKnobs> = {
62+
name: 'Playground',
63+
styles,
64+
render(knobs) {
65+
const color = knobs.color || 'standard';
66+
const orientation = knobs.orientation || 'horizontal';
67+
const docked = Boolean(knobs.docked);
68+
69+
return html`
70+
<div class="demo-container">
71+
<md-gb-toolbar
72+
color=${color}
73+
orientation=${orientation}
74+
?docked=${docked}
75+
aria-label="Formatting toolbar">
76+
<md-gb-button square type="toggle" selected>
77+
<md-gb-icon>edit</md-gb-icon>
78+
Edit
79+
</md-gb-button>
80+
<md-gb-button square type="toggle">
81+
<md-gb-icon>palette</md-gb-icon>
82+
Style
83+
</md-gb-button>
84+
<md-gb-icon-button square aria-label="Favorite" type="toggle">
85+
<md-gb-icon>favorite</md-gb-icon>
86+
</md-gb-icon-button>
87+
<md-gb-icon-button square aria-label="Settings" type="toggle">
88+
<md-gb-icon>settings</md-gb-icon>
89+
</md-gb-icon-button>
90+
</md-gb-toolbar>
91+
</div>
92+
`;
93+
},
94+
};
95+
96+
const allVariants: MaterialStoryInit<StoryKnobs> = {
97+
name: 'Expressive Variants',
98+
styles,
99+
render() {
100+
return html`
101+
<div class="demo-stack">
102+
<div class="demo-container">
103+
<md-gb-toolbar color="standard" aria-label="Standard floating">
104+
<md-gb-button square type="toggle" selected>
105+
<md-gb-icon>star</md-gb-icon>
106+
Starred
107+
</md-gb-button>
108+
<md-gb-button square type="toggle">
109+
<md-gb-icon>visibility</md-gb-icon>
110+
Preview
111+
</md-gb-button>
112+
<md-gb-icon-button square aria-label="Favorite" type="toggle">
113+
<md-gb-icon>favorite</md-gb-icon>
114+
</md-gb-icon-button>
115+
</md-gb-toolbar>
116+
</div>
117+
118+
<div class="demo-container">
119+
<md-gb-toolbar color="vibrant" aria-label="Vibrant floating">
120+
<md-gb-button square type="toggle" selected>
121+
<md-gb-icon>auto_awesome</md-gb-icon>
122+
Generate
123+
</md-gb-button>
124+
<md-gb-button square type="toggle">
125+
<md-gb-icon>palette</md-gb-icon>
126+
Theme
127+
</md-gb-button>
128+
<md-gb-icon-button
129+
square
130+
aria-label="Bookmark"
131+
type="toggle"
132+
selected>
133+
<md-gb-icon>bookmark</md-gb-icon>
134+
</md-gb-icon-button>
135+
</md-gb-toolbar>
136+
</div>
137+
138+
<div class="demo-container">
139+
<md-gb-toolbar color="standard" docked aria-label="Standard docked">
140+
<md-gb-icon-button square aria-label="Home" type="toggle">
141+
<md-gb-icon>home</md-gb-icon>
142+
</md-gb-icon-button>
143+
<md-gb-button square type="toggle" selected>
144+
<md-gb-icon>folder</md-gb-icon>
145+
Files
146+
</md-gb-button>
147+
<md-gb-icon-button square aria-label="Image" type="toggle">
148+
<md-gb-icon>image</md-gb-icon>
149+
</md-gb-icon-button>
150+
</md-gb-toolbar>
151+
</div>
152+
</div>
153+
`;
154+
},
155+
};
156+
157+
/** Toolbar stories. */
158+
export const stories = [playground, allVariants];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {ToolbarElement} from './toolbar-element.js';
8+
9+
declare global {
10+
interface HTMLElementTagNameMap {
11+
/** A Material Design gBreeze toolbar custom element. */
12+
'md-gb-toolbar': ToolbarElement;
13+
}
14+
}
15+
16+
customElements.define('md-gb-toolbar', ToolbarElement);

0 commit comments

Comments
 (0)