diff --git a/all.js b/all.js index bc4175c..dc15f50 100644 --- a/all.js +++ b/all.js @@ -6,6 +6,7 @@ */ import './buttons/elevated-button.js' import './buttons/button.js' +import './buttons/button-group.js' import './buttons/filled-tonal-button.js' import './buttons/outlined-button.js' import './buttons/text-button.js' @@ -48,6 +49,7 @@ import './text/text-field.js' // LINT.IfChange(exports) // go/keep-sorted start export * from './buttons/button.js' +export * from './buttons/button-group.js' export * from './checkbox/checkbox.js' export * from './chips/chip.js' export * from './chips/chip-set.js' diff --git a/buttons/README.md b/buttons/README.md index d82ff78..57c0dee 100644 --- a/buttons/README.md +++ b/buttons/README.md @@ -32,6 +32,30 @@ Changes from previous version: ``` +## Button Groups + +[Material 3 Button Groups](https://m3.material.io/components/button-groups/overview) + +Standard Button Group: + +```html + + One + Two + Three + +``` + +Connected Button Group: + +```html + + One + Two + Three + +``` + ## Floating Action Button - FAB [Material 3 Floating Action Button](https://m3.material.io/components/floating-action-button/overview)] diff --git a/buttons/button-group.js b/buttons/button-group.js new file mode 100644 index 0000000..72b8dde --- /dev/null +++ b/buttons/button-group.js @@ -0,0 +1,94 @@ +import { html, LitElement, css } from 'lit' + +export class ButtonGroup extends LitElement { + static styles = css` + :host { + display: inline-flex; + flex-direction: row; + vertical-align: middle; + } + + /* Standard group adds gap between buttons */ + :host(:not([connected])) { + gap: 8px; /* M3 standard button group gap */ + } + + /* Target all buttons except the first one */ + :host([connected]) ::slotted(*:not(:first-child)) { + /* Make flat on the left side */ + --_container-shape-start-start: 0; + --_container-shape-end-start: 0; + + /* Target variant-specific variables explicitly */ + --md-button-container-shape-start-start: 0; + --md-button-container-shape-end-start: 0; + --md-filled-tonal-button-container-shape-start-start: 0; + --md-filled-tonal-button-container-shape-end-start: 0; + --md-elevated-button-container-shape-start-start: 0; + --md-elevated-button-container-shape-end-start: 0; + --md-outlined-button-container-shape-start-start: 0; + --md-outlined-button-container-shape-end-start: 0; + --md-icon-button-container-shape-start-start: 0; + --md-icon-button-container-shape-end-start: 0; + + /* Explicit border radius as fallback */ + border-start-start-radius: 0; + border-end-start-radius: 0; + + /* Overlap borders */ + margin-inline-start: -1px; + } + + /* Target all buttons except the last one */ + :host([connected]) ::slotted(*:not(:last-child)) { + /* Make flat on the right side */ + --_container-shape-start-end: 0; + --_container-shape-end-end: 0; + + /* Target variant-specific variables explicitly */ + --md-button-container-shape-start-end: 0; + --md-button-container-shape-end-end: 0; + --md-filled-tonal-button-container-shape-start-end: 0; + --md-filled-tonal-button-container-shape-end-end: 0; + --md-elevated-button-container-shape-start-end: 0; + --md-elevated-button-container-shape-end-end: 0; + --md-outlined-button-container-shape-start-end: 0; + --md-outlined-button-container-shape-end-end: 0; + --md-icon-button-container-shape-start-end: 0; + --md-icon-button-container-shape-end-end: 0; + + /* Explicit border radius as fallback */ + border-start-end-radius: 0; + border-end-end-radius: 0; + } + + /* Ensure the active/hovered/focused button is on top to show full border */ + :host([connected]) ::slotted(*:hover), + :host([connected]) ::slotted(*:focus-within), + :host([connected]) ::slotted(*:active) { + z-index: 1; + position: relative; + } + + /* Selected state needs to be above unselected for connected groups */ + :host([connected]) ::slotted([selected]) { + z-index: 1; + position: relative; + } + ` + + static properties = { + connected: { type: Boolean, reflect: true } + } + + constructor() { + super() + this.connected = false + } + + render() { + return html`` + } +} + +customElements.define('md-button-group', ButtonGroup) diff --git a/common.js b/common.js index d063462..57b0e1f 100644 --- a/common.js +++ b/common.js @@ -7,6 +7,7 @@ * for production. */ import './buttons/button.js' +import './buttons/button-group.js' import './checkbox/checkbox.js' import './chips/chip.js' import './chips/chip-set.js' @@ -27,6 +28,7 @@ import './tabs/tabs.js' import './text/text-field.js' export * from './buttons/button.js' +export * from './buttons/button-group.js' export * from './checkbox/checkbox.js' export * from './chips/chip.js' export * from './chips/chip-set.js'