Skip to content

feat(snackbar): update snackbar to Material Design 3 specification - #148

Merged
treeder merged 4 commits into
mainfrom
verify_snackbar_spec
Oct 13, 2026
Merged

treeder merged 4 commits into
mainfrom
verify_snackbar_spec

Conversation

@treeder

@treeder treeder commented Oct 13, 2026

Copy link
Copy Markdown
Member

Summary

Updates <md-snackbar> and the snack() helper function to comply with the Material Design 3 Snackbar Specification.

Key Changes

  • Behavior & Dismissal Timing:
    • Actionable snackbars (with action buttons or close icons) remain persistent until the user takes action, matching M3 web accessibility guidelines.
    • Non-actionable snackbars default to 5,000ms duration (within the 4,000–10,000ms M3 range) instead of 3,000ms.
    • Single-instance enforcement: active snackbars are closed before opening a new one so notifications never overlap.
    • Automatic DOM cleanup upon closing transition to prevent DOM node leaks.
  • Typography & Alignment:
    • Replaced text-align: center with start alignment (text-align: start) and 16px start margin.
    • Applied M3 Body Medium typescale tokens (14px, 20px line-height, 400 weight).
  • Elevation & Tokens:
    • Integrated <md-elevation> with Level 3 elevation (3dp shadow).
    • Exposed design token variables: --md-snackbar-container-color, --md-snackbar-supporting-text-color, --md-snackbar-action-label-text-color, --md-snackbar-icon-color, --md-snackbar-container-elevation, and --md-snackbar-container-shape.
  • Dimensions & Responsive Configurations:
    • Flexible min-height: 48px with balanced padding: single-line renders at 48px, two-line expands to 68px.
    • Added support for M3 stacked action layout (stacked property/attribute).
  • Action & Close Buttons:
    • Updated inverse button colors to map to --md-sys-color-inverse-primary.
    • Close button in snack() now uses an accessible <md-icon-button> with aria-label="Dismiss".
  • Accessibility & Exports:
    • Added role="status", aria-live="polite", and aria-atomic="true".
    • Added lifecycle events (open, opened, close, closed).
    • Exported snackbar.js in all.js and updated snackbar/README.md.

Verification

  • Built package via npx vite build (clean build with 0 errors).
  • Formatted with prettier.
  • Verified import resolution of all.js, snackbar/snackbar.js, and buttons/button.js in Node.js.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ d410f6b 2026-10-13T07:23:35.083Z View logs ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 2eed456 2026-10-13T07:18:49.632Z View logs ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ ce60670 2026-10-13T06:56:35.484Z View logs ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 55a3c62 2026-10-13T06:46:25.171Z View logs ↗

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

This pull request exports and integrates md-snackbar into the main entry bundle (all.js), updates the button inverse text colour token to inverse-primary, and significantly revamps the snackbar implementation to align with Material Design 3 specifications. The snackbar component now features Level 3 elevation, stacked layout support, auto-dismissal rules for non-actionable notifications, and improved accessibility attributes (role="status", aria-live="polite").

🔍 General Feedback

  • Exporting md-snackbar in all.js and providing comprehensive documentation in snackbar/README.md is a great addition for developers consuming the bundle.
  • The alignment with Material 3 snackbar guidelines (such as persistent actionable notifications and Level 3 elevation) is well-executed.
  • Consider adding unit tests for the snackbar component (e.g. testing snack() helper creation, event dispatch sequence, and auto-dismissal behaviour).
📊 Token Usage & Cost Efficiency
Metric Value
Input Tokens (uncached) 41,149
Input Tokens (cached) 408,454 (⚡ 90.7% cached)
PR Comments History Tokens 487
Thinking / Reasoning Tokens 26,822
Output Tokens 798
Total Session Tokens 477,710
Cost (uncached input) $0.0312
Cost (cached input) $0.0306
Cost (thinking / reasoning) $0.1006
Cost (response output) $0.0030
Estimated Total Cost $0.1654

Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.

Comment thread buttons/button.js Outdated
Comment thread snackbar/snackbar.js Outdated
Comment thread snackbar/snackbar.js Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

This pull request completes the Material 3 Snackbar implementation by integrating Level 3 elevation, inverse colour tokens, stacked layouts, dismiss icon buttons, and transition lifecycle events. It also exports the snackbar module from all.js and provides comprehensive documentation and token mappings in snackbar/README.md.

✅ Resolved Items from Prior Reviews

  • Updated the fallback colour for --_label-text-color on inverse text buttons to #d0bcff in buttons/button.js to match the M3 baseline inverse-primary token value. (buttons/button.js:739)
  • Updated the snack() helper function in snackbar/snackbar.js to automatically call snackbar.close() when an action button is clicked. (snackbar/snackbar.js:46)
  • Updated close() in snackbar/snackbar.js to set this._open = false, remove the open attribute, and clear timers immediately to prevent state de-synchronisation during exit transitions. (snackbar/snackbar.js:388)

🔍 General Feedback

  • The component now adheres closely to the Material Design 3 Snackbar specification, particularly around persistent actionable notifications versus auto-dismissing non-actionable alerts.
  • Exporting both snack and SnackBar from all.js while preserving alphabetical sort order keeps the root bundle tidy and developer-friendly.
  • The helper function snack() ensures that only one snackbar instance remains active at a time, avoiding notification collisions on screen.
