mtrl 0.1.2 → 0.2.0

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 (220) hide show
  1. package/README.md +70 -22
  2. package/index.ts +33 -0
  3. package/package.json +14 -5
  4. package/src/components/button/{styles.scss → _styles.scss} +2 -2
  5. package/src/components/button/api.ts +89 -0
  6. package/src/components/button/button.ts +50 -0
  7. package/src/components/button/config.ts +75 -0
  8. package/src/components/button/constants.ts +17 -0
  9. package/src/components/button/index.ts +4 -0
  10. package/src/components/button/types.ts +118 -0
  11. package/src/components/card/_styles.scss +359 -0
  12. package/src/components/card/actions.ts +48 -0
  13. package/src/components/card/api.ts +102 -0
  14. package/src/components/card/card.ts +41 -0
  15. package/src/components/card/config.ts +99 -0
  16. package/src/components/card/constants.ts +69 -0
  17. package/src/components/card/content.ts +48 -0
  18. package/src/components/card/features.ts +228 -0
  19. package/src/components/card/header.ts +88 -0
  20. package/src/components/card/index.ts +19 -0
  21. package/src/components/card/media.ts +52 -0
  22. package/src/components/card/types.ts +174 -0
  23. package/src/components/checkbox/api.ts +82 -0
  24. package/src/components/checkbox/checkbox.ts +75 -0
  25. package/src/components/checkbox/config.ts +90 -0
  26. package/src/components/checkbox/index.ts +4 -0
  27. package/src/components/checkbox/types.ts +146 -0
  28. package/src/components/chip/_styles.scss +372 -0
  29. package/src/components/chip/api.ts +115 -0
  30. package/src/components/chip/chip-set.ts +225 -0
  31. package/src/components/chip/chip.ts +82 -0
  32. package/src/components/chip/config.ts +92 -0
  33. package/src/components/chip/constants.ts +38 -0
  34. package/src/components/chip/index.ts +4 -0
  35. package/src/components/chip/types.ts +172 -0
  36. package/src/components/list/api.ts +72 -0
  37. package/src/components/list/config.ts +43 -0
  38. package/src/components/list/{constants.js → constants.ts} +34 -7
  39. package/src/components/list/features.ts +224 -0
  40. package/src/components/list/index.ts +14 -0
  41. package/src/components/list/list-item.ts +120 -0
  42. package/src/components/list/list.ts +37 -0
  43. package/src/components/list/types.ts +179 -0
  44. package/src/components/list/utils.ts +47 -0
  45. package/src/components/menu/api.ts +119 -0
  46. package/src/components/menu/config.ts +54 -0
  47. package/src/components/menu/constants.ts +154 -0
  48. package/src/components/menu/features/items-manager.ts +457 -0
  49. package/src/components/menu/features/keyboard-navigation.ts +133 -0
  50. package/src/components/menu/features/positioning.ts +127 -0
  51. package/src/components/menu/features/{visibility.js → visibility.ts} +66 -64
  52. package/src/components/menu/index.ts +14 -0
  53. package/src/components/menu/menu-item.ts +43 -0
  54. package/src/components/menu/menu.ts +53 -0
  55. package/src/components/menu/types.ts +178 -0
  56. package/src/components/navigation/api.ts +79 -0
  57. package/src/components/navigation/config.ts +61 -0
  58. package/src/components/navigation/{constants.js → constants.ts} +10 -10
  59. package/src/components/navigation/index.ts +14 -0
  60. package/src/components/navigation/nav-item.ts +148 -0
  61. package/src/components/navigation/navigation.ts +50 -0
  62. package/src/components/navigation/types.ts +212 -0
  63. package/src/components/progress/_styles.scss +204 -0
  64. package/src/components/progress/api.ts +179 -0
  65. package/src/components/progress/config.ts +124 -0
  66. package/src/components/progress/constants.ts +43 -0
  67. package/src/components/progress/index.ts +5 -0
  68. package/src/components/progress/progress.ts +163 -0
  69. package/src/components/progress/types.ts +102 -0
  70. package/src/components/snackbar/api.ts +162 -0
  71. package/src/components/snackbar/config.ts +62 -0
  72. package/src/components/snackbar/{constants.js → constants.ts} +21 -4
  73. package/src/components/snackbar/features.ts +76 -0
  74. package/src/components/snackbar/index.ts +4 -0
  75. package/src/components/snackbar/position.ts +71 -0
  76. package/src/components/snackbar/queue.ts +76 -0
  77. package/src/components/snackbar/snackbar.ts +60 -0
  78. package/src/components/snackbar/types.ts +58 -0
  79. package/src/components/switch/api.ts +77 -0
  80. package/src/components/switch/config.ts +74 -0
  81. package/src/components/switch/index.ts +4 -0
  82. package/src/components/switch/switch.ts +52 -0
  83. package/src/components/switch/types.ts +142 -0
  84. package/src/components/textfield/api.ts +72 -0
  85. package/src/components/textfield/config.ts +54 -0
  86. package/src/components/textfield/{constants.js → constants.ts} +38 -5
  87. package/src/components/textfield/index.ts +4 -0
  88. package/src/components/textfield/textfield.ts +50 -0
  89. package/src/components/textfield/types.ts +139 -0
  90. package/src/core/compose/base.ts +43 -0
  91. package/src/core/compose/component.ts +247 -0
  92. package/src/core/compose/features/checkable.ts +155 -0
  93. package/src/core/compose/features/disabled.ts +116 -0
  94. package/src/core/compose/features/events.ts +65 -0
  95. package/src/core/compose/features/icon.ts +67 -0
  96. package/src/core/compose/features/index.ts +35 -0
  97. package/src/core/compose/features/input.ts +174 -0
  98. package/src/core/compose/features/lifecycle.ts +139 -0
  99. package/src/core/compose/features/position.ts +94 -0
  100. package/src/core/compose/features/ripple.ts +55 -0
  101. package/src/core/compose/features/size.ts +29 -0
  102. package/src/core/compose/features/style.ts +31 -0
  103. package/src/core/compose/features/text.ts +44 -0
  104. package/src/core/compose/features/textinput.ts +225 -0
  105. package/src/core/compose/features/textlabel.ts +92 -0
  106. package/src/core/compose/features/track.ts +84 -0
  107. package/src/core/compose/features/variant.ts +29 -0
  108. package/src/core/compose/features/withEvents.ts +137 -0
  109. package/src/core/compose/index.ts +54 -0
  110. package/src/core/compose/{pipe.js → pipe.ts} +16 -11
  111. package/src/core/config/component-config.ts +136 -0
  112. package/src/core/config.ts +211 -0
  113. package/src/core/dom/{attributes.js → attributes.ts} +11 -11
  114. package/src/core/dom/classes.ts +60 -0
  115. package/src/core/dom/create.ts +188 -0
  116. package/src/core/dom/events.ts +209 -0
  117. package/src/core/dom/index.ts +10 -0
  118. package/src/core/dom/utils.ts +97 -0
  119. package/src/core/index.ts +111 -0
  120. package/src/core/state/disabled.ts +81 -0
  121. package/src/core/state/emitter.ts +94 -0
  122. package/src/core/state/events.ts +88 -0
  123. package/src/core/state/index.ts +16 -0
  124. package/src/core/state/lifecycle.ts +131 -0
  125. package/src/core/state/store.ts +197 -0
  126. package/src/core/utils/index.ts +45 -0
  127. package/src/core/utils/{mobile.js → mobile.ts} +48 -24
  128. package/src/core/utils/object.ts +41 -0
  129. package/src/core/utils/validate.ts +234 -0
  130. package/src/{index.js → index.ts} +4 -2
  131. package/index.js +0 -11
  132. package/src/components/button/api.js +0 -54
  133. package/src/components/button/button.js +0 -81
  134. package/src/components/button/config.js +0 -10
  135. package/src/components/button/constants.js +0 -63
  136. package/src/components/button/index.js +0 -2
  137. package/src/components/checkbox/api.js +0 -45
  138. package/src/components/checkbox/checkbox.js +0 -96
  139. package/src/components/checkbox/index.js +0 -2
  140. package/src/components/container/api.js +0 -42
  141. package/src/components/container/container.js +0 -45
  142. package/src/components/container/index.js +0 -2
  143. package/src/components/container/styles.scss +0 -66
  144. package/src/components/list/index.js +0 -2
  145. package/src/components/list/list-item.js +0 -147
  146. package/src/components/list/list.js +0 -267
  147. package/src/components/menu/api.js +0 -117
  148. package/src/components/menu/constants.js +0 -42
  149. package/src/components/menu/features/items-manager.js +0 -375
  150. package/src/components/menu/features/keyboard-navigation.js +0 -129
  151. package/src/components/menu/features/positioning.js +0 -125
  152. package/src/components/menu/index.js +0 -2
  153. package/src/components/menu/menu-item.js +0 -41
  154. package/src/components/menu/menu.js +0 -54
  155. package/src/components/navigation/api.js +0 -43
  156. package/src/components/navigation/index.js +0 -2
  157. package/src/components/navigation/nav-item.js +0 -137
  158. package/src/components/navigation/navigation.js +0 -55
  159. package/src/components/snackbar/api.js +0 -125
  160. package/src/components/snackbar/features.js +0 -69
  161. package/src/components/snackbar/index.js +0 -2
  162. package/src/components/snackbar/position.js +0 -63
  163. package/src/components/snackbar/queue.js +0 -74
  164. package/src/components/snackbar/snackbar.js +0 -70
  165. package/src/components/switch/api.js +0 -44
  166. package/src/components/switch/index.js +0 -2
  167. package/src/components/switch/switch.js +0 -71
  168. package/src/components/textfield/api.js +0 -49
  169. package/src/components/textfield/index.js +0 -2
  170. package/src/components/textfield/textfield.js +0 -68
  171. package/src/core/build/_ripple.scss +0 -79
  172. package/src/core/build/constants.js +0 -51
  173. package/src/core/build/icon.js +0 -78
  174. package/src/core/build/ripple.js +0 -159
  175. package/src/core/build/text.js +0 -54
  176. package/src/core/compose/base.js +0 -8
  177. package/src/core/compose/component.js +0 -225
  178. package/src/core/compose/features/checkable.js +0 -114
  179. package/src/core/compose/features/disabled.js +0 -64
  180. package/src/core/compose/features/events.js +0 -48
  181. package/src/core/compose/features/icon.js +0 -33
  182. package/src/core/compose/features/index.js +0 -20
  183. package/src/core/compose/features/input.js +0 -100
  184. package/src/core/compose/features/lifecycle.js +0 -69
  185. package/src/core/compose/features/position.js +0 -60
  186. package/src/core/compose/features/ripple.js +0 -32
  187. package/src/core/compose/features/size.js +0 -9
  188. package/src/core/compose/features/style.js +0 -12
  189. package/src/core/compose/features/text.js +0 -17
  190. package/src/core/compose/features/textinput.js +0 -114
  191. package/src/core/compose/features/textlabel.js +0 -28
  192. package/src/core/compose/features/track.js +0 -49
  193. package/src/core/compose/features/variant.js +0 -9
  194. package/src/core/compose/features/withEvents.js +0 -67
  195. package/src/core/compose/index.js +0 -16
  196. package/src/core/config.js +0 -140
  197. package/src/core/dom/classes.js +0 -70
  198. package/src/core/dom/create.js +0 -132
  199. package/src/core/dom/events.js +0 -175
  200. package/src/core/dom/index.js +0 -5
  201. package/src/core/dom/utils.js +0 -22
  202. package/src/core/index.js +0 -23
  203. package/src/core/state/disabled.js +0 -51
  204. package/src/core/state/emitter.js +0 -63
  205. package/src/core/state/events.js +0 -29
  206. package/src/core/state/index.js +0 -6
  207. package/src/core/state/lifecycle.js +0 -64
  208. package/src/core/state/store.js +0 -112
  209. package/src/core/utils/index.js +0 -39
  210. package/src/core/utils/object.js +0 -22
  211. package/src/core/utils/validate.js +0 -37
  212. /package/src/components/checkbox/{styles.scss → _styles.scss} +0 -0
  213. /package/src/components/checkbox/{constants.js → constants.ts} +0 -0
  214. /package/src/components/list/{styles.scss → _styles.scss} +0 -0
  215. /package/src/components/menu/{styles.scss → _styles.scss} +0 -0
  216. /package/src/components/navigation/{styles.scss → _styles.scss} +0 -0
  217. /package/src/components/snackbar/{styles.scss → _styles.scss} +0 -0
  218. /package/src/components/switch/{styles.scss → _styles.scss} +0 -0
  219. /package/src/components/switch/{constants.js → constants.ts} +0 -0
  220. /package/src/components/textfield/{styles.scss → _styles.scss} +0 -0
