Skip to content

Commit 5950225

Browse files
authored
Toggle button (#100)
* Toggle button * makes selected button square * gemini fixes
1 parent 78dbce0 commit 5950225

File tree

2 files changed

+162
-15
lines changed

2 files changed

+162
-15
lines changed

buttons/button.js

Lines changed: 153 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export class Button extends LitElement {
2222
}
2323

2424
static properties = {
25-
toggle: { type: Boolean, reflect: true },
2625
size: { type: String, reflect: true },
2726
shape: { type: String, reflect: true },
2827
color: { type: String, reflect: true }, // this is elevated, filled, etc. Not an actual color.
@@ -33,6 +32,8 @@ export class Button extends LitElement {
3332
trailingIcon: { type: Boolean, attribute: 'trailing-icon', reflect: true },
3433
hasIcon: { type: Boolean, attribute: 'has-icon', reflect: true },
3534
type: { type: String },
35+
selected: { type: Boolean, reflect: true },
36+
toggle: { type: Boolean, reflect: true },
3637
}
3738

3839
get name() {
@@ -49,7 +50,6 @@ export class Button extends LitElement {
4950
constructor() {
5051
super()
5152

52-
this.toggle = false
5353
/**
5454
* Accepted values are 'small' (default), 'extra-small', 'medium', 'large', 'extra-large'.
5555
*/
@@ -98,6 +98,16 @@ export class Button extends LitElement {
9898
* form.
9999
*/
100100
this.value = ''
101+
102+
/**
103+
* Whether or not the toggle button is selected.
104+
*/
105+
this.selected = false
106+
/**
107+
* Set to turn this into a toggle button.
108+
*/
109+
this.toggle = false
110+
101111
this.handleActivationClick = (event) => {
102112
if (!isActivationClick(event) || !this.buttonElement) {
103113
return
@@ -162,9 +172,13 @@ export class Button extends LitElement {
162172
this.pressed = false
163173
}
164174
handleClick(event) {
165-
// if (this.href) {
166-
// event.preventDefault()
167-
// }
175+
if (this.disabled || !this.toggle) {
176+
return
177+
}
178+
179+
this.selected = !this.selected
180+
this.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }))
181+
this.dispatchEvent(new Event('change', { bubbles: true }))
168182
}
169183
renderButton() {
170184
// Needed for closure conformance
@@ -175,7 +189,8 @@ export class Button extends LitElement {
175189
?disabled=${this.disabled}
176190
aria-label="${ariaLabel || nothing}"
177191
aria-haspopup="${ariaHasPopup || nothing}"
178-
aria-expanded="${ariaExpanded || nothing}">
192+
aria-expanded="${ariaExpanded || nothing}"
193+
aria-pressed="${this.toggle ? this.selected : nothing}">
179194
${this.renderContent()}
180195
</button>`
181196
}
@@ -188,6 +203,7 @@ export class Button extends LitElement {
188203
aria-label="${ariaLabel || nothing}"
189204
aria-haspopup="${ariaHasPopup || nothing}"
190205
aria-expanded="${ariaExpanded || nothing}"
206+
aria-pressed="${this.toggle ? this.selected : nothing}"
191207
href=${this.href}
192208
target=${this.target || nothing}
193209
>${this.renderContent()}
@@ -276,6 +292,35 @@ export class Button extends LitElement {
276292
--_with-trailing-icon-leading-space: var(--md-button-with-trailing-icon-leading-space, 24px);
277293
--_with-trailing-icon-trailing-space: var(--md-button-with-trailing-icon-trailing-space, 16px);
278294
}
295+
:host([color='filled'][toggle]:not([selected])) {
296+
--_container-color: var(
297+
--md-button-unselected-container-color,
298+
var(--md-sys-color-surface-container-highest, #e6e0e9)
299+
);
300+
--_label-text-color: var(--md-button-unselected-label-text-color, var(--md-sys-color-primary, #6750a4));
301+
--_icon-color: var(--md-button-unselected-icon-color, var(--md-sys-color-primary, #6750a4));
302+
--_hover-state-layer-color: var(
303+
--md-button-unselected-hover-state-layer-color,
304+
var(--md-sys-color-primary, #6750a4)
305+
);
306+
--_pressed-state-layer-color: var(
307+
--md-button-unselected-pressed-state-layer-color,
308+
var(--md-sys-color-primary, #6750a4)
309+
);
310+
}
311+
:host([color='filled'][selected]) {
312+
--_container-color: var(--md-button-selected-container-color, var(--md-sys-color-primary, #6750a4));
313+
--_label-text-color: var(--md-button-selected-label-text-color, var(--md-sys-color-on-primary, #fff));
314+
--_icon-color: var(--md-button-selected-icon-color, var(--md-sys-color-on-primary, #fff));
315+
--_hover-state-layer-color: var(
316+
--md-button-selected-hover-state-layer-color,
317+
var(--md-sys-color-on-primary, #fff)
318+
);
319+
--_pressed-state-layer-color: var(
320+
--md-button-selected-pressed-state-layer-color,
321+
var(--md-sys-color-on-primary, #fff)
322+
);
323+
}
279324
`,
280325
css`
281326
:host([color='tonal']) {
@@ -386,6 +431,42 @@ export class Button extends LitElement {
386431
--_with-trailing-icon-leading-space: var(--md-filled-tonal-button-with-trailing-icon-leading-space, 24px);
387432
--_with-trailing-icon-trailing-space: var(--md-filled-tonal-button-with-trailing-icon-trailing-space, 16px);
388433
}
434+
:host([color='tonal'][toggle]:not([selected])) {
435+
--_container-color: var(
436+
--md-filled-tonal-button-unselected-container-color,
437+
var(--md-sys-color-surface-container-highest, #e6e0e9)
438+
);
439+
--_label-text-color: var(
440+
--md-filled-tonal-button-unselected-label-text-color,
441+
var(--md-sys-color-on-surface-variant, #49454f)
442+
);
443+
--_icon-color: var(
444+
--md-filled-tonal-button-unselected-icon-color,
445+
var(--md-sys-color-on-surface-variant, #49454f)
446+
);
447+
--_hover-state-layer-color: var(
448+
--md-filled-tonal-button-unselected-hover-state-layer-color,
449+
var(--md-sys-color-on-surface-variant, #49454f)
450+
);
451+
--_pressed-state-layer-color: var(
452+
--md-filled-tonal-button-unselected-pressed-state-layer-color,
453+
var(--md-sys-color-on-surface-variant, #49454f)
454+
);
455+
}
456+
:host([color='tonal'][selected]) {
457+
--_container-color: var(
458+
--md-filled-tonal-button-selected-container-color,
459+
var(--md-sys-color-secondary-container, #e8def8)
460+
);
461+
--_label-text-color: var(
462+
--md-filled-tonal-button-selected-label-text-color,
463+
var(--md-sys-color-on-secondary-container, #1d192b)
464+
);
465+
--_icon-color: var(
466+
--md-filled-tonal-button-selected-icon-color,
467+
var(--md-sys-color-on-secondary-container, #1d192b)
468+
);
469+
}
389470
`,
390471
// elevated
391472
css`
@@ -479,6 +560,37 @@ export class Button extends LitElement {
479560
--_with-trailing-icon-leading-space: var(--md-elevated-button-with-trailing-icon-leading-space, 24px);
480561
--_with-trailing-icon-trailing-space: var(--md-elevated-button-with-trailing-icon-trailing-space, 16px);
481562
}
563+
:host([color='elevated'][toggle]:not([selected])) {
564+
--_container-color: var(
565+
--md-elevated-button-unselected-container-color,
566+
var(--md-sys-color-surface-container-highest, #e6e0e9)
567+
);
568+
--_label-text-color: var(
569+
--md-elevated-button-unselected-label-text-color,
570+
var(--md-sys-color-primary, #6750a4)
571+
);
572+
--_icon-color: var(--md-elevated-button-unselected-icon-color, var(--md-sys-color-primary, #6750a4));
573+
}
574+
575+
:host([color='elevated'][selected]) {
576+
--_container-color: var(--md-elevated-button-selected-container-color, var(--md-sys-color-primary, #6750a4));
577+
--_label-text-color: var(--md-elevated-button-selected-label-text-color, var(--md-sys-color-on-primary, #fff));
578+
--_icon-color: var(--md-elevated-button-selected-icon-color, var(--md-sys-color-on-primary, #fff));
579+
}
580+
581+
:host([color='elevated'][selected]) {
582+
--_container-color: var(--md-elevated-button-selected-container-color, var(--md-sys-color-primary, #6750a4));
583+
--_label-text-color: var(--md-elevated-button-selected-label-text-color, var(--md-sys-color-on-primary, #fff));
584+
--_icon-color: var(--md-elevated-button-selected-icon-color, var(--md-sys-color-on-primary, #fff));
585+
--_hover-state-layer-color: var(
586+
--md-elevated-button-selected-hover-state-layer-color,
587+
var(--md-sys-color-on-primary, #fff)
588+
);
589+
--_pressed-state-layer-color: var(
590+
--md-elevated-button-selected-pressed-state-layer-color,
591+
var(--md-sys-color-on-primary, #fff)
592+
);
593+
}
482594
483595
md-elevation {
484596
transition-duration: 280ms;
@@ -577,6 +689,17 @@ export class Button extends LitElement {
577689
:host([color='text'].inverse) {
578690
--_label-text-color: var(--md-button-label-text-color, var(--md-sys-color-on-primary, #6750a4));
579691
}
692+
:host([color='text'][selected]) {
693+
--_container-color: var(
694+
--md-text-button-selected-container-color,
695+
var(--md-sys-color-secondary-container, #e8def8)
696+
);
697+
--_label-text-color: var(
698+
--md-text-button-selected-label-text-color,
699+
var(--md-sys-color-on-secondary-container, #1d192b)
700+
);
701+
--_icon-color: var(--md-text-button-selected-icon-color, var(--md-sys-color-on-secondary-container, #1d192b));
702+
}
580703
`,
581704
css`
582705
:host([color='outlined']) {
@@ -666,16 +789,26 @@ export class Button extends LitElement {
666789
--_disabled-container-opacity: 0;
667790
}
668791
792+
:host([color='outlined'][selected]) {
793+
--_container-color: var(
794+
--md-outlined-button-selected-container-color,
795+
var(--md-sys-color-inverse-surface, #313033)
796+
);
797+
--_label-text-color: var(
798+
--md-outlined-button-selected-label-text-color,
799+
var(--md-sys-color-inverse-on-surface, #f4eff4)
800+
);
801+
--_icon-color: var(--md-outlined-button-selected-icon-color, var(--md-sys-color-inverse-on-surface, #f4eff4));
802+
--_outline-color: var(--md-outlined-button-selected-outline-color, transparent);
803+
}
804+
669805
.outlined {
670806
inset: 0;
671807
border-style: solid;
672808
position: absolute;
673809
box-sizing: border-box;
674810
border-color: var(--_outline-color);
675-
border-start-start-radius: var(--_container-shape-start-start);
676-
border-start-end-radius: var(--_container-shape-start-end);
677-
border-end-start-radius: var(--_container-shape-end-start);
678-
border-end-end-radius: var(--_container-shape-end-end);
811+
border-radius: inherit;
679812
}
680813
681814
:host(:active) .outlined {
@@ -950,19 +1083,24 @@ export class Button extends LitElement {
9501083
:host([shape='square'][size='extra-large']) {
9511084
border-radius: 28px;
9521085
}
953-
:host([pressed][size='extra-small']) {
1086+
:host([pressed][size='extra-small']),
1087+
:host([selected][size='extra-small']) {
9541088
border-radius: 8px;
9551089
}
956-
:host([pressed][size='small']) {
1090+
:host([pressed][size='small']),
1091+
:host([selected][size='small']) {
9571092
border-radius: 8px;
9581093
}
959-
:host([pressed][size='medium']) {
1094+
:host([pressed][size='medium']),
1095+
:host([selected][size='medium']) {
9601096
border-radius: 12px;
9611097
}
962-
:host([pressed][size='large']) {
1098+
:host([pressed][size='large']),
1099+
:host([selected][size='large']) {
9631100
border-radius: 16px;
9641101
}
965-
:host([pressed][size='extra-large']) {
1102+
:host([pressed][size='extra-large']),
1103+
:host([selected][size='extra-large']) {
9661104
border-radius: 16px;
9671105
}
9681106
`,

demo/components/expressive-component.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ class ExpressiveComponent extends LitElement {
232232
<md-button shape="square" size="extra-large">Extra large</md-button>
233233
</div>
234234
235+
<h3>Toggle buttons</h3>
236+
<div class="flexw g12 aic">
237+
<md-button toggle>Toggle me</md-button>
238+
<md-button toggle color="elevated">Toggle me</md-button>
239+
<md-button toggle color="tonal">Tonal</md-button>
240+
<md-button toggle color="outlined">Outlined</md-button>
241+
<md-button toggle shape="square">Toggle me</md-button>
242+
</div>
243+
235244
<h3>Chips</h3>
236245
<md-chip-set>
237246
<md-chip type="assist" label="Assist chip" @click=${this.clicked}>

0 commit comments

Comments
 (0)