📊 Token Usage & Cost Efficiency
Metric Value
Input Tokens (uncached) 41,554
Input Tokens (cached) 408,454 (⚡ 90.6% cached)
PR Comments History Tokens 1,031
Thinking / Reasoning Tokens 20,224
Output Tokens 830
Total Session Tokens 472,093
Cost (uncached input) $0.0319
Cost (cached input) $0.0306
Cost (thinking / reasoning) $0.0758
Cost (response output) $0.0031
Estimated Total Cost $0.1415

Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.

Comment thread snackbar/snackbar.js Outdated
Comment thread snackbar/snackbar.js

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

This pull request refactors the Snackbar component to align with the Material Design 3 specification, introducing proper tokens for inverse surface styling, Level 3 elevation, stacked action layouts, and accessible ARIA attributes. It also enhances the programmatic snack() helper by ensuring action dismissals, single-instance coordination, and DOM cleanup on close, whilst updating all.js bundle exports.

✅ Resolved Items from Prior Reviews

  • Updated the fallback token for :host([color='text'].inverse) in buttons/button.js to #d0bcff to match the Material 3 inverse-primary baseline palette. (buttons/button.js:739)
  • Ensured clicking the action button in the snack() helper invokes snackbar.close() to dismiss actionable snackbars. (snackbar/snackbar.js:46)
  • Fixed state desynchronisation by immediately setting this._open = false in close() and clearing pending transition timers. (snackbar/snackbar.js:388)
  • Kept the #snackbar container in the DOM and drove entry/exit transitions declaratively via component state classes rather than direct DOM mutations. (snackbar/snackbar.js:358)
  • Added an if (!this._open) return guard in close() to guarantee closing calls are idempotent. (snackbar/snackbar.js:413)

🔍 General Feedback

  • The refactored SnackBar implementation cleanly adheres to the Material Design 3 specification, particularly regarding auto-dismiss rules (allowing non-actionable snackbars to auto-dismiss after 5s whilst keeping actionable snackbars persistent until interaction).
  • Cleaning up programmatic DOM nodes on the closed event in snack() is an excellent pattern that prevents memory and DOM leaks in single-page applications.
  • The component includes comprehensive accessibility features via role="status", aria-live="polite", and aria-atomic="true".
📊 Token Usage & Cost Efficiency
Metric Value
Input Tokens (uncached) 41,677
Input Tokens (cached) 408,454 (⚡ 90.4% cached)
PR Comments History Tokens 1,792
Thinking / Reasoning Tokens 17,993
Output Tokens 1,325
Total Session Tokens 471,241
Cost (uncached input) $0.0326
Cost (cached input) $0.0306
Cost (thinking / reasoning) $0.0675
Cost (response output) $0.0050
Estimated Total Cost $0.1357

Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.

Comment thread buttons/button.js
Comment thread snackbar/README.md Outdated
Comment thread snackbar/README.md Outdated
Comment thread snackbar/snackbar.js Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

This pull request refactors the Material 3 Snackbar component and its documentation to align with official Material Design 3 specifications. It introduces Level 3 elevation, inverse-surface and inverse-primary tokens, single-instance coordination, persistent actionable snackbars, and declarative transition management. All previous review suggestions have been resolved and the component is now properly exported from all.js.

✅ Resolved Items from Prior Reviews

  • Updated the fallback color for inverse text buttons to #d0bcff (--md-sys-color-inverse-primary) and applied it across default, hover, focus, and pressed states. (buttons/button.js:739)
  • Added automatic dismissal of the snackbar when the action button is clicked. (snackbar/snackbar.js:46)
  • Immediately set this._open = false upon calling close() and managed animation timer handles to prevent state desynchronisation. (snackbar/snackbar.js:388)
  • Kept #snackbar in the DOM and drove entrance and exit transitions declaratively via component state classes. (snackbar/snackbar.js:358)
  • Added an if (!this._open) return guard to make close() idempotent during ongoing close transitions. (snackbar/snackbar.js:413)
  • Updated README examples to explicitly specify color="text" for action buttons in standard and stacked snackbar layouts. (snackbar/README.md:30)
  • Replaced innerText with textContent when creating action buttons programmatically. (snackbar/snackbar.js:45)

🔍 General Feedback

  • The snackbar implementation now complies with Material Design 3 guidelines regarding persistent actionable snackbars, accessible ARIA status roles (role="status", aria-live="polite"), and single-instance coordination.
  • Transitions are managed smoothly through declarative CSS classes without layout flashes or abrupt element mounting.
  • Exporting snackbar.js in all.js ensures full bundle parity with the rest of the component suite.
📊 Token Usage & Cost Efficiency
Metric Value
Input Tokens (uncached) 42,153
Input Tokens (cached) 408,454 (⚡ 90.0% cached)
PR Comments History Tokens 3,046
Thinking / Reasoning Tokens 9,916
Output Tokens 599
Total Session Tokens 464,168
Cost (uncached input) $0.0339
Cost (cached input) $0.0306
Cost (thinking / reasoning) $0.0372
Cost (response output) $0.0022
Estimated Total Cost $0.1040

Gemini 3.8 Flash: introductory rate $0.75/$3.75 per 1M applied; reverts to $1.5/$7.5 after 2026-12-31.
Gemini 3.8 Flash: standard tier; batch and flex are half again, priority is higher.
Cache reads are priced here, but context-cache STORAGE, where the model charges for it separately per token-hour, is not included, so the figure can run slightly low.

@treeder
treeder merged commit 3df51bb into main Oct 13, 2026
2 checks passed
@treeder
treeder deleted the verify_snackbar_spec branch October 13, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant