@m3e/button 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +193 -0
  3. package/cem.config.mjs +16 -0
  4. package/demo/index.html +105 -0
  5. package/dist/css-custom-data.json +1582 -0
  6. package/dist/custom-elements.json +1753 -0
  7. package/dist/html-custom-data.json +83 -0
  8. package/dist/index.js +1781 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/index.min.js +468 -0
  11. package/dist/index.min.js.map +1 -0
  12. package/dist/src/ButtonElement.d.ts +429 -0
  13. package/dist/src/ButtonElement.d.ts.map +1 -0
  14. package/dist/src/ButtonShape.d.ts +3 -0
  15. package/dist/src/ButtonShape.d.ts.map +1 -0
  16. package/dist/src/ButtonSize.d.ts +3 -0
  17. package/dist/src/ButtonSize.d.ts.map +1 -0
  18. package/dist/src/ButtonVariant.d.ts +3 -0
  19. package/dist/src/ButtonVariant.d.ts.map +1 -0
  20. package/dist/src/index.d.ts +5 -0
  21. package/dist/src/index.d.ts.map +1 -0
  22. package/dist/src/styles/ButtonSizeStyle.d.ts +7 -0
  23. package/dist/src/styles/ButtonSizeStyle.d.ts.map +1 -0
  24. package/dist/src/styles/ButtonSizeToken.d.ts +27 -0
  25. package/dist/src/styles/ButtonSizeToken.d.ts.map +1 -0
  26. package/dist/src/styles/ButtonStyle.d.ts +7 -0
  27. package/dist/src/styles/ButtonStyle.d.ts.map +1 -0
  28. package/dist/src/styles/ButtonVariantStyle.d.ts +7 -0
  29. package/dist/src/styles/ButtonVariantStyle.d.ts.map +1 -0
  30. package/dist/src/styles/ButtonVariantToken.d.ts +75 -0
  31. package/dist/src/styles/ButtonVariantToken.d.ts.map +1 -0
  32. package/dist/src/styles/index.d.ts +4 -0
  33. package/dist/src/styles/index.d.ts.map +1 -0
  34. package/eslint.config.mjs +13 -0
  35. package/package.json +48 -0
  36. package/rollup.config.js +32 -0
  37. package/src/ButtonElement.ts +629 -0
  38. package/src/ButtonShape.ts +2 -0
  39. package/src/ButtonSize.ts +2 -0
  40. package/src/ButtonVariant.ts +2 -0
  41. package/src/index.ts +4 -0
  42. package/src/styles/ButtonSizeStyle.ts +102 -0
  43. package/src/styles/ButtonSizeToken.ts +180 -0
  44. package/src/styles/ButtonStyle.ts +191 -0
  45. package/src/styles/ButtonVariantStyle.ts +170 -0
  46. package/src/styles/ButtonVariantToken.ts +1165 -0
  47. package/src/styles/index.ts +3 -0
  48. package/tsconfig.json +9 -0
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./ButtonElement";
2
+ export * from "./ButtonShape";
3
+ export * from "./ButtonSize";
4
+ export * from "./ButtonVariant";
@@ -0,0 +1,102 @@
1
+ import { css, CSSResult, CSSResultGroup, unsafeCSS } from "lit";
2
+
3
+ import { ButtonSize } from "../ButtonSize";
4
+ import { ButtonSizeToken } from "./ButtonSizeToken";
5
+
6
+ /** @private */
7
+ function buttonStyle(size: ButtonSize): CSSResult {
8
+ return css`
9
+ :host([size="${unsafeCSS(size)}"]) .base {
10
+ height: ${ButtonSizeToken[size].containerHeight};
11
+ }
12
+ :host([size="${unsafeCSS(size)}"]) .wrapper {
13
+ padding-inline-start: ${ButtonSizeToken[size].leadingSpace};
14
+ padding-inline-end: ${ButtonSizeToken[size].trailingSpace};
15
+ column-gap: ${ButtonSizeToken[size].iconLabelSpace};
16
+ }
17
+ :host([size="${unsafeCSS(size)}"].-grouped:not(.-connected).-adjacent-pressed:not(.-pressed)) .wrapper {
18
+ padding-inline-start: calc(
19
+ ${ButtonSizeToken[size].leadingSpace} -
20
+ calc(calc(var(--_adjacent-button-width) * var(--m3e-standard-button-group-width-multiplier, 0.15)) / 4.25)
21
+ );
22
+ padding-inline-end: calc(
23
+ ${ButtonSizeToken[size].trailingSpace} -
24
+ calc(calc(var(--_adjacent-button-width) * var(--m3e-standard-button-group-width-multiplier, 0.15)) / 4.25)
25
+ );
26
+ }
27
+ :host([size="${unsafeCSS(size)}"]) .label {
28
+ font-size: ${ButtonSizeToken[size].labelTextFontSize};
29
+ font-weight: ${ButtonSizeToken[size].labelTextFontWeight};
30
+ line-height: ${ButtonSizeToken[size].labelTextLineHeight};
31
+ letter-spacing: ${ButtonSizeToken[size].labelTextTracking};
32
+ }
33
+ :host([size="${unsafeCSS(size)}"]) .icon {
34
+ font-size: ${ButtonSizeToken[size].iconSize};
35
+ --m3e-icon-size: ${ButtonSizeToken[size].iconSize};
36
+ }
37
+ :host([size="${unsafeCSS(size)}"]) .base {
38
+ outline-offset: calc(0px - ${ButtonSizeToken[size].outlineThickness});
39
+ outline-width: ${ButtonSizeToken[size].outlineThickness};
40
+ }
41
+ :host(:not(.-connected)[size="${unsafeCSS(size)}"][shape="rounded"]) .base {
42
+ border-radius: var(--_button-shape, ${ButtonSizeToken[size].shapeRound});
43
+ }
44
+ :host(:not(.-connected)[size="${unsafeCSS(size)}"][shape="rounded"][toggle][selected]:not(.-pressed)) .base {
45
+ border-radius: ${ButtonSizeToken[size].selectedShapeRound};
46
+ }
47
+ :host(:not(.-connected)[size="${unsafeCSS(size)}"][shape="square"]) .base {
48
+ border-radius: ${ButtonSizeToken[size].shapeSquare};
49
+ }
50
+ :host(:not(.-connected)[size="${unsafeCSS(size)}"][shape="square"][toggle][selected]:not(.-pressed)) .base {
51
+ border-radius: var(--_button-shape, ${ButtonSizeToken[size].selectedShapeSquare});
52
+ }
53
+ :host(:not(.-connected)[size="${unsafeCSS(size)}"].-pressed) .base {
54
+ border-radius: ${ButtonSizeToken[size].shapePressedMorph};
55
+ }
56
+ :host(.-connected[size="${unsafeCSS(size)}"][shape="rounded"]) .base {
57
+ border-start-start-radius: var(
58
+ --_button-rounded-start-shape,
59
+ var(--_button-shape, ${ButtonSizeToken[size].shapeRound})
60
+ );
61
+ border-end-start-radius: var(
62
+ --_button-rounded-start-shape,
63
+ var(--_button-shape, ${ButtonSizeToken[size].shapeRound})
64
+ );
65
+ border-start-end-radius: var(
66
+ --_button-rounded-end-shape,
67
+ var(--_button-shape, ${ButtonSizeToken[size].shapeRound})
68
+ );
69
+ border-end-end-radius: var(
70
+ --_button-rounded-end-shape,
71
+ var(--_button-shape, ${ButtonSizeToken[size].shapeRound})
72
+ );
73
+ }
74
+ :host(.-connected[size="${unsafeCSS(size)}"][shape="square"]) .base {
75
+ border-start-start-radius: var(--_button-square-start-shape, ${ButtonSizeToken[size].shapeSquare});
76
+ border-end-start-radius: var(--_button-square-start-shape, ${ButtonSizeToken[size].shapeSquare});
77
+ border-start-end-radius: var(--_button-square-end-shape, ${ButtonSizeToken[size].shapeSquare});
78
+ border-end-end-radius: var(--_button-square-end-shape, ${ButtonSizeToken[size].shapeSquare});
79
+ }
80
+ :host(.-connected[size="${unsafeCSS(size)}"][shape="square"][toggle][selected]:not(.-pressed)) .base {
81
+ border-radius: var(--_button-shape, ${ButtonSizeToken[size].selectedShapeSquare});
82
+ }
83
+ :host(.-connected[size="${unsafeCSS(size)}"].-pressed) .base {
84
+ border-start-start-radius: var(--_button-start-shape-pressed-morph, ${ButtonSizeToken[size].shapePressedMorph});
85
+ border-end-start-radius: var(--_button-start-shape-pressed-morph, ${ButtonSizeToken[size].shapePressedMorph});
86
+ border-start-end-radius: var(--_button-end-shape-pressed-morph, ${ButtonSizeToken[size].shapePressedMorph});
87
+ border-end-end-radius: var(--_button-end-shape-pressed-morph, ${ButtonSizeToken[size].shapePressedMorph});
88
+ }
89
+ `;
90
+ }
91
+
92
+ /**
93
+ * Size variant styles for `M3eButtonElement`.
94
+ * @internal
95
+ */
96
+ export const ButtonSizeStyle: CSSResultGroup = [
97
+ buttonStyle("extra-small"),
98
+ buttonStyle("small"),
99
+ buttonStyle("medium"),
100
+ buttonStyle("large"),
101
+ buttonStyle("extra-large"),
102
+ ];
@@ -0,0 +1,180 @@
1
+ import { CSSResult, unsafeCSS } from "lit";
2
+
3
+ import { DesignToken } from "@m3e/core";
4
+
5
+ import { ButtonSize } from "../ButtonSize";
6
+
7
+ /** @private */
8
+ type _ButtonSizeToken = {
9
+ containerHeight: CSSResult;
10
+ outlineThickness: CSSResult;
11
+ labelTextFontSize: CSSResult;
12
+ labelTextFontWeight: CSSResult;
13
+ labelTextLineHeight: CSSResult;
14
+ labelTextTracking: CSSResult;
15
+ iconSize: CSSResult;
16
+ shapeRound: CSSResult;
17
+ shapeSquare: CSSResult;
18
+ selectedShapeRound: CSSResult;
19
+ selectedShapeSquare: CSSResult;
20
+ shapePressedMorph: CSSResult;
21
+ leadingSpace: CSSResult;
22
+ trailingSpace: CSSResult;
23
+ iconLabelSpace: CSSResult;
24
+ };
25
+
26
+ /**
27
+ * Component design tokens that control the `M3eButtonElement` for all size variants.
28
+ * @internal
29
+ */
30
+ export const ButtonSizeToken: Record<ButtonSize, _ButtonSizeToken> = {
31
+ "extra-small": {
32
+ containerHeight: unsafeCSS(
33
+ `calc(var(--m3e-button-extra-small-container-height, 2rem) + ${DesignToken.density.calc(0)})`
34
+ ),
35
+ outlineThickness: unsafeCSS("var(--m3e-button-extra-small-outline-thickness, 1px)"),
36
+ labelTextFontSize: unsafeCSS(
37
+ `var(--m3e-button-extra-small-label-text-font-size, ${DesignToken.typescale.standard.label.large.fontSize})`
38
+ ),
39
+ labelTextFontWeight: unsafeCSS(
40
+ `var(--m3e-button-extra-small-label-text-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight})`
41
+ ),
42
+ labelTextLineHeight: unsafeCSS(
43
+ `var(--m3e-button-extra-small-label-text-line-height, ${DesignToken.typescale.standard.label.large.lineHeight})`
44
+ ),
45
+ labelTextTracking: unsafeCSS(
46
+ `var(--m3e-button-extra-small-label-text-tracking, ${DesignToken.typescale.standard.label.large.tracking})`
47
+ ),
48
+ iconSize: unsafeCSS("var(--m3e-button-extra-small-icon-size, 1.25rem)"),
49
+ shapeRound: unsafeCSS(`var(--m3e-button-extra-small-shape-round, ${DesignToken.shape.corner.full})`),
50
+ shapeSquare: unsafeCSS(`var(--m3e-button-extra-small-shape-square, ${DesignToken.shape.corner.medium})`),
51
+ selectedShapeRound: unsafeCSS(
52
+ `var(--m3e-button-extra-small-selected-shape-round, ${DesignToken.shape.corner.medium})`
53
+ ),
54
+ selectedShapeSquare: unsafeCSS(
55
+ `var(--m3e-button-extra-small-selected-shape-square, ${DesignToken.shape.corner.full})`
56
+ ),
57
+ shapePressedMorph: unsafeCSS(
58
+ `var(--m3e-button-extra-small-shape-pressed-morph, ${DesignToken.shape.corner.small})`
59
+ ),
60
+ leadingSpace: unsafeCSS("var(--m3e-button-extra-small-leading-space, 0.75rem)"),
61
+ trailingSpace: unsafeCSS("var(--m3e-button-extra-small-trailing-space, 0.75rem)"),
62
+ iconLabelSpace: unsafeCSS("var(--m3e-button-extra-small-icon-label-space, 0.5rem)"),
63
+ },
64
+ small: {
65
+ containerHeight: unsafeCSS(
66
+ `calc(var(--m3e-button-small-container-height, 2.5rem) + ${DesignToken.density.calc(-1)})`
67
+ ),
68
+ outlineThickness: unsafeCSS("var(--m3e-button-small-outline-thickness, 1px)"),
69
+ labelTextFontSize: unsafeCSS(
70
+ `var(--m3e-button-small-label-text-font-size, ${DesignToken.typescale.standard.label.large.fontSize})`
71
+ ),
72
+ labelTextFontWeight: unsafeCSS(
73
+ `var(--m3e-button-small-label-text-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight})`
74
+ ),
75
+ labelTextLineHeight: unsafeCSS(
76
+ `var(--m3e-button-small-label-text-line-height, ${DesignToken.typescale.standard.label.large.lineHeight})`
77
+ ),
78
+ labelTextTracking: unsafeCSS(
79
+ `var(--m3e-button-small-label-text-tracking, ${DesignToken.typescale.standard.label.large.tracking})`
80
+ ),
81
+ iconSize: unsafeCSS("var(--m3e-button-small-icon-size, 1.25rem)"),
82
+ shapeRound: unsafeCSS(`var(--m3e-button-small-shape-round, ${DesignToken.shape.corner.full})`),
83
+ shapeSquare: unsafeCSS(`var(--m3e-button-small-shape-square, ${DesignToken.shape.corner.medium})`),
84
+ selectedShapeRound: unsafeCSS(`var(--m3e-button-small-selected-shape-round, ${DesignToken.shape.corner.medium})`),
85
+ selectedShapeSquare: unsafeCSS(`var(--m3e-button-small-selected-shape-square, ${DesignToken.shape.corner.full})`),
86
+ shapePressedMorph: unsafeCSS(`var(--m3e-button-small-shape-pressed-morph, ${DesignToken.shape.corner.small})`),
87
+ leadingSpace: unsafeCSS("var(--m3e-button-small-leading-space, 1rem)"),
88
+ trailingSpace: unsafeCSS("var(--m3e-button-small-trailing-space, 1rem)"),
89
+ iconLabelSpace: unsafeCSS("var(--m3e-button-small-icon-label-space, 0.5rem)"),
90
+ },
91
+ medium: {
92
+ containerHeight: unsafeCSS(
93
+ `calc(var(--m3e-button-medium-container-height, 3.5rem) + ${DesignToken.density.calc(-2)})`
94
+ ),
95
+ outlineThickness: unsafeCSS("var(--m3e-button-medium-outline-thickness, 1px)"),
96
+ labelTextFontSize: unsafeCSS(
97
+ `var(--m3e-button-medium-label-text-font-size, ${DesignToken.typescale.standard.body.large.fontSize})`
98
+ ),
99
+ labelTextFontWeight: unsafeCSS(
100
+ `var(--m3e-button-medium-label-text-font-weight, ${DesignToken.typescale.standard.body.large.fontWeight})`
101
+ ),
102
+ labelTextLineHeight: unsafeCSS(
103
+ `var(--m3e-button-medium-label-text-line-height, ${DesignToken.typescale.standard.body.large.lineHeight})`
104
+ ),
105
+ labelTextTracking: unsafeCSS(
106
+ `var(--m3e-button-medium-label-text-tracking, ${DesignToken.typescale.standard.body.large.tracking})`
107
+ ),
108
+ iconSize: unsafeCSS("var(--m3e-button-medium-icon-size, 1.5rem)"),
109
+ shapeRound: unsafeCSS(`var(--m3e-button-medium-shape-round, ${DesignToken.shape.corner.full})`),
110
+ shapeSquare: unsafeCSS(`var(--m3e-button-medium-shape-square, ${DesignToken.shape.corner.large})`),
111
+ selectedShapeRound: unsafeCSS(`var(--m3e-button-medium-selected-shape-round, ${DesignToken.shape.corner.large})`),
112
+ selectedShapeSquare: unsafeCSS(`var(--m3e-button-medium-selected-shape-square, ${DesignToken.shape.corner.full})`),
113
+ shapePressedMorph: unsafeCSS(`var(--m3e-button-medium-shape-pressed-morph, ${DesignToken.shape.corner.medium})`),
114
+ leadingSpace: unsafeCSS("var(--m3e-button-medium-leading-space, 1.5rem)"),
115
+ trailingSpace: unsafeCSS("var(--m3e-button-medium-trailing-space, 1.5rem)"),
116
+ iconLabelSpace: unsafeCSS("var(--m3e-button-medium-icon-label-space, 0.5rem)"),
117
+ },
118
+ large: {
119
+ containerHeight: unsafeCSS(
120
+ `calc(var(--m3e-button-large-container-height, 6rem) + ${DesignToken.density.calc(-3)})`
121
+ ),
122
+ outlineThickness: unsafeCSS("var(--m3e-button-large-outline-thickness, 0.125rem)"),
123
+ labelTextFontSize: unsafeCSS(
124
+ `var(--m3e-button-large-label-text-font-size, ${DesignToken.typescale.standard.headline.small.fontSize})`
125
+ ),
126
+ labelTextFontWeight: unsafeCSS(
127
+ `var(--m3e-button-large-label-text-font-weight, ${DesignToken.typescale.standard.headline.small.fontWeight})`
128
+ ),
129
+ labelTextLineHeight: unsafeCSS(
130
+ `var(--m3e-button-large-label-text-line-height, ${DesignToken.typescale.standard.headline.small.lineHeight})`
131
+ ),
132
+ labelTextTracking: unsafeCSS(
133
+ `var(--m3e-button-large-label-text-tracking, ${DesignToken.typescale.standard.headline.small.tracking})`
134
+ ),
135
+ iconSize: unsafeCSS("var(--m3e-button-large-icon-size, 2rem)"),
136
+ shapeRound: unsafeCSS(`var(--m3e-button-large-shape-round, ${DesignToken.shape.corner.full})`),
137
+ shapeSquare: unsafeCSS(`var(--m3e-button-large-shape-square, ${DesignToken.shape.corner.extraLarge})`),
138
+ selectedShapeRound: unsafeCSS(
139
+ `var(--m3e-button-large-selected-shape-round, ${DesignToken.shape.corner.extraLarge})`
140
+ ),
141
+ selectedShapeSquare: unsafeCSS(`var(--m3e-button-large-selected-shape-square, ${DesignToken.shape.corner.full})`),
142
+ shapePressedMorph: unsafeCSS(`var(--m3e-button-large-shape-pressed-morph, ${DesignToken.shape.corner.large})`),
143
+ leadingSpace: unsafeCSS("var(--m3e-button-large-leading-space, 3rem)"),
144
+ trailingSpace: unsafeCSS("var(--m3e-button-large-trailing-space, 3rem)"),
145
+ iconLabelSpace: unsafeCSS("var(--m3e-button-large-icon-label-space, 0.75rem)"),
146
+ },
147
+ "extra-large": {
148
+ containerHeight: unsafeCSS(
149
+ `calc(var(--m3e-button-extra-large-container-height, 8.5rem) + ${DesignToken.density.calc(-3)})`
150
+ ),
151
+ outlineThickness: unsafeCSS("var(--m3e-button-extra-large-outline-thickness, 0.1875rem)"),
152
+ labelTextFontSize: unsafeCSS(
153
+ `var(--m3e-button-extra-large-label-text-font-size, ${DesignToken.typescale.standard.headline.large.fontSize})`
154
+ ),
155
+ labelTextFontWeight: unsafeCSS(
156
+ `var(--m3e-button-extra-large-label-text-font-weight, ${DesignToken.typescale.standard.headline.large.fontWeight})`
157
+ ),
158
+ labelTextLineHeight: unsafeCSS(
159
+ `var(--m3e-button-extra-large-label-text-line-height, ${DesignToken.typescale.standard.headline.large.lineHeight})`
160
+ ),
161
+ labelTextTracking: unsafeCSS(
162
+ `var(--m3e-button-extra-large-label-text-tracking, ${DesignToken.typescale.standard.headline.large.tracking})`
163
+ ),
164
+ iconSize: unsafeCSS("var(--m3e-button-extra-large-icon-size, 2.5rem)"),
165
+ shapeRound: unsafeCSS(`var(--m3e-button-extra-large-shape-round, ${DesignToken.shape.corner.full})`),
166
+ shapeSquare: unsafeCSS(`var(--m3e-button-extra-large-shape-square, ${DesignToken.shape.corner.extraLarge})`),
167
+ selectedShapeRound: unsafeCSS(
168
+ `var(--m3e-button-extra-large-selected-shape-round, ${DesignToken.shape.corner.extraLarge})`
169
+ ),
170
+ selectedShapeSquare: unsafeCSS(
171
+ `var(--m3e-button-extra-large-selected-shape-square, ${DesignToken.shape.corner.full})`
172
+ ),
173
+ shapePressedMorph: unsafeCSS(
174
+ `var(--m3e-button-extra-large-shape-pressed-morph, ${DesignToken.shape.corner.large})`
175
+ ),
176
+ leadingSpace: unsafeCSS("var(--m3e-button-extra-large-leading-space, 4rem)"),
177
+ trailingSpace: unsafeCSS("var(--m3e-button-extra-large-trailing-space, 4rem)"),
178
+ iconLabelSpace: unsafeCSS("var(--m3e-button-extra-large-icon-label-space, 1rem)"),
179
+ },
180
+ } as const;
@@ -0,0 +1,191 @@
1
+ import { css, CSSResultGroup, unsafeCSS } from "lit";
2
+
3
+ import { DesignToken } from "@m3e/core";
4
+
5
+ /**
6
+ * Baseline styles for `M3eButtonElement`.
7
+ * @internal
8
+ */
9
+ export const ButtonStyle: CSSResultGroup = css`
10
+ :host {
11
+ display: inline-block;
12
+ outline: none;
13
+ user-select: none;
14
+ }
15
+ .base {
16
+ box-sizing: border-box;
17
+ vertical-align: middle;
18
+ display: inline-flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ position: relative;
22
+ width: 100%;
23
+ transition: ${unsafeCSS(
24
+ `background-color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard}`
25
+ )};
26
+ }
27
+ .touch {
28
+ position: absolute;
29
+ height: 3rem;
30
+ left: 0;
31
+ right: 0;
32
+ }
33
+ :host(.-pressed) .base,
34
+ :host(.-resting) .base {
35
+ transition: ${unsafeCSS(`background-color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard},
36
+ border-radius ${DesignToken.motion.spring.fastEffects}`)};
37
+ }
38
+ .wrapper {
39
+ width: 100%;
40
+ overflow: hidden;
41
+ display: inline-flex;
42
+ align-items: center;
43
+ }
44
+ .label {
45
+ justify-self: center;
46
+ flex: 1 1 auto;
47
+ text-align: center;
48
+ white-space: nowrap;
49
+ overflow: hidden;
50
+ text-overflow: ellipsis;
51
+ transition: ${unsafeCSS(`color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard}`)};
52
+ }
53
+ .icon {
54
+ transition: ${unsafeCSS(`color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard}`)};
55
+ }
56
+ :host(:not(:disabled):not([disabled-interactive])) {
57
+ cursor: pointer;
58
+ }
59
+ :host([disabled-interactive]) {
60
+ cursor: not-allowed;
61
+ }
62
+ ::slotted([slot="icon"]),
63
+ ::slotted([slot="selected-icon"]),
64
+ ::slotted([slot="trailing-icon"]) {
65
+ font-size: inherit !important;
66
+ flex: none;
67
+ }
68
+ ::slotted(svg[slot="icon"]),
69
+ ::slotted(svg[slot="selected-icon"]),
70
+ ::slotted(svg[slot="trailing-icon"]) {
71
+ width: 1em;
72
+ height: 1em;
73
+ }
74
+ :host([toggle]:not([selected])) .base.with-selected-icon slot[name="selected-icon"],
75
+ :host([toggle][selected]) .base.with-selected-icon slot[name="icon"] {
76
+ display: none;
77
+ }
78
+ a {
79
+ all: unset;
80
+ display: block;
81
+ position: absolute;
82
+ top: 0px;
83
+ left: 0px;
84
+ right: 0px;
85
+ bottom: 0px;
86
+ z-index: 1;
87
+ }
88
+ :host(.-grouped.-connected) {
89
+ flex: 1 1 auto;
90
+ }
91
+ :host(.-grouped:not(.-connected)) {
92
+ transition: ${unsafeCSS(`padding-inline ${DesignToken.motion.spring.fastEffects}`)};
93
+ }
94
+ :host(.-grouped:not(.-connected):not(.-adjacent-pressed):not(.-pressed)) {
95
+ flex-shrink: 0;
96
+ flex-grow: 0;
97
+ }
98
+ :host(.-grouped:not(.-connected).-adjacent-pressed:not(.-pressed)) {
99
+ flex-shrink: 1;
100
+ min-width: 0;
101
+ }
102
+ :host(.-grouped:not(.-connected).-adjacent-pressed:not(.-pressed)) .label {
103
+ text-overflow: clip;
104
+ }
105
+ :host(.-grouped:not(.-connected).-pressed:not([disabled-interactive]):not(:disabled)) {
106
+ flex-shrink: 0;
107
+ flex-basis: calc(
108
+ var(--_button-width) + calc(var(--_button-width) * var(--m3e-standard-button-group-width-multiplier, 0.15))
109
+ );
110
+ }
111
+ @media (forced-colors: active) {
112
+ .base,
113
+ .label,
114
+ .icon {
115
+ transition: none;
116
+ }
117
+ :host(.-pressed) .base,
118
+ :host(.-resting) .base {
119
+ transition: ${unsafeCSS(`border-radius ${DesignToken.motion.spring.fastEffects}`)};
120
+ }
121
+ :host([variant]:not(:disabled):not([disabled-interactive]):not([toggle])) .base {
122
+ background-color: ButtonFace;
123
+ outline-color: ButtonText;
124
+ }
125
+ :host([variant]:not(:disabled):not([disabled-interactive]):not([toggle])) .label,
126
+ :host([variant]:not(:disabled):not([disabled-interactive]):not([toggle])) .icon {
127
+ color: ButtonText;
128
+ }
129
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle]:not([selected])) .base {
130
+ background-color: ButtonFace;
131
+ outline-color: ButtonText;
132
+ }
133
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle]:not([selected])) .label,
134
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle]:not([selected])) .icon {
135
+ color: ButtonText;
136
+ }
137
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle][selected]) .base {
138
+ background-color: ButtonText;
139
+ outline: none;
140
+ }
141
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle][selected]) .label,
142
+ :host([variant]:not(:disabled):not([disabled-interactive])[toggle][selected]) .icon {
143
+ forced-color-adjust: none;
144
+ color: ButtonFace;
145
+ background-color: ButtonText;
146
+ }
147
+ :host([variant]:disabled) .base,
148
+ :host([variant][disabled-interactive]) .base {
149
+ outline-color: GrayText;
150
+ background-color: unset;
151
+ }
152
+ :host([variant]:disabled) .label,
153
+ :host([variant][disabled-interactive]) .label,
154
+ :host([variant]:disabled) .icon,
155
+ :host([variant][disabled-interactive]) .icon {
156
+ color: GrayText;
157
+ }
158
+ .base {
159
+ outline-style: solid;
160
+ }
161
+ :host([size="extra-small"]) .base {
162
+ outline-offset: calc(0px - var(--m3e-button-extra-small-outline-thickness, 1px));
163
+ outline-width: var(--m3e-button-extra-small-outline-thickness, 1px);
164
+ }
165
+ :host([size="small"]) .base {
166
+ outline-offset: calc(0px - var(--m3e-button-small-outline-thickness, 1px));
167
+ outline-width: var(--m3e-button-small-outline-thickness, 1px);
168
+ }
169
+ :host([size="medium"]) .base {
170
+ outline-offset: calc(0px - var(--m3e-button-medium-outline-thickness, 1px));
171
+ outline-width: var(--m3e-button-medium-outline-thickness, 1px);
172
+ }
173
+ :host([size="large"]) .base {
174
+ outline-offset: calc(0px - var(--m3e-button-large-outline-thickness, 0.125rem));
175
+ outline-width: var(--m3e-button-large-outline-thickness, 0.125rem);
176
+ }
177
+ :host([size="extra-large"]) .base {
178
+ outline-offset: calc(0px - var(--m3e-button-extra-large-outline-thickness, 0.1875rem));
179
+ outline-width: var(--m3e-button-extra-large-outline-thickness, 0.1875rem);
180
+ }
181
+ }
182
+ @media (prefers-reduced-motion) {
183
+ :host(.-pressed) .base,
184
+ :host(.-resting) .base,
185
+ .base,
186
+ .label,
187
+ .icon {
188
+ transition: none;
189
+ }
190
+ }
191
+ `;
@@ -0,0 +1,170 @@
1
+ import { css, CSSResult, CSSResultGroup, unsafeCSS } from "lit";
2
+
3
+ import { ButtonVariant } from "../ButtonVariant";
4
+ import { ButtonVariantToken } from "./ButtonVariantToken";
5
+
6
+ /** @private */
7
+ function buttonVariantStyle(variant: ButtonVariant): CSSResult {
8
+ return css`
9
+ :host([variant="${unsafeCSS(variant)}"]:not(:disabled):not([disabled-interactive])) .base {
10
+ background-color: ${ButtonVariantToken[variant].containerColor ?? unsafeCSS("unset")};
11
+ --m3e-state-layer-hover-color: ${ButtonVariantToken[variant].hover.stateLayerColor};
12
+ --m3e-state-layer-hover-opacity: ${ButtonVariantToken[variant].hover.stateLayerOpacity};
13
+ --m3e-state-layer-focus-color: ${ButtonVariantToken[variant].focus.stateLayerColor};
14
+ --m3e-state-layer-focus-opacity: ${ButtonVariantToken[variant].focus.stateLayerOpacity};
15
+ --m3e-ripple-color: ${ButtonVariantToken[variant].pressed.stateLayerColor};
16
+ --m3e-ripple-opacity: ${ButtonVariantToken[variant].pressed.stateLayerOpacity};
17
+ --m3e-elevation-level: ${ButtonVariantToken[variant].containerElevation ?? unsafeCSS("unset")};
18
+ --m3e-elevation-hover-level: ${ButtonVariantToken[variant].hover.containerElevation ?? unsafeCSS("unset")};
19
+ --m3e-elevation-focus-level: ${ButtonVariantToken[variant].focus.containerElevation ?? unsafeCSS("unset")};
20
+ --m3e-elevation-pressed-level: ${ButtonVariantToken[variant].pressed.containerElevation ?? unsafeCSS("unset")};
21
+ }
22
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):not(:disabled):not([disabled-interactive])) .base {
23
+ background-color: ${ButtonVariantToken[variant].unselectedContainerColor ?? unsafeCSS("unset")};
24
+ --m3e-state-layer-hover-color: ${ButtonVariantToken[variant].hover.unselectedStateLayerColor};
25
+ --m3e-state-layer-focus-color: ${ButtonVariantToken[variant].focus.unselectedStateLayerColor};
26
+ --m3e-ripple-color: ${ButtonVariantToken[variant].pressed.unselectedStateLayerColor};
27
+ }
28
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:not(:disabled):not([disabled-interactive])) .base {
29
+ background-color: ${ButtonVariantToken[variant].selectedContainerColor ?? unsafeCSS("unset")};
30
+ --m3e-state-layer-hover-color: ${ButtonVariantToken[variant].hover.selectedStateLayerColor};
31
+ --m3e-state-layer-focus-color: ${ButtonVariantToken[variant].focus.selectedStateLayerColor};
32
+ --m3e-ripple-color: ${ButtonVariantToken[variant].pressed.selectedStateLayerColor};
33
+ }
34
+ :host([variant="${unsafeCSS(variant)}"]:not(:disabled):not([disabled-interactive])) .base {
35
+ outline-color: ${ButtonVariantToken[variant].outlineColor ?? unsafeCSS("unset")};
36
+ }
37
+ :host([variant="${unsafeCSS(variant)}"]:focus:not(:disabled):not([disabled-interactive])) .base {
38
+ outline-color: ${ButtonVariantToken[variant].focus.outlineColor ?? unsafeCSS("unset")};
39
+ }
40
+ :host([variant="${unsafeCSS(variant)}"]:hover:not(:disabled):not([disabled-interactive])) .base {
41
+ outline-color: ${ButtonVariantToken[variant].hover.outlineColor ?? unsafeCSS("unset")};
42
+ }
43
+ :host([variant="${unsafeCSS(variant)}"].-pressed:not(:disabled):not([disabled-interactive])) .base {
44
+ outline-color: ${ButtonVariantToken[variant].pressed.outlineColor ?? unsafeCSS("unset")};
45
+ }
46
+ :host([variant="${unsafeCSS(variant)}"]:not(:disabled):not([disabled-interactive])) .label {
47
+ color: ${ButtonVariantToken[variant].labelTextColor};
48
+ }
49
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):not(:disabled):not([disabled-interactive])) .label {
50
+ color: ${ButtonVariantToken[variant].unselectedLabelTextColor};
51
+ }
52
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:not(:disabled):not([disabled-interactive])) .label {
53
+ color: ${ButtonVariantToken[variant].selectedLabelTextColor};
54
+ }
55
+ :host([variant="${unsafeCSS(variant)}"]:focus:not(:disabled):not([disabled-interactive])) .label {
56
+ color: ${ButtonVariantToken[variant].focus.labelTextColor};
57
+ }
58
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):focus:not(:disabled):not([disabled-interactive]))
59
+ .label {
60
+ color: ${ButtonVariantToken[variant].focus.unselectedLabelTextColor};
61
+ }
62
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:focus:not(:disabled):not([disabled-interactive])) .label {
63
+ color: ${ButtonVariantToken[variant].focus.selectedLabelTextColor};
64
+ }
65
+ :host([variant="${unsafeCSS(variant)}"]:hover:not(:disabled):not([disabled-interactive])) .label {
66
+ color: ${ButtonVariantToken[variant].hover.labelTextColor};
67
+ }
68
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):hover:not(:disabled):not([disabled-interactive]))
69
+ .label {
70
+ color: ${ButtonVariantToken[variant].hover.unselectedLabelTextColor};
71
+ }
72
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:hover:not(:disabled):not([disabled-interactive])) .label {
73
+ color: ${ButtonVariantToken[variant].hover.selectedLabelTextColor};
74
+ }
75
+ :host([variant="${unsafeCSS(variant)}"].-pressed:not(:disabled):not([disabled-interactive])) .label {
76
+ color: ${ButtonVariantToken[variant].pressed.labelTextColor};
77
+ }
78
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]).-pressed:not(:disabled):not([disabled-interactive]))
79
+ .label {
80
+ color: ${ButtonVariantToken[variant].pressed.unselectedLabelTextColor};
81
+ }
82
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected].-pressed:not(:disabled):not([disabled-interactive]))
83
+ .label {
84
+ color: ${ButtonVariantToken[variant].pressed.selectedLabelTextColor};
85
+ }
86
+ :host([variant="${unsafeCSS(variant)}"]:not(:disabled):not([disabled-interactive])) .icon {
87
+ color: ${ButtonVariantToken[variant].iconColor};
88
+ }
89
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):not(:disabled):not([disabled-interactive])) .icon {
90
+ color: ${ButtonVariantToken[variant].unselectedIconColor};
91
+ }
92
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:not(:disabled):not([disabled-interactive])) .icon {
93
+ color: ${ButtonVariantToken[variant].selectedIconColor};
94
+ }
95
+ :host([variant="${unsafeCSS(variant)}"]:focus:not(:disabled):not([disabled-interactive])) .icon {
96
+ color: ${ButtonVariantToken[variant].focus.iconColor};
97
+ }
98
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):focus:not(:disabled):not([disabled-interactive]))
99
+ .icon {
100
+ color: ${ButtonVariantToken[variant].focus.unselectedIconColor};
101
+ }
102
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:focus:not(:disabled):not([disabled-interactive])) .icon {
103
+ color: ${ButtonVariantToken[variant].focus.selectedIconColor};
104
+ }
105
+ :host([variant="${unsafeCSS(variant)}"]:hover:not(:disabled):not([disabled-interactive])) .icon {
106
+ color: ${ButtonVariantToken[variant].hover.iconColor};
107
+ }
108
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]):hover:not(:disabled):not([disabled-interactive]))
109
+ .icon {
110
+ color: ${ButtonVariantToken[variant].hover.unselectedIconColor};
111
+ }
112
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected]:hover:not(:disabled):not([disabled-interactive])) .icon {
113
+ color: ${ButtonVariantToken[variant].hover.selectedIconColor};
114
+ }
115
+ :host([variant="${unsafeCSS(variant)}"].-pressed:not(:disabled):not([disabled-interactive])) .icon {
116
+ color: ${ButtonVariantToken[variant].pressed.iconColor};
117
+ }
118
+ :host([variant="${unsafeCSS(variant)}"][toggle]:not([selected]).-pressed:not(:disabled):not([disabled-interactive]))
119
+ .icon {
120
+ color: ${ButtonVariantToken[variant].pressed.unselectedIconColor};
121
+ }
122
+ :host([variant="${unsafeCSS(variant)}"][toggle][selected].-pressed:not(:disabled):not([disabled-interactive]))
123
+ .icon {
124
+ color: ${ButtonVariantToken[variant].pressed.selectedIconColor};
125
+ }
126
+ :host([variant="${unsafeCSS(variant)}"]:disabled) .base,
127
+ :host([variant="${unsafeCSS(variant)}"][disabled-interactive]) .base {
128
+ --m3e-elevation-level: ${ButtonVariantToken[variant].disabled.containerElevation ?? unsafeCSS("unset")};
129
+ outline-color: ${ButtonVariantToken[variant].disabled.outlineColor ?? unsafeCSS("unset")};
130
+ background-color: color-mix(
131
+ in srgb,
132
+ ${ButtonVariantToken[variant].disabled.containerColor} ${ButtonVariantToken[variant].disabled.containerOpacity},
133
+ transparent
134
+ );
135
+ }
136
+ :host([variant="${unsafeCSS(variant)}"]:disabled) .label,
137
+ :host([variant="${unsafeCSS(variant)}"][disabled-interactive]) .label {
138
+ color: color-mix(
139
+ in srgb,
140
+ ${ButtonVariantToken[variant].disabled.labelTextColor} ${ButtonVariantToken[variant].disabled.labelTextOpacity},
141
+ transparent
142
+ );
143
+ }
144
+ :host([variant="${unsafeCSS(variant)}"]:disabled) .icon,
145
+ :host([variant="${unsafeCSS(variant)}"][disabled-interactive]) .icon {
146
+ color: color-mix(
147
+ in srgb,
148
+ ${ButtonVariantToken[variant].disabled.iconColor} ${ButtonVariantToken[variant].disabled.iconOpacity},
149
+ transparent
150
+ );
151
+ }
152
+ `;
153
+ }
154
+
155
+ /**
156
+ * Appearance variant styles for `M3eButtonElement`.
157
+ * @internal
158
+ */
159
+ export const ButtonVariantStyle: CSSResultGroup = [
160
+ buttonVariantStyle("text"),
161
+ buttonVariantStyle("elevated"),
162
+ buttonVariantStyle("outlined"),
163
+ buttonVariantStyle("filled"),
164
+ buttonVariantStyle("tonal"),
165
+ css`
166
+ :host([variant="outlined"]) .base {
167
+ outline-style: solid;
168
+ }
169
+ `,
170
+ ];