Skip to content

Commit fe899b6

Browse files
committed
feat(snackbar): ✨ Add snackbar component
- Implements the snackbar component with various options like two-lines, action, and fixed positioning. - Includes theming support via CSS custom properties. - Adds demo and documentation for the new component.
1 parent 7e79cf6 commit fe899b6

File tree

13 files changed

+716
-0
lines changed

13 files changed

+716
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import '@maicol07/material-web-additions/snackbar/snackbar.js';
3.88 KB
Loading

docs/components/snackbar.md

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
<!-- catalog-only-start --><!-- ---
2+
name: Snackbar
3+
dirname: snackbar
4+
-----><!-- catalog-only-end -->
5+
6+
<catalog-component-header>
7+
<catalog-component-header-title slot="title">
8+
9+
# Snackbar
10+
11+
<!-- no-catalog-start -->
12+
13+
<!--*
14+
# Document freshness: For more information, see go/fresh-source.
15+
freshness: { owner: 'maicol07' reviewed: '2025-03-29' }
16+
tag: 'docType:reference'
17+
*-->
18+
19+
<!-- go/md-button -->
20+
21+
<!-- [TOC] -->
22+
23+
<!-- external-only-start -->
24+
**This documentation is fully rendered on the
25+
[Material Web Additions catalog](https://material-web-additions.maicol07.it/components/snackbar/).**
26+
<!-- external-only-end -->
27+
28+
<!-- no-catalog-end -->
29+
30+
[Snackbars](https://m3.material.io/components/snackbar) show short updates about app processes at the bottom of the screen
31+
32+
</catalog-component-header-title>
33+
34+
<img
35+
class="hero"
36+
alt="A phone showing a snackbar with the text 'Email archived' and an action button 'Undo'"
37+
src="https://lh3.googleusercontent.com/L_YKoQnBJo4gZDehCRImD_CA4nS0d_4FrD7l7MKQ8gVKkpNC9HyxKAoTycybWfPUMwcBPoiNKIGiVY9yZV5ExZobitkC3gI0Yc92oIf_Zs3o5BNvmKQ=w1200">
38+
39+
</catalog-component-header>
40+
41+
* [Design article](https://m3.material.io/components/snackbar) <!-- {.external} -->
42+
* [API Documentation](#api)
43+
* [Source code](https://github.com/maicol07/material-web-additions/tree/main/snackbar)
44+
<!-- {.external} -->
45+
46+
<!-- catalog-only-start -->
47+
48+
<!--
49+
50+
## Interactive Demo
51+
52+
{% playgroundexample dirname=dirname %}
53+
54+
-->
55+
56+
<!-- catalog-only-end -->
57+
58+
## Types
59+
60+
<!-- no-catalog-start -->
61+
62+
![Snackbar types](https://lh3.googleusercontent.com/Pd1qLYMI80pcYjx89JXrogC_QiOljw2S1pbGruxLf1oJu_bQnZBwoBxb7V3AnPcV-piQUix6mCFtdBH73KWXOmBI-Svt8rcfh8sRwlh6yJ26dg=s0 "Single and multi-line snackbars with or without action")
63+
64+
<!-- no-catalog-end -->
65+
<!-- catalog-only-start -->
66+
67+
<!--
68+
69+
<div class="figure-wrapper">
70+
<figure
71+
class="types-image"
72+
style="justify-content:center;"
73+
title="Elevated, filled and outlined cards"
74+
aria-label="The 3 types of cards">
75+
<style>
76+
.types-image .wrapper,
77+
.types-image .wrapper > * {
78+
display: flex;
79+
padding: 8px;
80+
flex-wrap: wrap;
81+
justify-content: center;
82+
}
83+
.types-image .wrapper > * {
84+
flex-direction: column;
85+
align-items: center;
86+
padding-inline: 16px;
87+
}
88+
.types-image span {
89+
display: inline-flex;
90+
background-color: var(--md-sys-color-inverse-surface);
91+
color: var(--md-sys-color-inverse-on-surface);
92+
padding: 8px;
93+
margin-block-start: 8px;
94+
width: 24px;
95+
height: 24px;
96+
border-radius: 50%;
97+
justify-content: center;
98+
align-items: center;
99+
}
100+
</style>
101+
<div class="wrapper">
102+
<div>
103+
<md-snackbar open timeout="0">Single-line snackbar</md-snackbar>
104+
<span>1</span>
105+
</div>
106+
<div>
107+
<md-snackbar open timeout="0" action-text="Action">Single-line snackbar with action</md-snackbar>
108+
<span>2</span>
109+
</div>
110+
<div>
111+
<md-snackbar open timeout="0" two-lines>
112+
Two-line snackbar <br>
113+
without action
114+
</md-snackbar>
115+
<span>3</span>
116+
</div>
117+
<div>
118+
<md-snackbar open timeout="0" two-lines action-text="Action">
119+
Two-line snackbar <br>
120+
with action
121+
</md-snackbar>
122+
<span>4</span>
123+
</div>
124+
<div>
125+
<md-snackbar open timeout="0" two-lines longer-action action-text="Longer action">
126+
Two-line snackbar <br>
127+
with longer action
128+
</md-snackbar>
129+
<span>5</span>
130+
</div>
131+
<div>
132+
<md-text-button onclick="this.nextElementSibling.open = true">Open</md-text-button>
133+
<md-snackbar open timeout="0">
134+
Single-line snackbar with icon button
135+
<md-icon-button slot="icon">
136+
<md-icon>close</md-icon>
137+
</md-icon-button>
138+
</md-snackbar>
139+
<span>6</span>
140+
</div>
141+
<div>
142+
<md-text-button onclick="this.nextElementSibling.open = true">Open</md-text-button>
143+
<md-snackbar fixed>
144+
Single-line snackbar fixed
145+
</md-snackbar>
146+
<span>7</span>
147+
</div>
148+
</div>
149+
</figure>
150+
</div>
151+
152+
-->
153+
154+
<!-- catalog-only-end -->
155+
156+
1. [Single line](#single-line)
157+
2. [Single line with action](#single-line-with-action)
158+
3. [Two lines](#two-lines)
159+
4. [Two lines with action](#two-lines-with-action)
160+
5. [Two lines with longer action](#two-lines-with-longer-action)
161+
6. [Single line with icon button closable/openable](#single-line-with-icon-button)
162+
6. [Single line fixed](#single-line-fixed)
163+
164+
## Usage
165+
Snackbars inform users of a process that an app has performed or will perform.
166+
167+
```html
168+
<md-snackbar open timeout="0">
169+
Single-line snackbar
170+
</md-snackbar>
171+
```
172+
173+
### Action
174+
A snackbar can contain an action button.
175+
176+
```html
177+
<md-snackbar open timeout="0" action-text="Action">
178+
Single-line snackbar with action
179+
</md-snackbar>
180+
```
181+
182+
### Two lines
183+
A snackbar can contain two lines of text.
184+
185+
```html
186+
<md-snackbar open timeout="0" two-lines>
187+
Two-line snackbar <br>
188+
without action
189+
</md-snackbar>
190+
```
191+
192+
### Icon Button
193+
A snackbar can contain an optional icon button.
194+
195+
```html
196+
<md-snackbar open timeout="0">
197+
Single-line snackbar with icon button
198+
<md-icon-button slot="icon">
199+
<md-icon>close</md-icon>
200+
</md-icon-button>
201+
</md-snackbar>
202+
```
203+
204+
## Theming
205+
206+
Cards supports [Material theming](https://material-web.dev/theming/material-theming/) and can be customized
207+
in terms of color, typography, and shape.
208+
209+
### Tokens
210+
| Token | Default value |
211+
|---------------------------------|-------------------------------------|
212+
| `--md-snackbar-container-color` | `--md-sys-color-surface` |
213+
| `--md-snackbar-container-shape` | `--md-sys-shape-corner-extra-small` |
214+
215+
* [All tokens](https://github.com/maicol07/material-web-additions/blob/main/tokens/_md-comp-snackbar.scss)
216+
<!-- {.external} -->
217+
218+
### Example
219+
220+
<!-- no-catalog-start -->
221+
222+
![Image of a snackbar with a different theme applied](images/snackbar/theming.png "Snackbar theming example.")
223+
224+
<!-- no-catalog-end -->
225+
<!-- catalog-only-start -->
226+
227+
<!--
228+
229+
<div class="figure-wrapper">
230+
<figure
231+
style="justify-content:center;align-items:center;"
232+
class="styled-example"
233+
title="Snackbar theming example."
234+
aria-label="Image of a snackbar with a different theme applied">
235+
<style>
236+
.styled-example {
237+
--md-snackbar-container-shape: 0px;
238+
--md-snackbar-container-color: red;
239+
}
240+
</style>
241+
242+
<md-snackbar open timeout="0" class="styled-example">
243+
Snackbar
244+
</md-snackbar>
245+
</figure>
246+
</div>
247+
248+
-->
249+
250+
<!-- catalog-only-end -->
251+
252+
```html
253+
<style>
254+
.styled-example {
255+
--md-snackbar-container-shape: 0px;
256+
--md-snackbar-container-color: red;
257+
}
258+
</style>
259+
260+
<md-snackbar open timeout="0" class="styled-example">
261+
Snackbar
262+
</md-snackbar>
263+
```
264+
265+
<!-- auto-generated API docs start -->
266+
267+
## API
268+
269+
270+
### MdSnackbar <code>&lt;md-snackbar&gt;</code>
271+
272+
#### Properties
273+
274+
<!-- mdformat off(autogenerated might break rendering in catalog) -->
275+
276+
Property | Attribute | Type | Default | Description
277+
--- | --- | --- | --- | ---
278+
`open` | `open` | `boolean` | `false` | Opened state of the snackbar.
279+
`twoLines` | `two-lines` | `boolean` | `false` | Support two lines of text.
280+
`actionText` | `action-text` | `string` | `undefined` | Text for the action button.
281+
`fixed` | `fixed` | `boolean` | `false` | Fixed position of the snackbar.
282+
`timeout` | `timeout` | `number` | `5000` | Timeout for the snackbar to close automatically.
283+
284+
<!-- mdformat on(autogenerated might break rendering in catalog) -->
285+
286+
#### Methods
287+
288+
<!-- mdformat off(autogenerated might break rendering in catalog) -->
289+
290+
Method | Parameters | Returns | Description
291+
--- | --- | --- | ---
292+
`close` | _None_ | `void` | Closes the snackbar.<br>This method will remove the 'opened' class from the snackbar and dispatch a 'close' event. After a timeout, it will set the `open` property to false and dispatch a 'closed' event.
293+
`show` | _None_ | `void` | Opens the snackbar.
294+
295+
<!-- mdformat on(autogenerated might break rendering in catalog) -->
296+
297+
<!-- auto-generated API docs end -->

scripts/analyzer/element-docs-map.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export const docsToElementMapping: {[key: string]: string[]} = {
1717
'layout-grid.md': [
1818
'layout-grid/layout-grid.ts'
1919
],
20+
'snackbar.md': [
21+
'snackbar/snackbar.ts'
22+
],
2023
'data-table.md': [
2124
'data-table/data-table.ts',
2225
'data-table/data-table-cell.ts',

snackbar/demo/demo.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @license
3+
* Copyright 2023 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import '~catalog/stories/index.js';
8+
import '~catalog/stories/material-collection.js';
9+
10+
import {KnobTypesToKnobs, MaterialCollection, materialInitsToStoryInits, setUpDemo} from '~catalog/stories/material-collection.js';
11+
import {boolInput, Knob, textInput, numberInput} from '~catalog/stories/index.js';
12+
13+
import {stories, StoryKnobs} from './stories.js';
14+
15+
const collection =
16+
new MaterialCollection<KnobTypesToKnobs<StoryKnobs>>('Snackbar', [
17+
new Knob('open', boolInput(), {
18+
defaultValue: false,
19+
description: 'Open state of the snackbar.',
20+
}),
21+
new Knob('twoLines', boolInput(), {
22+
defaultValue: false,
23+
description: 'Support two lines of text.',
24+
}),
25+
new Knob('actionText', textInput(), {
26+
defaultValue: 'Action',
27+
description: 'Text for the action button.',
28+
}),
29+
new Knob('fixed', boolInput(), {
30+
defaultValue: false,
31+
description: 'Fixed position of the snackbar.',
32+
}),
33+
new Knob('timeout', numberInput(), {
34+
defaultValue: '5000',
35+
description: 'Timeout for the snackbar to close automatically.',
36+
}),
37+
]);
38+
39+
collection.addStories(...materialInitsToStoryInits(stories));
40+
41+
setUpDemo(collection, {fonts: 'roboto', icons: 'material-symbols'});

snackbar/demo/project.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "/assets/stories/base.json",
3+
"files": {
4+
"demo.ts": {
5+
"hidden": true
6+
},
7+
"stories.ts": {}
8+
}
9+
}

0 commit comments

Comments
 (0)