material-inspired-component-library 1.0.3 → 1.1.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.
- package/README.md +6 -0
- package/components/slider/index.scss +11 -8
- package/components/textfield/README.md +48 -15
- package/components/textfield/index.scss +98 -55
- package/components/textfield/index.ts +23 -16
- package/components.ts +2 -1
- package/dist/micl.css +1 -1
- package/dist/micl.js +1 -1
- package/dist/slider.css +1 -1
- package/dist/textfield.css +1 -1
- package/docs/micl.css +1 -1
- package/docs/micl.js +1 -1
- package/docs/slider.html +1 -0
- package/docs/textfield.html +30 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -97,3 +97,9 @@ The library currently consists of the following components:
|
|
|
97
97
|
- [x] [Slider](components/slider/README.md)
|
|
98
98
|
- [x] [Switch](components/switch/README.md)
|
|
99
99
|
- [x] [Text field](components/textfield/README.md)
|
|
100
|
+
|
|
101
|
+
## Change Log
|
|
102
|
+
|
|
103
|
+
#### 1.1.0 (12.08.2025)
|
|
104
|
+
**Features**
|
|
105
|
+
- **Text field**: Added support for multi-line text fields.
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
@mixin slider-track() {
|
|
26
26
|
block-size: var(--md-sys-slider-track-height);
|
|
27
27
|
border-radius: var(--md-sys-slider-track-radius);
|
|
28
|
+
background-color: inherit;
|
|
28
29
|
background-image: linear-gradient(
|
|
29
30
|
var(--md-sys-slider-track-direction),
|
|
30
31
|
var(--md-sys-color-primary) calc(100% * (var(--md-sys-slider-value) - var(--md-sys-slider-min)) / (var(--md-sys-slider-max) - var(--md-sys-slider-min))),
|
|
@@ -48,13 +49,12 @@
|
|
|
48
49
|
appearance: none;
|
|
49
50
|
box-sizing: content-box;
|
|
50
51
|
position: relative;
|
|
51
|
-
inline-size:
|
|
52
|
+
inline-size: 16px;
|
|
52
53
|
block-size: var(--md-sys-slider-handle-height);
|
|
53
54
|
inset: 0;
|
|
54
|
-
inset-block-start: calc(-1 * (var(--md-sys-slider-handle-height)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
background-color: var(--md-sys-color-primary);
|
|
55
|
+
inset-block-start: calc(-1 * (var(--md-sys-slider-handle-height) - var(--md-sys-slider-track-height)) / 2);
|
|
56
|
+
background-color: inherit;
|
|
57
|
+
background-image: linear-gradient(to right,transparent 0px,transparent var(--md-sys-slider-thumb-space), var(--md-sys-color-primary) var(--md-sys-slider-thumb-space),var(--md-sys-color-primary) 10px,transparent 10px, transparent 16px);
|
|
58
58
|
cursor: pointer;
|
|
59
59
|
z-index: 2;
|
|
60
60
|
}
|
|
@@ -105,7 +105,7 @@ input[type=range].micl-slider-xl {
|
|
|
105
105
|
margin: 0;
|
|
106
106
|
outline: none;
|
|
107
107
|
color: var(--md-sys-color-surface-container-low);
|
|
108
|
-
background-color:
|
|
108
|
+
background-color: inherit;
|
|
109
109
|
accent-color: var(--md-sys-color-primary);
|
|
110
110
|
|
|
111
111
|
&::before {
|
|
@@ -145,6 +145,9 @@ input[type=range].micl-slider-xl {
|
|
|
145
145
|
z-index: 3;
|
|
146
146
|
transition: opacity var(--md-sys-motion-duration-long2) motion.$md-sys-motion-easing-emphasized-decelerate;
|
|
147
147
|
}
|
|
148
|
+
&::-webkit-slider-container {
|
|
149
|
+
background-color: inherit;
|
|
150
|
+
}
|
|
148
151
|
&::-webkit-slider-runnable-track {
|
|
149
152
|
@include slider-track;
|
|
150
153
|
}
|
|
@@ -195,12 +198,12 @@ input[type=range].micl-slider-xl {
|
|
|
195
198
|
}
|
|
196
199
|
&:not(:disabled):active {
|
|
197
200
|
&::-webkit-slider-thumb {
|
|
198
|
-
|
|
201
|
+
background-image: linear-gradient(to right,transparent 0px, transparent calc(var(--md-sys-slider-thumb-space) + 1px), var(--md-sys-color-primary) calc(var(--md-sys-slider-thumb-space) + 1px), var(--md-sys-color-primary) calc(var(--md-sys-slider-thumb-space) + 3px), transparent calc(var(--md-sys-slider-thumb-space) + 3px), transparent calc(2 * var(--md-sys-slider-thumb-space) + 4px));
|
|
199
202
|
outline: none;
|
|
200
203
|
cursor: grabbing;
|
|
201
204
|
}
|
|
202
205
|
&::-moz-range-thumb {
|
|
203
|
-
|
|
206
|
+
background-image: linear-gradient(to right,transparent 0px, transparent calc(var(--md-sys-slider-thumb-space) + 1px), var(--md-sys-color-primary) calc(var(--md-sys-slider-thumb-space) + 1px), var(--md-sys-color-primary) calc(var(--md-sys-slider-thumb-space) + 3px), transparent calc(var(--md-sys-slider-thumb-space) + 3px), transparent calc(2 * var(--md-sys-slider-thumb-space) + 4px));
|
|
204
207
|
outline: none;
|
|
205
208
|
cursor: grabbing;
|
|
206
209
|
}
|
|
@@ -41,35 +41,68 @@ The following example shows a text field with every available feature. You can i
|
|
|
41
41
|
|
|
42
42
|
```HTML
|
|
43
43
|
<div class="micl-textfield-filled">
|
|
44
|
-
<span class="micl-textfield__icon-leading material-symbols-outlined"
|
|
44
|
+
<span class="micl-textfield__icon-leading material-symbols-outlined">search</span>
|
|
45
45
|
<label for="mytextfield">Label text</label>
|
|
46
|
-
<span class="micl-textfield__prefix">$</span>
|
|
47
|
-
<input type="text" id="mytextfield" maxlength="20">
|
|
48
|
-
<span class="micl-textfield__suffix">kg</span>
|
|
49
|
-
<span class="micl-textfield__icon-trailing material-symbols-outlined"
|
|
50
|
-
<span class="micl-textfield__supporting-text">Supporting text</span>
|
|
46
|
+
<span class="micl-textfield__prefix" aria-label="US dollars">$</span>
|
|
47
|
+
<input type="text" id="mytextfield" maxlength="20" aria-describedby="mysupport">
|
|
48
|
+
<span class="micl-textfield__suffix" aria-label="kilograms">kg</span>
|
|
49
|
+
<span class="micl-textfield__icon-trailing material-symbols-outlined">cancel</span>
|
|
50
|
+
<span id="mysupport" class="micl-textfield__supporting-text">Supporting text</span>
|
|
51
51
|
<span class="micl-textfield__character-counter"></span>
|
|
52
52
|
</div>
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
The `<input>` element can have the following types: `text`, `date`, `datetime-local`, `email`, `month`, `number`, `password`, `tel`, `time`, `url` and `week`.
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Adding the `disabled` boolean attribute to the `<input>` element causes the text field to be displayed in a disabled state.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Adding the `micl-textfield--error` class to the text field displays it in an error state.
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
### Leading Content
|
|
62
|
+
The data-input element can be preceded by various elements:
|
|
63
|
+
|
|
64
|
+
- **Icon**: Use `micl-textfield__icon-leading` with a (Material Symbols) icon.
|
|
65
|
+
|
|
66
|
+
- **Prefix**: A prefix (e.g., "$", "NOK") can be included to provide additional context. You can customize the spacing by overriding CSS variables:
|
|
67
|
+
```HTML
|
|
68
|
+
<span class="micl-textfield__prefix" style="--md-sys-textfield-prefix-space:20px">USD</span>
|
|
69
|
+
```
|
|
65
70
|
|
|
66
|
-
|
|
71
|
+
### Trailing Content
|
|
72
|
+
The data-input element may be followed by a trailing text or other element:
|
|
73
|
+
|
|
74
|
+
- **Icon**: Use `micl-textfield__icon-trailing` with a (Material Symbols) icon.
|
|
75
|
+
|
|
76
|
+
- **Suffix**: A suffix (e.g., "kg", "@gmail.com") can be included to provide additional context. You can customize the spacing by overriding CSS variables:
|
|
77
|
+
```HTML
|
|
78
|
+
<span class="micl-textfield__suffix" style="--md-sys-textfield-suffix-space:10em">@gmail.com</span>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Supporting Content
|
|
82
|
+
Use an element with the `micl-textfield__supporting-text` class to add extra information about the text field. If you want this element only to be visible when the text field is focused, add the `micl-textfield__supporting-text--focus` as well.
|
|
67
83
|
|
|
68
84
|
If the `<input>` element includes the `maxlength` attribute, the **character counter** will display automatically in the element with the `micl-textfield__character-counter` class.
|
|
69
85
|
|
|
70
|
-
|
|
86
|
+
### Multi-line Text Field
|
|
87
|
+
Replace the `<input>` element with the `<textarea>` element to create a multi-line text field:
|
|
71
88
|
|
|
72
|
-
|
|
89
|
+
```HTML
|
|
90
|
+
<div class="micl-textfield-outlined">
|
|
91
|
+
<label for="mytextfield">Label text</label>
|
|
92
|
+
<textarea id="mytextfield"></textarea>
|
|
93
|
+
</div>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Add a value to the `rows` attribute of the `<textarea>` element to create a text field of fixed height:
|
|
97
|
+
|
|
98
|
+
```HTML
|
|
99
|
+
<div class="micl-textfield-outlined">
|
|
100
|
+
<label for="mytextfield">Label text</label>
|
|
101
|
+
<textarea id="mytextfield" rows="4"></textarea>
|
|
102
|
+
</div>
|
|
103
|
+
```
|
|
73
104
|
|
|
74
105
|
## Compatibility
|
|
75
106
|
This component uses relative RGB colors, which might not be supported in your browser. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#browser_compatibility) for details.
|
|
107
|
+
|
|
108
|
+
The multi-line text field variant uses the `field-sizing` CSS property, which might not be supported in your browser. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/field-sizing#browser_compatibility) for details.
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
.micl-textfield-filled,
|
|
26
26
|
.micl-textfield-outlined {
|
|
27
|
+
--md-sys-textfield-height: 56px;
|
|
27
28
|
--md-sys-textfield-icon-size: 24px;
|
|
28
29
|
--md-sys-textfield-icon-space: 12px;
|
|
29
30
|
--md-sys-textfield-input-space: 16px;
|
|
@@ -40,30 +41,29 @@
|
|
|
40
41
|
|
|
41
42
|
box-sizing: content-box;
|
|
42
43
|
grid-area: textfield;
|
|
44
|
+
align-self: flex-start;
|
|
43
45
|
width: fit-content;
|
|
44
|
-
line-height: 1;
|
|
45
46
|
padding-inline: 4px;
|
|
46
|
-
margin-block-start:
|
|
47
|
+
margin-block-start: calc((var(--md-sys-textfield-height) - var(--md-sys-typescale-body-large-line-height)) / 2);
|
|
47
48
|
margin-inline-start: 12px;
|
|
48
49
|
border-radius: 4px;
|
|
49
50
|
background-color: inherit;
|
|
50
51
|
color: var(--md-sys-color-on-surface-variant);
|
|
51
52
|
z-index: 1;
|
|
52
53
|
transition:
|
|
53
|
-
margin-block-start var(--md-sys-motion-duration-
|
|
54
|
-
margin-inline-start var(--md-sys-motion-duration-
|
|
55
|
-
font-size var(--md-sys-motion-duration-
|
|
56
|
-
letter-spacing var(--md-sys-motion-duration-
|
|
54
|
+
margin-block-start var(--md-sys-motion-duration-medium2) var(--md-sys-motion-duration-short3),
|
|
55
|
+
margin-inline-start var(--md-sys-motion-duration-medium2) var(--md-sys-motion-duration-short3),
|
|
56
|
+
font-size var(--md-sys-motion-duration-medium2),
|
|
57
|
+
letter-spacing var(--md-sys-motion-duration-medium2);
|
|
57
58
|
}
|
|
58
59
|
&> input,
|
|
59
|
-
&> select
|
|
60
|
+
&> select,
|
|
61
|
+
&> textarea {
|
|
60
62
|
@include typography.body-large;
|
|
61
63
|
|
|
62
64
|
box-sizing: border-box;
|
|
63
65
|
grid-area: textfield;
|
|
64
|
-
height: 56px;
|
|
65
66
|
margin: 0;
|
|
66
|
-
padding-block: 0;
|
|
67
67
|
padding-inline: var(--md-sys-textfield-input-space);
|
|
68
68
|
border: none;
|
|
69
69
|
border-block-end: 1px solid var(--md-sys-color-on-surface-variant);
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
caret-color: var(--md-sys-color-primary);
|
|
76
76
|
|
|
77
77
|
&:disabled {
|
|
78
|
-
border-color: rgb(from var(--md-sys-color-on-surface) r g b / 38%);
|
|
78
|
+
border-block-end-color: rgb(from var(--md-sys-color-on-surface) r g b / 38%);
|
|
79
79
|
color: rgb(from var(--md-sys-color-on-surface) r g b / 38%);
|
|
80
80
|
}
|
|
81
81
|
&::placeholder {
|
|
@@ -90,13 +90,32 @@
|
|
|
90
90
|
-moz-appearance: textfield;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
&> input,
|
|
94
|
+
&> select {
|
|
95
|
+
height: var(--md-sys-textfield-height);
|
|
96
|
+
padding-block: 0;
|
|
97
|
+
}
|
|
98
|
+
&> textarea {
|
|
99
|
+
min-height: var(--md-sys-textfield-height);
|
|
100
|
+
padding-block: calc((var(--md-sys-textfield-height) - var(--md-sys-typescale-body-large-line-height)) / 2);
|
|
101
|
+
resize: none;
|
|
102
|
+
|
|
103
|
+
&[rows] {
|
|
104
|
+
padding-block-start: 0;
|
|
105
|
+
border-block-start: 8px solid transparent;
|
|
106
|
+
overflow: hidden;
|
|
107
|
+
}
|
|
108
|
+
&:not([rows]) {
|
|
109
|
+
field-sizing: content;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
93
112
|
&> .micl-textfield__prefix,
|
|
94
113
|
&> .micl-textfield__suffix {
|
|
95
114
|
@include typography.body-large;
|
|
96
115
|
|
|
97
116
|
grid-area: textfield;
|
|
98
117
|
align-content: center;
|
|
99
|
-
height:
|
|
118
|
+
height: var(--md-sys-textfield-height);
|
|
100
119
|
color: var(--md-sys-color-on-surface-variant);
|
|
101
120
|
opacity: 0;
|
|
102
121
|
z-index: 1;
|
|
@@ -124,12 +143,14 @@
|
|
|
124
143
|
margin-inline: auto var(--md-sys-textfield-icon-space);
|
|
125
144
|
}
|
|
126
145
|
&:has(> .micl-textfield__prefix) {
|
|
127
|
-
&> input
|
|
146
|
+
&> input,
|
|
147
|
+
&> textarea {
|
|
128
148
|
padding-inline-start: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-prefix-space));
|
|
129
149
|
}
|
|
130
150
|
}
|
|
131
151
|
&:has(> .micl-textfield__suffix) {
|
|
132
|
-
&> input
|
|
152
|
+
&> input,
|
|
153
|
+
&> textarea {
|
|
133
154
|
padding-inline-end: calc(var(--md-sys-textfield-suffix-space) + var(--md-sys-textfield-input-space));
|
|
134
155
|
}
|
|
135
156
|
}
|
|
@@ -138,19 +159,23 @@
|
|
|
138
159
|
margin-inline-start: calc(var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-input-space));
|
|
139
160
|
}
|
|
140
161
|
&> .micl-textfield__prefix,
|
|
141
|
-
&> input
|
|
162
|
+
&> input,
|
|
163
|
+
&> textarea {
|
|
142
164
|
padding-inline-start: calc(var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-input-space));
|
|
143
165
|
}
|
|
144
|
-
&:has(> .micl-textfield__prefix) > input
|
|
166
|
+
&:has(> .micl-textfield__prefix) > input,
|
|
167
|
+
&:has(> .micl-textfield__prefix) > textarea {
|
|
145
168
|
padding-inline-start: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-icon-space) + var(--md-sys-textfield-prefix-space));
|
|
146
169
|
}
|
|
147
170
|
}
|
|
148
171
|
&:has(> .micl-textfield__icon-trailing) {
|
|
149
172
|
&> .micl-textfield__suffix,
|
|
150
|
-
&> input
|
|
173
|
+
&> input,
|
|
174
|
+
&> textarea {
|
|
151
175
|
padding-inline-end: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-icon-space));
|
|
152
176
|
}
|
|
153
|
-
&:has(> .micl-textfield__suffix) > input
|
|
177
|
+
&:has(> .micl-textfield__suffix) > input,
|
|
178
|
+
&:has(> .micl-textfield__suffix) > textarea {
|
|
154
179
|
padding-inline-end: calc(var(--md-sys-textfield-input-space) + var(--md-sys-textfield-icon-size) + var(--md-sys-textfield-prefix-space) + var(--md-sys-textfield-icon-space));
|
|
155
180
|
}
|
|
156
181
|
}
|
|
@@ -162,28 +187,33 @@
|
|
|
162
187
|
padding-block: 4px 0;
|
|
163
188
|
padding-inline: 16px;
|
|
164
189
|
color: var(--md-sys-color-on-surface-variant);
|
|
190
|
+
|
|
191
|
+
&.micl-textfield__supporting-text--focus {
|
|
192
|
+
visibility: hidden;
|
|
193
|
+
}
|
|
165
194
|
}
|
|
166
195
|
&> .micl-textfield__character-counter {
|
|
167
196
|
justify-self: flex-end;
|
|
168
197
|
}
|
|
169
198
|
&:has(> input:active),
|
|
170
199
|
&:has(> select:active),
|
|
200
|
+
&:has(> textarea:active),
|
|
171
201
|
&:has(> input:focus),
|
|
172
202
|
&:has(> select:focus),
|
|
203
|
+
&:has(> textarea:focus),
|
|
173
204
|
&:has(> input:focus-visible),
|
|
174
|
-
&:has(> select:focus-visible)
|
|
205
|
+
&:has(> select:focus-visible),
|
|
206
|
+
&:has(> textarea:focus-visible) {
|
|
175
207
|
&> label {
|
|
176
208
|
color: var(--md-sys-color-primary);
|
|
177
209
|
}
|
|
178
|
-
&> .micl-
|
|
179
|
-
|
|
180
|
-
&> .micl-textfield__supporting-text,
|
|
181
|
-
&> .micl-textfield__character-counter {
|
|
182
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
210
|
+
&> .micl-textfield__supporting-text.micl-textfield__supporting-text--focus {
|
|
211
|
+
visibility: visible;
|
|
183
212
|
}
|
|
184
213
|
}
|
|
185
214
|
&:has(> input:disabled),
|
|
186
|
-
&:has(> select:disabled)
|
|
215
|
+
&:has(> select:disabled),
|
|
216
|
+
&:has(> textarea:disabled) {
|
|
187
217
|
&> label {
|
|
188
218
|
color: rgb(from var(--md-sys-color-on-surface) r g b / 38%);
|
|
189
219
|
}
|
|
@@ -196,12 +226,14 @@
|
|
|
196
226
|
display: none;
|
|
197
227
|
}
|
|
198
228
|
}
|
|
199
|
-
&:has(> input:not([maxlength]))
|
|
229
|
+
&:has(> input:not([maxlength])),
|
|
230
|
+
&:has(> textarea:not([maxlength])) {
|
|
200
231
|
&> .micl-textfield__character-counter {
|
|
201
232
|
display: none;
|
|
202
233
|
}
|
|
203
234
|
}
|
|
204
|
-
&:has(> input[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter)
|
|
235
|
+
&:has(> input[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter),
|
|
236
|
+
&:has(> textarea[maxlength]:not(:disabled)):has(> .micl-textfield__character-counter) {
|
|
205
237
|
&> .micl-textfield__supporting-text {
|
|
206
238
|
padding-inline-end: 64px;
|
|
207
239
|
}
|
|
@@ -214,14 +246,17 @@
|
|
|
214
246
|
}
|
|
215
247
|
&:hover {
|
|
216
248
|
&> input:not(:disabled),
|
|
217
|
-
&> select:not(:disabled)
|
|
218
|
-
|
|
249
|
+
&> select:not(:disabled),
|
|
250
|
+
&> textarea:not(:disabled) {
|
|
251
|
+
border-block-end-color: var(--md-sys-color-on-surface);
|
|
219
252
|
background-color: color-mix(in srgb, var(--md-sys-color-surface-container-highest), var(--md-sys-color-on-surface) var(--md-sys-state-hover-state-layer-opacity));
|
|
220
253
|
}
|
|
221
254
|
}
|
|
222
255
|
&> input,
|
|
223
|
-
&> select
|
|
224
|
-
|
|
256
|
+
&> select,
|
|
257
|
+
&> textarea {
|
|
258
|
+
padding-block-start: 18px;
|
|
259
|
+
padding-block-end: 2px;
|
|
225
260
|
background-color: var(--md-sys-color-surface-container-highest);
|
|
226
261
|
border-end-start-radius: 0;
|
|
227
262
|
border-end-end-radius: 0;
|
|
@@ -233,14 +268,17 @@
|
|
|
233
268
|
&:not(:disabled):focus,
|
|
234
269
|
&:not(:disabled):focus-visible,
|
|
235
270
|
&:not(:disabled):active {
|
|
236
|
-
padding-block-
|
|
237
|
-
border-width: 3px;
|
|
238
|
-
border-color: var(--md-sys-color-primary);
|
|
271
|
+
padding-block-end: 0px;
|
|
272
|
+
border-block-end-width: 3px;
|
|
273
|
+
border-block-end-color: var(--md-sys-color-primary);
|
|
239
274
|
}
|
|
240
275
|
}
|
|
241
276
|
&> select {
|
|
242
277
|
line-height: 28px;
|
|
243
278
|
}
|
|
279
|
+
&> textarea {
|
|
280
|
+
padding-block-start: 24px;
|
|
281
|
+
}
|
|
244
282
|
&:has(
|
|
245
283
|
> input:focus,
|
|
246
284
|
> input[value]:not([value='']):not([data-miclinitialized]),
|
|
@@ -252,12 +290,15 @@
|
|
|
252
290
|
> input[type=week],
|
|
253
291
|
> select:focus,
|
|
254
292
|
> select[value]:not([value='']):not([data-miclinitialized]),
|
|
255
|
-
> select[data-miclvalue]
|
|
293
|
+
> select[data-miclvalue],
|
|
294
|
+
> textarea:focus,
|
|
295
|
+
> textarea:not(:empty):not([data-miclinitialized]),
|
|
296
|
+
> textarea[data-miclvalue]
|
|
256
297
|
) {
|
|
257
298
|
&> label {
|
|
258
299
|
@include typography.body-small;
|
|
259
300
|
|
|
260
|
-
margin-block-start:
|
|
301
|
+
margin-block-start: 8px;
|
|
261
302
|
margin-inline-start: 12px;
|
|
262
303
|
}
|
|
263
304
|
&:has(> .micl-textfield__icon-leading) > label {
|
|
@@ -279,13 +320,15 @@
|
|
|
279
320
|
color: var(--md-sys-color-on-surface);
|
|
280
321
|
}
|
|
281
322
|
&> input:not(:disabled),
|
|
282
|
-
&> select:not(:disabled)
|
|
323
|
+
&> select:not(:disabled),
|
|
324
|
+
&> textarea:not(:disabled) {
|
|
283
325
|
outline-color: var(--md-sys-color-on-surface);
|
|
284
326
|
color: var(--md-sys-color-on-surface);
|
|
285
327
|
}
|
|
286
328
|
}
|
|
287
329
|
&> input,
|
|
288
|
-
&> select
|
|
330
|
+
&> select,
|
|
331
|
+
&> textarea {
|
|
289
332
|
border: none;
|
|
290
333
|
outline: 1px solid var(--md-sys-color-outline);
|
|
291
334
|
|
|
@@ -300,7 +343,7 @@
|
|
|
300
343
|
}
|
|
301
344
|
}
|
|
302
345
|
&> select {
|
|
303
|
-
line-height:
|
|
346
|
+
line-height: var(--md-sys-textfield-height);
|
|
304
347
|
}
|
|
305
348
|
&:has(
|
|
306
349
|
> input:focus,
|
|
@@ -313,12 +356,15 @@
|
|
|
313
356
|
> input[type=week],
|
|
314
357
|
> select:focus,
|
|
315
358
|
> select[value]:not([value='']):not([data-miclinitialized]),
|
|
316
|
-
> select[data-miclvalue]
|
|
359
|
+
> select[data-miclvalue],
|
|
360
|
+
> textarea:focus,
|
|
361
|
+
> textarea:not(:empty):not([data-miclinitialized]),
|
|
362
|
+
> textarea[data-miclvalue]
|
|
317
363
|
) {
|
|
318
364
|
&> label {
|
|
319
365
|
@include typography.body-small;
|
|
320
366
|
|
|
321
|
-
margin-block-start: -
|
|
367
|
+
margin-block-start: calc(-2px - var(--md-sys-typescale-body-small-line-height) / 2);
|
|
322
368
|
margin-inline-start: 12px;
|
|
323
369
|
}
|
|
324
370
|
&> .micl-textfield__prefix,
|
|
@@ -336,18 +382,17 @@
|
|
|
336
382
|
&> .micl-textfield__character-counter {
|
|
337
383
|
color: var(--md-sys-color-error);
|
|
338
384
|
}
|
|
339
|
-
&> input
|
|
340
|
-
|
|
385
|
+
&> input,
|
|
386
|
+
&> textarea {
|
|
387
|
+
border-block-end-color: var(--md-sys-color-error);
|
|
341
388
|
outline-color: var(--md-sys-color-error);
|
|
342
|
-
color: var(--md-sys-color-on-surface);
|
|
343
389
|
caret-color: var(--md-sys-color-error);
|
|
344
390
|
|
|
345
391
|
&:active,
|
|
346
392
|
&:focus,
|
|
347
393
|
&:focus-visible {
|
|
348
|
-
border-color: var(--md-sys-color-error);
|
|
394
|
+
border-block-end-color: var(--md-sys-color-error);
|
|
349
395
|
outline-color: var(--md-sys-color-error);
|
|
350
|
-
color: var(--md-sys-color-on-surface);
|
|
351
396
|
}
|
|
352
397
|
}
|
|
353
398
|
&:hover {
|
|
@@ -355,22 +400,20 @@
|
|
|
355
400
|
&> .micl-textfield__icon-trailing {
|
|
356
401
|
color: var(--md-sys-color-on-error-container);
|
|
357
402
|
}
|
|
358
|
-
&> input
|
|
359
|
-
|
|
403
|
+
&> input,
|
|
404
|
+
&> textarea {
|
|
405
|
+
border-block-end-color: var(--md-sys-color-on-error-container);
|
|
360
406
|
outline-color: var(--md-sys-color-on-error-container);
|
|
361
407
|
}
|
|
362
|
-
&> .micl-textfield__supporting-text,
|
|
363
|
-
&> .micl-textfield__character-counter {
|
|
364
|
-
color: var(--md-sys-color-error);
|
|
365
|
-
}
|
|
366
408
|
}
|
|
367
409
|
&:has(> input:active),
|
|
368
410
|
&:has(> input:focus),
|
|
369
|
-
&:has(> input:focus-visible)
|
|
411
|
+
&:has(> input:focus-visible),
|
|
412
|
+
&:has(> textarea:active),
|
|
413
|
+
&:has(> textarea:focus),
|
|
414
|
+
&:has(> textarea:focus-visible) {
|
|
370
415
|
&> label,
|
|
371
|
-
&> .micl-textfield__icon-trailing
|
|
372
|
-
&> .micl-textfield__supporting-text,
|
|
373
|
-
&> .micl-textfield__character-counter {
|
|
416
|
+
&> .micl-textfield__icon-trailing {
|
|
374
417
|
color: var(--md-sys-color-error);
|
|
375
418
|
}
|
|
376
419
|
}
|
|
@@ -21,13 +21,14 @@
|
|
|
21
21
|
|
|
22
22
|
export const textfieldSelector = '.micl-textfield-outlined > input,.micl-textfield-filled > input';
|
|
23
23
|
export const selectSelector = '.micl-textfield-outlined > select,.micl-textfield-filled > select';
|
|
24
|
+
export const textareaSelector = '.micl-textfield-outlined > textarea,.micl-textfield-filled > textarea';
|
|
24
25
|
|
|
25
26
|
export default (() =>
|
|
26
27
|
{
|
|
27
|
-
const counterSelector = '.micl-
|
|
28
|
+
const counterSelector = '.micl-textfield__character-counter';
|
|
28
29
|
|
|
29
30
|
return {
|
|
30
|
-
initialize: (element: HTMLInputElement | HTMLSelectElement): void =>
|
|
31
|
+
initialize: (element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void =>
|
|
31
32
|
{
|
|
32
33
|
if (element.dataset.miclinitialized) {
|
|
33
34
|
return;
|
|
@@ -39,21 +40,25 @@ export default (() =>
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
if (
|
|
42
|
-
(element instanceof
|
|
43
|
-
|
|
43
|
+
(element instanceof HTMLSelectElement)
|
|
44
|
+
|| !element.maxLength
|
|
44
45
|
) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const counter = element.parentElement?.querySelector(counterSelector);
|
|
50
|
+
if (counter) {
|
|
51
|
+
counter.textContent = `${element.value.length}/${element.maxLength}`;
|
|
49
52
|
}
|
|
50
53
|
},
|
|
51
54
|
|
|
52
55
|
input: (event: Event): void =>
|
|
53
56
|
{
|
|
54
57
|
if (
|
|
55
|
-
!(event.target as Element).matches(`${textfieldSelector},${selectSelector}`)
|
|
56
|
-
|| !((event.target instanceof HTMLInputElement)
|
|
58
|
+
!(event.target as Element).matches(`${textfieldSelector},${selectSelector},${textareaSelector}`)
|
|
59
|
+
|| !((event.target instanceof HTMLInputElement)
|
|
60
|
+
|| (event.target instanceof HTMLSelectElement)
|
|
61
|
+
|| (event.target instanceof HTMLTextAreaElement))
|
|
57
62
|
|| !event.target.dataset.miclinitialized
|
|
58
63
|
|| event.target.disabled
|
|
59
64
|
) {
|
|
@@ -68,13 +73,15 @@ export default (() =>
|
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
if (
|
|
71
|
-
(event.target instanceof
|
|
72
|
-
|
|
76
|
+
(event.target instanceof HTMLSelectElement)
|
|
77
|
+
|| !event.target.maxLength
|
|
73
78
|
) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const counter = event.target.parentElement?.querySelector(counterSelector);
|
|
83
|
+
if (counter) {
|
|
84
|
+
counter.textContent = `${event.target.value.length}/${event.target.maxLength}`;
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
};
|
package/components.ts
CHANGED
|
@@ -25,7 +25,7 @@ import _checkbox, { checkboxSelector } from './components/checkbox';
|
|
|
25
25
|
import _list, { listSelector } from './components/list';
|
|
26
26
|
import _menu, { menuSelector } from './components/menu';
|
|
27
27
|
import _slider, { sliderSelector } from './components/slider';
|
|
28
|
-
import _textfield, { textfieldSelector, selectSelector } from './components/textfield';
|
|
28
|
+
import _textfield, { textfieldSelector, selectSelector, textareaSelector } from './components/textfield';
|
|
29
29
|
|
|
30
30
|
interface ComponentEntry<T extends HTMLElement> {
|
|
31
31
|
component: {
|
|
@@ -47,6 +47,7 @@ export default (() =>
|
|
|
47
47
|
[menuSelector] : { component: _menu, type: HTMLElement },
|
|
48
48
|
[selectSelector] : { component: _textfield, type: HTMLSelectElement },
|
|
49
49
|
[sliderSelector] : { component: _slider, type: HTMLInputElement },
|
|
50
|
+
[textareaSelector] : { component: _textfield, type: HTMLTextAreaElement },
|
|
50
51
|
[textfieldSelector] : { component: _textfield, type: HTMLInputElement }
|
|
51
52
|
};
|
|
52
53
|
|