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'