@@ -0,0 +1,75 @@
1
+ // src/components/checkbox/checkbox.ts
2
+ import { pipe } from '../../core/compose';
3
+ import { createBase, withElement } from '../../core/compose/component';
4
+ import {
5
+ withEvents,
6
+ withTextLabel,
7
+ withDisabled,
8
+ withLifecycle,
9
+ withInput,
10
+ withCheckable
11
+ } from '../../core/compose/features';
12
+ import { withAPI } from './api';
13
+ import { CheckboxConfig, CheckboxComponent, BaseComponent } from './types';
14
+ import {
15
+ createBaseConfig,
16
+ getElementConfig,
17
+ withCheckIcon,
18
+ withLabelPosition,
19
+ getApiConfig
20
+ } from './config';
21
+
22
+ /**
23
+ * Enhances a component with checkable features and indeterminate state
24
+ * @param {BaseComponent} component - The component to enhance
25
+ * @param {CheckboxConfig} config - Configuration options
26
+ * @returns {BaseComponent} The enhanced component
27
+ */
28
+ const enhanceWithCheckable = (component: BaseComponent, config: CheckboxConfig): BaseComponent => {
29
+ const enhanced = withCheckable(config)(component);
30
+
31
+ // Add indeterminate state handling
32
+ if (config.indeterminate) {
33
+ enhanced.input.indeterminate = true;
34
+ }
35
+
36
+ enhanced.setIndeterminate = (state: boolean) => {
37
+ enhanced.input.indeterminate = state;
38
+ enhanced.element.classList.toggle(`${config.prefix}-checkbox--indeterminate`, state);
39
+ return enhanced;
40
+ };
41
+
42
+ return enhanced;
43
+ };
44
+
45
+ /**
46
+ * Creates a new Checkbox component
47
+ * @param {CheckboxConfig} config - Checkbox configuration
48
+ * @returns {CheckboxComponent} Checkbox component instance
49
+ */
50
+ const createCheckbox = (config: CheckboxConfig = {}): CheckboxComponent => {
51
+ const baseConfig = createBaseConfig(config);
52
+
53
+ try {
54
+ const checkbox = pipe(
55
+ createBase,
56
+ withEvents(),
57
+ withElement(getElementConfig(baseConfig)),
58
+ withInput(baseConfig),
59
+ withCheckIcon(baseConfig),
60
+ withTextLabel(baseConfig),
61
+ withLabelPosition(baseConfig),
62
+ component => enhanceWithCheckable(component, baseConfig),
63
+ withDisabled(baseConfig),
64
+ withLifecycle(),
65
+ comp => withAPI(getApiConfig(comp))(comp)
66
+ )(baseConfig);
67
+
68
+ return checkbox as CheckboxComponent;
69
+ } catch (error) {
70
+ console.error('Checkbox creation error:', error instanceof Error ? error.message : String(error));
71
+ throw new Error(`Failed to create checkbox: ${error instanceof Error ? error.message : String(error)}`);
72
+ }
73
+ };
74
+
75
+ export default createCheckbox;
@@ -0,0 +1,90 @@
1
+ // src/components/checkbox/config.ts
2
+ import {
3
+ createComponentConfig,
4
+ createElementConfig,
5
+ BaseComponentConfig
6
+ } from '../../core/config/component-config';
7
+ import { CheckboxConfig, BaseComponent, ApiOptions } from './types';
8
+ import { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
9
+
10
+ /**
11
+ * Default configuration for the Checkbox component
12
+ */
13
+ export const defaultConfig: CheckboxConfig = {
14
+ variant: CHECKBOX_VARIANTS.FILLED,
15
+ labelPosition: CHECKBOX_LABEL_POSITION.END
16
+ };
17
+
18
+ /**
19
+ * Creates the base configuration for Checkbox component
20
+ * @param {CheckboxConfig} config - User provided configuration
21
+ * @returns {CheckboxConfig} Complete configuration with defaults applied
22
+ */
23
+ export const createBaseConfig = (config: CheckboxConfig = {}): CheckboxConfig =>
24
+ createComponentConfig(defaultConfig, config, 'checkbox') as CheckboxConfig;
25
+
26
+ /**
27
+ * Generates element configuration for the Checkbox component
28
+ * @param {CheckboxConfig} config - Checkbox configuration
29
+ * @returns {Object} Element configuration object for withElement
30
+ */
31
+ export const getElementConfig = (config: CheckboxConfig) =>
32
+ createElementConfig(config, {
33
+ tag: 'div',
34
+ componentName: 'checkbox',
35
+ className: config.class,
36
+ interactive: true
37
+ });
38
+
39
+ /**
40
+ * Adds check icon to checkbox
41
+ * @param {CheckboxConfig} config - Component configuration
42
+ */
43
+ export const withCheckIcon = (config: CheckboxConfig) => (component: BaseComponent): BaseComponent => {
44
+ const icon = document.createElement('span');
45
+ icon.className = `${config.prefix}-checkbox-icon`;
46
+ icon.innerHTML = `
47
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
48
+ <path d="M9.55 14.6L6.35 11.4l-1.9 1.9L9.55 18.4l10.9-10.9-1.9-1.9z"/>
49
+ </svg>
50
+ `;
51
+
52
+ component.element.appendChild(icon);
53
+ return component;
54
+ };
55
+
56
+ /**
57
+ * Applies label position class to the component
58
+ * @param {CheckboxConfig} config - Component configuration
59
+ */
60
+ export const withLabelPosition = (config: CheckboxConfig) => (component: BaseComponent): BaseComponent => {
61
+ const position = config.labelPosition || CHECKBOX_LABEL_POSITION.END;
62
+ const positionClass = `${config.prefix}-checkbox--label-${position}`;
63
+
64
+ component.element.classList.add(positionClass);
65
+
66
+ return component;
67
+ };
68
+
69
+ /**
70
+ * Creates API configuration for the Checkbox component
71
+ * @param {BaseComponent} comp - Component with disabled, lifecycle, and checkable features
72
+ * @returns {ApiOptions} API configuration object
73
+ */
74
+ export const getApiConfig = (comp: BaseComponent): ApiOptions => ({
75
+ disabled: {
76
+ enable: comp.disabled?.enable,
77
+ disable: comp.disabled?.disable
78
+ },
79
+ lifecycle: {
80
+ destroy: comp.lifecycle?.destroy
81
+ },
82
+ checkable: {
83
+ check: comp.checkable?.check,
84
+ uncheck: comp.checkable?.uncheck,
85
+ toggle: comp.checkable?.toggle,
86
+ isChecked: comp.checkable?.isChecked
87
+ }
88
+ });
89
+
90
+ export default defaultConfig;
@@ -0,0 +1,4 @@
1
+ // src/components/checkbox/index.ts
2
+ export { default } from './checkbox';
3
+ export { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
4
+ export { CheckboxConfig, CheckboxComponent } from './types';
@@ -0,0 +1,146 @@
1
+ // src/components/checkbox/types.ts
2
+ import { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
3
+
4
+ /**
5
+ * Configuration interface for the Checkbox component
6
+ */
7
+ export interface CheckboxConfig {
8
+ /** Input name attribute */
9
+ name?: string;
10
+
11
+ /** Initial checked state */
12
+ checked?: boolean;
13
+
14
+ /** Initial indeterminate state */
15
+ indeterminate?: boolean;
16
+
17
+ /** Whether input is required */
18
+ required?: boolean;
19
+
20
+ /** Whether checkbox is disabled */
21
+ disabled?: boolean;
22
+
23
+ /** Input value attribute */
24
+ value?: string;
25
+
26
+ /** Label text */
27
+ label?: string;
28
+
29
+ /** Label position (start/end) */
30
+ labelPosition?: keyof typeof CHECKBOX_LABEL_POSITION | string;
31
+
32
+ /** Visual variant */
33
+ variant?: keyof typeof CHECKBOX_VARIANTS | string;
34
+
35
+ /** Additional CSS classes */
36
+ class?: string;
37
+
38
+ /** Prefix for class names */
39
+ prefix?: string;
40
+
41
+ /** Component name */
42
+ componentName?: string;
43
+ }
44
+
45
+ /**
46
+ * Checkbox component interface
47
+ */
48
+ export interface CheckboxComponent {
49
+ /** The root element of the checkbox */
50
+ element: HTMLElement;
51
+
52
+ /** The input element */
53
+ input: HTMLInputElement;
54
+
55
+ /** Gets the checkbox's value */
56
+ getValue: () => string;
57
+
58
+ /** Sets the checkbox's value */
59
+ setValue: (value: string) => CheckboxComponent;
60
+
61
+ /** Checks the checkbox */
62
+ check: () => CheckboxComponent;
63
+
64
+ /** Unchecks the checkbox */
65
+ uncheck: () => CheckboxComponent;
66
+
67
+ /** Toggles the checkbox's checked state */
68
+ toggle: () => CheckboxComponent;
69
+
70
+ /** Returns whether the checkbox is checked */
71
+ isChecked: () => boolean;
72
+
73
+ /** Sets the checkbox's indeterminate state */
74
+ setIndeterminate: (state: boolean) => CheckboxComponent;
75
+
76
+ /** Sets the checkbox's label text */
77
+ setLabel: (text: string) => CheckboxComponent;
78
+
79
+ /** Gets the checkbox's label text */
80
+ getLabel: () => string;
81
+
82
+ /** Adds event listener */
83
+ on: (event: string, handler: Function) => CheckboxComponent;
84
+
85
+ /** Removes event listener */
86
+ off: (event: string, handler: Function) => CheckboxComponent;
87
+
88
+ /** Enables the checkbox */
89
+ enable: () => CheckboxComponent;
90
+
91
+ /** Disables the checkbox */
92
+ disable: () => CheckboxComponent;
93
+
94
+ /** Destroys the checkbox component and cleans up resources */
95
+ destroy: () => void;
96
+ }
97
+
98
+ /**
99
+ * API options interface
100
+ */
101
+ export interface ApiOptions {
102
+ disabled: {
103
+ enable: () => any;
104
+ disable: () => any;
105
+ };
106
+ lifecycle: {
107
+ destroy: () => void;
108
+ };
109
+ checkable: {
110
+ check: () => any;
111
+ uncheck: () => any;
112
+ toggle: () => any;
113
+ isChecked: () => boolean;
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Base component interface
119
+ */
120
+ export interface BaseComponent {
121
+ element: HTMLElement;
122
+ input?: HTMLInputElement;
123
+ getValue?: () => string;
124
+ setValue?: (value: string) => any;
125
+ setIndeterminate?: (state: boolean) => any;
126
+ text?: {
127
+ setText: (content: string) => any;
128
+ getText: () => string;
129
+ };
130
+ on?: (event: string, handler: Function) => any;
131
+ off?: (event: string, handler: Function) => any;
132
+ disabled?: {
133
+ enable: () => any;
134
+ disable: () => any;
135
+ };
136
+ lifecycle?: {
137
+ destroy: () => void;
138
+ };
139
+ checkable?: {
140
+ check: () => any;
141
+ uncheck: () => any;
142
+ toggle: () => any;
143
+ isChecked: () => boolean;
144
+ };
145
+ [key: string]: any;
146
+ }
@@ -0,0 +1,372 @@
1
+ // src/components/chip/_styles.scss
2
+ @use '../../styles/abstract/base' as base;
3
+ @use '../../styles/abstract/variables' as v;
4
+ @use '../../styles/abstract/functions' as f;
5
+ @use '../../styles/abstract/mixins' as m;
6
+ @use '../../styles/abstract/theme' as t;
7
+
8
+ $component: '#{base.$prefix}-chip';
9
+
10
+ .#{$component} {
11
+ // Base styles
12
+ position: relative;
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ height: 32px;
17
+ padding: 0 12px;
18
+ border: none;
19
+ border-radius: 8px;
20
+ background-color: transparent;
21
+ color: inherit;
22
+ font: inherit;
23
+ text-decoration: none;
24
+ cursor: pointer;
25
+ user-select: none;
26
+ vertical-align: middle;
27
+ appearance: none;
28
+ overflow: hidden;
29
+ transition: background-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease,
30
+ border-color 0.15s ease, opacity 0.15s ease;
31
+
32
+ // Typography
33
+ @include m.typography('label-large');
34
+
35
+ // Focus styles
36
+ &:focus {
37
+ outline: none;
38
+ }
39
+
40
+ &:focus-visible {
41
+ outline: 2px solid t.color('outline');
42
+ outline-offset: 2px;
43
+ }
44
+
45
+ // Disabled state
46
+ &[aria-disabled="true"] {
47
+ pointer-events: none;
48
+ opacity: 0.38;
49
+ }
50
+
51
+ // Leading icon styles
52
+ &-icon {
53
+ display: inline-flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 18px;
57
+ height: 18px;
58
+ margin-right: 8px;
59
+
60
+ svg {
61
+ width: 18px;
62
+ height: 18px;
63
+ }
64
+ }
65
+
66
+ // Trailing icon styles
67
+ &-trailing-icon {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ width: 18px;
72
+ height: 18px;
73
+ margin-left: 8px;
74
+
75
+ svg {
76
+ width: 18px;
77
+ height: 18px;
78
+ }
79
+
80
+ &:hover {
81
+ opacity: 0.8;
82
+ }
83
+ }
84
+
85
+ // Text content
86
+ &-text {
87
+ // Text truncation for long chip labels
88
+ @include m.truncate;
89
+ max-width: 150px;
90
+ }
91
+
92
+ // Ripple container
93
+ .ripple {
94
+ position: absolute;
95
+ border-radius: 50%;
96
+ transform: scale(0);
97
+ pointer-events: none;
98
+ background-color: currentColor;
99
+ opacity: 0.12;
100
+ }
101
+
102
+ // === VARIANTS ===
103
+
104
+ // Filled chip (default)
105
+ &--filled {
106
+ background-color: t.color('surface-container-highest');
107
+ color: t.color('on-surface');
108
+
109
+ &:hover {
110
+ @include m.state-layer(t.color('on-surface'), 'hover');
111
+ }
112
+
113
+ &:active {
114
+ @include m.state-layer(t.color('on-surface'), 'pressed');
115
+ }
116
+
117
+ &.#{$component}--selected {
118
+ background-color: t.color('secondary-container');
119
+ color: t.color('on-secondary-container');
120
+
121
+ &:hover {
122
+ @include m.state-layer(t.color('on-secondary-container'), 'hover');
123
+ }
124
+
125
+ &:active {
126
+ @include m.state-layer(t.color('on-secondary-container'), 'pressed');
127
+ }
128
+ }
129
+ }
130
+
131
+ // Outlined chip
132
+ &--outlined {
133
+ border: 1px solid t.color('outline');
134
+ color: t.color('on-surface');
135
+
136
+ &:hover {
137
+ @include m.state-layer(t.color('on-surface'), 'hover');
138
+ }
139
+
140
+ &:active {
141
+ @include m.state-layer(t.color('on-surface'), 'pressed');
142
+ }
143
+
144
+ &.#{$component}--selected {
145
+ border-color: t.color('secondary');
146
+ background-color: t.color('secondary-container');
147
+ color: t.color('on-secondary-container');
148
+
149
+ &:hover {
150
+ @include m.state-layer(t.color('on-secondary-container'), 'hover');
151
+ }
152
+
153
+ &:active {
154
+ @include m.state-layer(t.color('on-secondary-container'), 'pressed');
155
+ }
156
+ }
157
+ }
158
+
159
+ // Elevated chip
160
+ &--elevated {
161
+ background-color: t.color('surface-container-low');
162
+ color: t.color('on-surface');
163
+ @include m.elevation(1);
164
+
165
+ &:hover {
166
+ @include m.state-layer(t.color('on-surface'), 'hover');
167
+ @include m.elevation(2);
168
+ }
169
+
170
+ &:active {
171
+ @include m.state-layer(t.color('on-surface'), 'pressed');
172
+ @include m.elevation(1);
173
+ }
174
+
175
+ &.#{$component}--selected {
176
+ background-color: t.color('secondary-container');
177
+ color: t.color('on-secondary-container');
178
+
179
+ &:hover {
180
+ @include m.state-layer(t.color('on-secondary-container'), 'hover');
181
+ }
182
+
183
+ &:active {
184
+ @include m.state-layer(t.color('on-secondary-container'), 'pressed');
185
+ }
186
+ }
187
+
188
+ &[aria-disabled="true"] {
189
+ @include m.elevation(0);
190
+ box-shadow: none;
191
+ }
192
+ }
193
+
194
+ // Assist chip
195
+ &--assist {
196
+ background-color: t.color('surface-container');
197
+ color: t.color('on-surface');
198
+
199
+ &:hover {
200
+ @include m.state-layer(t.color('on-surface'), 'hover');
201
+ }
202
+
203
+ &:active {
204
+ @include m.state-layer(t.color('on-surface'), 'pressed');
205
+ }
206
+
207
+ .#{$component}-icon {
208
+ color: t.color('primary');
209
+ }
210
+ }
211
+
212
+ // Filter chip
213
+ &--filter {
214
+ background-color: t.color('surface-container-highest');
215
+ color: t.color('on-surface');
216
+
217
+ &:hover {
218
+ @include m.state-layer(t.color('on-surface'), 'hover');
219
+ }
220
+
221
+ &:active {
222
+ @include m.state-layer(t.color('on-surface'), 'pressed');
223
+ }
224
+
225
+ &.#{$component}--selected {
226
+ background-color: t.color('secondary-container');
227
+ color: t.color('on-secondary-container');
228
+
229
+ &:hover {
230
+ @include m.state-layer(t.color('on-secondary-container'), 'hover');
231
+ }
232
+
233
+ &:active {
234
+ @include m.state-layer(t.color('on-secondary-container'), 'pressed');
235
+ }
236
+
237
+ // Checkmark icon for selected filter chips
238
+ .#{$component}-icon {
239
+ color: t.color('on-secondary-container');
240
+ }
241
+ }
242
+ }
243
+
244
+ // Input chip
245
+ &--input {
246
+ background-color: t.color('surface-container-highest');
247
+ color: t.color('on-surface');
248
+ padding-right: 8px; // Less padding on the right to accommodate the trailing icon
249
+
250
+ &:hover {
251
+ @include m.state-layer(t.color('on-surface'), 'hover');
252
+ }
253
+
254
+ .#{$component}-trailing-icon {
255
+ color: t.color('on-surface-variant');
256
+
257
+ &:hover {
258
+ color: t.color('on-surface');
259
+ }
260
+ }
261
+ }
262
+
263
+ // Suggestion chip
264
+ &--suggestion {
265
+ background-color: t.color('surface-container');
266
+ color: t.color('on-surface');
267
+
268
+ &:hover {
269
+ @include m.state-layer(t.color('on-surface'), 'hover');
270
+ }
271
+
272
+ &:active {
273
+ @include m.state-layer(t.color('on-surface'), 'pressed');
274
+ }
275
+ }
276
+
277
+ // === SIZES ===
278
+
279
+ &--small {
280
+ height: 24px;
281
+ padding: 0 8px;
282
+ font-size: 12px;
283
+
284
+ .#{$component}-icon,
285
+ .#{$component}-trailing-icon {
286
+ width: 16px;
287
+ height: 16px;
288
+
289
+ svg {
290
+ width: 16px;
291
+ height: 16px;
292
+ }
293
+ }
294
+
295
+ .#{$component}-icon {
296
+ margin-right: 4px;
297
+ }
298
+
299
+ .#{$component}-trailing-icon {
300
+ margin-left: 4px;
301
+ }
302
+ }
303
+
304
+ &--large {
305
+ height: 40px;
306
+ padding: 0 16px;
307
+ font-size: 15px;
308
+ border-radius: 12px;
309
+
310
+ .#{$component}-icon,
311
+ .#{$component}-trailing-icon {
312
+ width: 20px;
313
+ height: 20px;
314
+
315
+ svg {
316
+ width: 20px;
317
+ height: 20px;
318
+ }
319
+ }
320
+
321
+ .#{$component}-icon {
322
+ margin-right: 10px;
323
+ }
324
+
325
+ .#{$component}-trailing-icon {
326
+ margin-left: 10px;
327
+ }
328
+ }
329
+
330
+ // === SPECIAL CASES ===
331
+
332
+ // For chips with only icons (no text)
333
+ &--icon-only {
334
+ padding: 0;
335
+ width: 32px;
336
+
337
+ &.#{$component}--small {
338
+ width: 24px;
339
+ }
340
+
341
+ &.#{$component}--large {
342
+ width: 40px;
343
+ }
344
+
345
+ .#{$component}-icon {
346
+ margin-right: 0;
347
+ }
348
+ }
349
+ }
350
+
351
+ // === CHIP SET STYLES ===
352
+
353
+ .#{$component}-set {
354
+ display: flex;
355
+ flex-wrap: wrap;
356
+ gap: 8px;
357
+
358
+ &--scrollable {
359
+ flex-wrap: nowrap;
360
+ overflow-x: auto;
361
+ scrollbar-width: none; // Firefox
362
+
363
+ &::-webkit-scrollbar {
364
+ display: none; // Chrome, Safari, Edge
365
+ }
366
+ }
367
+
368
+ &--vertical {
369
+ flex-direction: column;
370
+ align-items: flex-start;
371
+ }
372
+ }