@moni-labs/moni-ui 0.2.0 → 0.3.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 +52 -194
- package/custom-elements.json +1636 -350
- package/dist/actions/index.d.ts +6 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +6 -0
- package/dist/components/_base/field-styles.d.ts +51 -16
- package/dist/components/_base/field-styles.d.ts.map +1 -1
- package/dist/components/_base/field-styles.js +164 -36
- package/dist/components/_base/index.d.ts +25 -0
- package/dist/components/_base/index.d.ts.map +1 -1
- package/dist/components/_base/index.js +25 -0
- package/dist/components/_base/interaction-styles.d.ts +39 -12
- package/dist/components/_base/interaction-styles.d.ts.map +1 -1
- package/dist/components/_base/interaction-styles.js +85 -33
- package/dist/components/_base/moni-element.d.ts +43 -8
- package/dist/components/_base/moni-element.d.ts.map +1 -1
- package/dist/components/_base/moni-element.js +43 -8
- package/dist/components/_base/shared-styles.d.ts +41 -17
- package/dist/components/_base/shared-styles.d.ts.map +1 -1
- package/dist/components/_base/shared-styles.js +113 -21
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +6 -0
- package/dist/components/loading-shapes.d.ts +6 -0
- package/dist/components/loading-shapes.d.ts.map +1 -1
- package/dist/components/loading-shapes.js +6 -0
- package/dist/components/moni-app-bar.d.ts +128 -33
- package/dist/components/moni-app-bar.d.ts.map +1 -1
- package/dist/components/moni-app-bar.js +121 -26
- package/dist/components/moni-badge.d.ts +122 -14
- package/dist/components/moni-badge.d.ts.map +1 -1
- package/dist/components/moni-badge.js +122 -14
- package/dist/components/moni-bottom-sheet.d.ts +120 -15
- package/dist/components/moni-bottom-sheet.d.ts.map +1 -1
- package/dist/components/moni-bottom-sheet.js +116 -12
- package/dist/components/moni-button-group.d.ts +53 -27
- package/dist/components/moni-button-group.d.ts.map +1 -1
- package/dist/components/moni-button-group.js +49 -23
- package/dist/components/moni-button-segment.d.ts +28 -8
- package/dist/components/moni-button-segment.d.ts.map +1 -1
- package/dist/components/moni-button-segment.js +27 -7
- package/dist/components/moni-button.d.ts +51 -32
- package/dist/components/moni-button.d.ts.map +1 -1
- package/dist/components/moni-button.js +50 -31
- package/dist/components/moni-card.d.ts +91 -31
- package/dist/components/moni-card.d.ts.map +1 -1
- package/dist/components/moni-card.js +86 -26
- package/dist/components/moni-carousel.d.ts +67 -17
- package/dist/components/moni-carousel.d.ts.map +1 -1
- package/dist/components/moni-carousel.js +59 -16
- package/dist/components/moni-checkbox.d.ts +122 -17
- package/dist/components/moni-checkbox.d.ts.map +1 -1
- package/dist/components/moni-checkbox.js +118 -14
- package/dist/components/moni-chip.d.ts +56 -30
- package/dist/components/moni-chip.d.ts.map +1 -1
- package/dist/components/moni-chip.js +51 -25
- package/dist/components/moni-color-field.d.ts +44 -6
- package/dist/components/moni-color-field.d.ts.map +1 -1
- package/dist/components/moni-color-field.js +43 -5
- package/dist/components/moni-context-menu.d.ts +44 -22
- package/dist/components/moni-context-menu.d.ts.map +1 -1
- package/dist/components/moni-context-menu.js +43 -21
- package/dist/components/moni-dialog.d.ts +107 -15
- package/dist/components/moni-dialog.d.ts.map +1 -1
- package/dist/components/moni-dialog.js +105 -14
- package/dist/components/moni-divider.d.ts +50 -15
- package/dist/components/moni-divider.d.ts.map +1 -1
- package/dist/components/moni-divider.js +49 -14
- package/dist/components/moni-expansion.d.ts +44 -8
- package/dist/components/moni-expansion.d.ts.map +1 -1
- package/dist/components/moni-expansion.js +43 -7
- package/dist/components/moni-fab-menu.d.ts +39 -20
- package/dist/components/moni-fab-menu.d.ts.map +1 -1
- package/dist/components/moni-fab-menu.js +38 -19
- package/dist/components/moni-fab.d.ts +49 -23
- package/dist/components/moni-fab.d.ts.map +1 -1
- package/dist/components/moni-fab.js +46 -20
- package/dist/components/moni-file-field.d.ts +54 -14
- package/dist/components/moni-file-field.d.ts.map +1 -1
- package/dist/components/moni-file-field.js +53 -13
- package/dist/components/moni-icon.d.ts +78 -11
- package/dist/components/moni-icon.d.ts.map +1 -1
- package/dist/components/moni-icon.js +77 -10
- package/dist/components/moni-list-item.d.ts +61 -30
- package/dist/components/moni-list-item.d.ts.map +1 -1
- package/dist/components/moni-list-item.js +55 -24
- package/dist/components/moni-list.d.ts +37 -13
- package/dist/components/moni-list.d.ts.map +1 -1
- package/dist/components/moni-list.js +36 -12
- package/dist/components/moni-loading-indicator.d.ts +38 -11
- package/dist/components/moni-loading-indicator.d.ts.map +1 -1
- package/dist/components/moni-loading-indicator.js +37 -10
- package/dist/components/moni-menu-item.d.ts +31 -8
- package/dist/components/moni-menu-item.d.ts.map +1 -1
- package/dist/components/moni-menu-item.js +30 -7
- package/dist/components/moni-menu.d.ts +58 -33
- package/dist/components/moni-menu.d.ts.map +1 -1
- package/dist/components/moni-menu.js +51 -26
- package/dist/components/moni-morph-modal.d.ts +7 -1
- package/dist/components/moni-morph-modal.d.ts.map +1 -1
- package/dist/components/moni-morph-modal.js +46 -24
- package/dist/components/moni-nav-item.d.ts +50 -10
- package/dist/components/moni-nav-item.d.ts.map +1 -1
- package/dist/components/moni-nav-item.js +48 -8
- package/dist/components/moni-nav.d.ts +57 -22
- package/dist/components/moni-nav.d.ts.map +1 -1
- package/dist/components/moni-nav.js +53 -18
- package/dist/components/moni-progress.d.ts +108 -20
- package/dist/components/moni-progress.d.ts.map +1 -1
- package/dist/components/moni-progress.js +104 -16
- package/dist/components/moni-radio.d.ts +106 -14
- package/dist/components/moni-radio.d.ts.map +1 -1
- package/dist/components/moni-radio.js +104 -13
- package/dist/components/moni-ripple.d.ts +121 -10
- package/dist/components/moni-ripple.d.ts.map +1 -1
- package/dist/components/moni-ripple.js +120 -9
- package/dist/components/moni-segmented-button.d.ts +31 -11
- package/dist/components/moni-segmented-button.d.ts.map +1 -1
- package/dist/components/moni-segmented-button.js +30 -10
- package/dist/components/moni-select-option.d.ts +43 -9
- package/dist/components/moni-select-option.d.ts.map +1 -1
- package/dist/components/moni-select-option.js +41 -7
- package/dist/components/moni-select.d.ts +59 -2
- package/dist/components/moni-select.d.ts.map +1 -1
- package/dist/components/moni-select.js +58 -1
- package/dist/components/moni-shape.d.ts +1 -1
- package/dist/components/moni-side-sheet.d.ts +56 -19
- package/dist/components/moni-side-sheet.d.ts.map +1 -1
- package/dist/components/moni-side-sheet.js +53 -16
- package/dist/components/moni-slider.d.ts +56 -25
- package/dist/components/moni-slider.d.ts.map +1 -1
- package/dist/components/moni-slider.js +55 -24
- package/dist/components/moni-snackbar.d.ts +86 -17
- package/dist/components/moni-snackbar.d.ts.map +1 -1
- package/dist/components/moni-snackbar.js +85 -16
- package/dist/components/moni-split-button.d.ts +38 -9
- package/dist/components/moni-split-button.d.ts.map +1 -1
- package/dist/components/moni-split-button.js +37 -8
- package/dist/components/moni-step.d.ts +42 -9
- package/dist/components/moni-step.d.ts.map +1 -1
- package/dist/components/moni-step.js +41 -8
- package/dist/components/moni-stepper.d.ts +43 -6
- package/dist/components/moni-stepper.d.ts.map +1 -1
- package/dist/components/moni-stepper.js +42 -5
- package/dist/components/moni-switch.d.ts +103 -16
- package/dist/components/moni-switch.d.ts.map +1 -1
- package/dist/components/moni-switch.js +99 -13
- package/dist/components/moni-tab.d.ts +35 -8
- package/dist/components/moni-tab.d.ts.map +1 -1
- package/dist/components/moni-tab.js +34 -7
- package/dist/components/moni-tabs.d.ts +51 -13
- package/dist/components/moni-tabs.d.ts.map +1 -1
- package/dist/components/moni-tabs.js +48 -10
- package/dist/components/moni-text-field.d.ts +55 -10
- package/dist/components/moni-text-field.d.ts.map +1 -1
- package/dist/components/moni-text-field.js +54 -9
- package/dist/components/moni-textarea.d.ts +51 -21
- package/dist/components/moni-textarea.d.ts.map +1 -1
- package/dist/components/moni-textarea.js +48 -18
- package/dist/components/moni-time-picker.d.ts +41 -11
- package/dist/components/moni-time-picker.d.ts.map +1 -1
- package/dist/components/moni-time-picker.js +40 -10
- package/dist/components/moni-toolbar.d.ts +43 -15
- package/dist/components/moni-toolbar.d.ts.map +1 -1
- package/dist/components/moni-toolbar.js +42 -14
- package/dist/components/moni-tooltip.d.ts +55 -25
- package/dist/components/moni-tooltip.d.ts.map +1 -1
- package/dist/components/moni-tooltip.js +54 -24
- package/dist/components/moni-typography.d.ts +43 -18
- package/dist/components/moni-typography.d.ts.map +1 -1
- package/dist/components/moni-typography.js +42 -17
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -2
- package/dist/styles/tailwind.css +67 -0
- package/dist/styles/tokens.css +111 -99
- package/dist/utils/color.d.ts +181 -2
- package/dist/utils/color.d.ts.map +1 -1
- package/dist/utils/color.js +182 -4
- package/dist/utils/theme.svelte.d.ts +305 -2
- package/dist/utils/theme.svelte.d.ts.map +1 -1
- package/dist/utils/theme.svelte.js +331 -2
- package/dist/web-components.d.ts +28 -0
- package/dist/web-components.d.ts.map +1 -1
- package/dist/web-components.js +29 -2
- package/package.json +1 -1
- package/src/actions/index.ts +7 -0
- package/src/components/_base/field-styles.ts +165 -37
- package/src/components/_base/index.ts +27 -0
- package/src/components/_base/interaction-styles.ts +86 -33
- package/src/components/_base/moni-element.ts +44 -8
- package/src/components/_base/shared-styles.ts +114 -21
- package/src/components/index.ts +7 -0
- package/src/components/loading-shapes.ts +7 -0
- package/src/components/moni-app-bar.ts +127 -26
- package/src/components/moni-badge.ts +128 -14
- package/src/components/moni-bottom-sheet.ts +125 -13
- package/src/components/moni-button-group.ts +50 -23
- package/src/components/moni-button-segment.ts +28 -7
- package/src/components/moni-button.ts +51 -31
- package/src/components/moni-card.ts +90 -26
- package/src/components/moni-carousel.ts +67 -16
- package/src/components/moni-checkbox.ts +125 -14
- package/src/components/moni-chip.ts +52 -25
- package/src/components/moni-color-field.ts +44 -5
- package/src/components/moni-context-menu.ts +44 -21
- package/src/components/moni-dialog.ts +111 -14
- package/src/components/moni-divider.ts +50 -14
- package/src/components/moni-expansion.ts +44 -7
- package/src/components/moni-fab-menu.ts +39 -19
- package/src/components/moni-fab.ts +47 -20
- package/src/components/moni-file-field.ts +54 -13
- package/src/components/moni-icon.ts +80 -10
- package/src/components/moni-list-item.ts +56 -24
- package/src/components/moni-list.ts +37 -12
- package/src/components/moni-loading-indicator.ts +38 -10
- package/src/components/moni-menu-item.ts +31 -7
- package/src/components/moni-menu.ts +52 -26
- package/src/components/moni-morph-modal.ts +58 -24
- package/src/components/moni-nav-item.ts +49 -8
- package/src/components/moni-nav.ts +54 -18
- package/src/components/moni-progress.ts +109 -16
- package/src/components/moni-radio.ts +111 -13
- package/src/components/moni-ripple.ts +126 -9
- package/src/components/moni-segmented-button.ts +31 -10
- package/src/components/moni-select-option.ts +42 -7
- package/src/components/moni-select.ts +79 -1
- package/src/components/moni-side-sheet.ts +54 -16
- package/src/components/moni-slider.ts +56 -24
- package/src/components/moni-snackbar.ts +90 -16
- package/src/components/moni-split-button.ts +38 -8
- package/src/components/moni-step.ts +42 -8
- package/src/components/moni-stepper.ts +43 -5
- package/src/components/moni-switch.ts +106 -13
- package/src/components/moni-tab.ts +35 -7
- package/src/components/moni-tabs.ts +49 -10
- package/src/components/moni-text-field.ts +55 -9
- package/src/components/moni-textarea.ts +49 -18
- package/src/components/moni-time-picker.ts +41 -10
- package/src/components/moni-toolbar.ts +43 -14
- package/src/components/moni-tooltip.ts +55 -24
- package/src/components/moni-typography.ts +43 -17
- package/src/index.ts +67 -3
- package/src/styles/tailwind.css +67 -0
- package/src/styles/tokens.css +111 -99
- package/src/types/svelte-runes.d.ts +64 -2
- package/src/utils/color.ts +286 -5
- package/src/utils/theme.svelte.ts +411 -2
- package/src/web-components.ts +31 -2
- package/dist/assets/shapes/arch.svg +0 -1
- package/dist/assets/shapes/arrow.svg +0 -1
- package/dist/assets/shapes/boom.svg +0 -1
- package/dist/assets/shapes/burst.svg +0 -1
- package/dist/assets/shapes/circle.svg +0 -1
- package/dist/assets/shapes/clamshell.svg +0 -1
- package/dist/assets/shapes/diamond.svg +0 -1
- package/dist/assets/shapes/fan.svg +0 -1
- package/dist/assets/shapes/flower.svg +0 -1
- package/dist/assets/shapes/gem.svg +0 -1
- package/dist/assets/shapes/ghost-ish.svg +0 -1
- package/dist/assets/shapes/heart.svg +0 -1
- package/dist/assets/shapes/leaf-clover4.svg +0 -1
- package/dist/assets/shapes/leaf-clover8.svg +0 -1
- package/dist/assets/shapes/loading-indicator.svg +0 -1
- package/dist/assets/shapes/oval.svg +0 -1
- package/dist/assets/shapes/pentagon.svg +0 -1
- package/dist/assets/shapes/pill.svg +0 -1
- package/dist/assets/shapes/pixel-circle.svg +0 -1
- package/dist/assets/shapes/pixel-triangle.svg +0 -1
- package/dist/assets/shapes/puffy-diamond.svg +0 -1
- package/dist/assets/shapes/puffy.svg +0 -1
- package/dist/assets/shapes/semicircle.svg +0 -1
- package/dist/assets/shapes/sided-cookie12.svg +0 -1
- package/dist/assets/shapes/sided-cookie4.svg +0 -1
- package/dist/assets/shapes/sided-cookie6.svg +0 -1
- package/dist/assets/shapes/sided-cookie7.svg +0 -1
- package/dist/assets/shapes/sided-cookie9.svg +0 -1
- package/dist/assets/shapes/slanted.svg +0 -1
- package/dist/assets/shapes/soft-boom.svg +0 -1
- package/dist/assets/shapes/soft-burst.svg +0 -1
- package/dist/assets/shapes/square.svg +0 -1
- package/dist/assets/shapes/sunny.svg +0 -1
- package/dist/assets/shapes/triangle.svg +0 -1
- package/dist/assets/shapes/very-sunny.svg +0 -1
- package/dist/assets/shapes/wavy-circle.svg +0 -1
- package/dist/assets/shapes/wavy.svg +0 -1
- package/src/assets/shapes/arch.svg +0 -1
- package/src/assets/shapes/arrow.svg +0 -1
- package/src/assets/shapes/boom.svg +0 -1
- package/src/assets/shapes/burst.svg +0 -1
- package/src/assets/shapes/circle.svg +0 -1
- package/src/assets/shapes/clamshell.svg +0 -1
- package/src/assets/shapes/diamond.svg +0 -1
- package/src/assets/shapes/fan.svg +0 -1
- package/src/assets/shapes/flower.svg +0 -1
- package/src/assets/shapes/gem.svg +0 -1
- package/src/assets/shapes/ghost-ish.svg +0 -1
- package/src/assets/shapes/heart.svg +0 -1
- package/src/assets/shapes/leaf-clover4.svg +0 -1
- package/src/assets/shapes/leaf-clover8.svg +0 -1
- package/src/assets/shapes/loading-indicator.svg +0 -1
- package/src/assets/shapes/oval.svg +0 -1
- package/src/assets/shapes/pentagon.svg +0 -1
- package/src/assets/shapes/pill.svg +0 -1
- package/src/assets/shapes/pixel-circle.svg +0 -1
- package/src/assets/shapes/pixel-triangle.svg +0 -1
- package/src/assets/shapes/puffy-diamond.svg +0 -1
- package/src/assets/shapes/puffy.svg +0 -1
- package/src/assets/shapes/semicircle.svg +0 -1
- package/src/assets/shapes/sided-cookie12.svg +0 -1
- package/src/assets/shapes/sided-cookie4.svg +0 -1
- package/src/assets/shapes/sided-cookie6.svg +0 -1
- package/src/assets/shapes/sided-cookie7.svg +0 -1
- package/src/assets/shapes/sided-cookie9.svg +0 -1
- package/src/assets/shapes/slanted.svg +0 -1
- package/src/assets/shapes/soft-boom.svg +0 -1
- package/src/assets/shapes/soft-burst.svg +0 -1
- package/src/assets/shapes/square.svg +0 -1
- package/src/assets/shapes/sunny.svg +0 -1
- package/src/assets/shapes/triangle.svg +0 -1
- package/src/assets/shapes/very-sunny.svg +0 -1
- package/src/assets/shapes/wavy-circle.svg +0 -1
- package/src/assets/shapes/wavy.svg +0 -1
package/dist/actions/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,CAAC"}
|
package/dist/actions/index.js
CHANGED
|
@@ -1,23 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* @file components/_base/field-styles.ts
|
|
3
|
+
* @package @moni-labs/moni-ui
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @contributors Moni Labs & Contributors
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Shared visual rules for all field-like input components.
|
|
9
|
+
*
|
|
10
|
+
* This stylesheet provides the complete CSS foundation for the Moni input
|
|
11
|
+
* field pattern, ported and extended from the BeerCSS field system. It is
|
|
12
|
+
* consumed by: `moni-text-field`, `moni-textarea`, `moni-select`,
|
|
13
|
+
* `moni-color-field`, and `moni-file-field`.
|
|
14
|
+
*
|
|
15
|
+
* **Required DOM structure:**
|
|
16
|
+
* Each consumer must render this exact DOM hierarchy inside its shadow root for
|
|
17
|
+
* all selectors (especially the floating label) to function correctly:
|
|
18
|
+
*
|
|
19
|
+
* ```html
|
|
20
|
+
* <div class="field [label] [fill|border] [small|large|extra] [prefix|suffix|icon] [invalid] [round*]">
|
|
21
|
+
* <i class="leading-icon">...</i> <!-- optional leading icon -->
|
|
22
|
+
* <input | select | textarea> <!-- native form control -->
|
|
23
|
+
* <label>Label text</label> <!-- MUST be immediately after the control -->
|
|
24
|
+
* <i class="trailing-icon">...</i> <!-- optional trailing icon -->
|
|
25
|
+
* <span class="suffix-text">...</span> <!-- optional suffix text -->
|
|
26
|
+
* <slot name="trailing"></slot> <!-- optional trailing slot -->
|
|
27
|
+
* <output>Helper or error text</output> <!-- helper / validation message -->
|
|
28
|
+
* </div>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* **Critical ordering rule:**
|
|
32
|
+
* The `<label>` element MUST be the immediate next sibling of the
|
|
33
|
+
* `<input|select|textarea>`. The CSS adjacent sibling combinator (`+ label`)
|
|
34
|
+
* and the `:focus + label` selector depend on this ordering to animate the
|
|
35
|
+
* floating label lift. Breaking the order will prevent the label from animating.
|
|
3
36
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
37
|
+
* **Modifier classes:**
|
|
38
|
+
* - `.label` — Activates the floating label behavior.
|
|
39
|
+
* - `.fill` — Uses `surface-container-highest` as the input background (filled style).
|
|
40
|
+
* - `.border` — Applies an `outline-variant` border (outlined style).
|
|
41
|
+
* - `.small` / `.large` / `.extra` — Adjusts height and padding.
|
|
42
|
+
* - `.prefix` / `.suffix` — Shifts input padding to make room for icons.
|
|
43
|
+
* - `.invalid` — Applies error color to borders, label, and helper text.
|
|
44
|
+
* - `.round` / `.round-*` — Applies pill-shaped border radius to the field.
|
|
45
|
+
* - `.square` — Removes all border-radius (overrides everything via `!important`).
|
|
7
46
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* <slot name="trailing"> ← optional slot
|
|
15
|
-
* <output> ← helper text or error
|
|
16
|
-
* </div>
|
|
47
|
+
* **Internal CSS custom properties:**
|
|
48
|
+
* | Property | Default | Description |
|
|
49
|
+
* |------------|---------|------------------------------------------|
|
|
50
|
+
* | `--_input` | `3rem` | Height of the input area. |
|
|
51
|
+
* | `--_start` | `1.2rem`| Block-start padding for label alignment. |
|
|
52
|
+
* | `--_middle`| computed| Vertical center of the input (for icons).|
|
|
17
53
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* label. If a component reorders the DOM, the label may not animate properly.
|
|
54
|
+
* @see {@link sharedStyles} — Token bridge consumed by this stylesheet.
|
|
55
|
+
* @see {@link interactionStyles} — State layer (not used directly in fields).
|
|
21
56
|
*/
|
|
22
57
|
export declare const fieldStyles: import("lit").CSSResult;
|
|
23
58
|
export default fieldStyles;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-styles.d.ts","sourceRoot":"","sources":["../../../src/components/_base/field-styles.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"field-styles.d.ts","sourceRoot":"","sources":["../../../src/components/_base/field-styles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,WAAW,yBA6jBvB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -1,35 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file components/_base/field-styles.ts
|
|
3
|
+
* @package @moni-labs/moni-ui
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @contributors Moni Labs & Contributors
|
|
6
|
+
*/
|
|
1
7
|
import { css } from 'lit';
|
|
2
8
|
/**
|
|
3
|
-
* Shared visual rules for
|
|
9
|
+
* Shared visual rules for all field-like input components.
|
|
10
|
+
*
|
|
11
|
+
* This stylesheet provides the complete CSS foundation for the Moni input
|
|
12
|
+
* field pattern, ported and extended from the BeerCSS field system. It is
|
|
13
|
+
* consumed by: `moni-text-field`, `moni-textarea`, `moni-select`,
|
|
14
|
+
* `moni-color-field`, and `moni-file-field`.
|
|
15
|
+
*
|
|
16
|
+
* **Required DOM structure:**
|
|
17
|
+
* Each consumer must render this exact DOM hierarchy inside its shadow root for
|
|
18
|
+
* all selectors (especially the floating label) to function correctly:
|
|
19
|
+
*
|
|
20
|
+
* ```html
|
|
21
|
+
* <div class="field [label] [fill|border] [small|large|extra] [prefix|suffix|icon] [invalid] [round*]">
|
|
22
|
+
* <i class="leading-icon">...</i> <!-- optional leading icon -->
|
|
23
|
+
* <input | select | textarea> <!-- native form control -->
|
|
24
|
+
* <label>Label text</label> <!-- MUST be immediately after the control -->
|
|
25
|
+
* <i class="trailing-icon">...</i> <!-- optional trailing icon -->
|
|
26
|
+
* <span class="suffix-text">...</span> <!-- optional suffix text -->
|
|
27
|
+
* <slot name="trailing"></slot> <!-- optional trailing slot -->
|
|
28
|
+
* <output>Helper or error text</output> <!-- helper / validation message -->
|
|
29
|
+
* </div>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* **Critical ordering rule:**
|
|
33
|
+
* The `<label>` element MUST be the immediate next sibling of the
|
|
34
|
+
* `<input|select|textarea>`. The CSS adjacent sibling combinator (`+ label`)
|
|
35
|
+
* and the `:focus + label` selector depend on this ordering to animate the
|
|
36
|
+
* floating label lift. Breaking the order will prevent the label from animating.
|
|
4
37
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
38
|
+
* **Modifier classes:**
|
|
39
|
+
* - `.label` — Activates the floating label behavior.
|
|
40
|
+
* - `.fill` — Uses `surface-container-highest` as the input background (filled style).
|
|
41
|
+
* - `.border` — Applies an `outline-variant` border (outlined style).
|
|
42
|
+
* - `.small` / `.large` / `.extra` — Adjusts height and padding.
|
|
43
|
+
* - `.prefix` / `.suffix` — Shifts input padding to make room for icons.
|
|
44
|
+
* - `.invalid` — Applies error color to borders, label, and helper text.
|
|
45
|
+
* - `.round` / `.round-*` — Applies pill-shaped border radius to the field.
|
|
46
|
+
* - `.square` — Removes all border-radius (overrides everything via `!important`).
|
|
8
47
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* <slot name="trailing"> ← optional slot
|
|
16
|
-
* <output> ← helper text or error
|
|
17
|
-
* </div>
|
|
48
|
+
* **Internal CSS custom properties:**
|
|
49
|
+
* | Property | Default | Description |
|
|
50
|
+
* |------------|---------|------------------------------------------|
|
|
51
|
+
* | `--_input` | `3rem` | Height of the input area. |
|
|
52
|
+
* | `--_start` | `1.2rem`| Block-start padding for label alignment. |
|
|
53
|
+
* | `--_middle`| computed| Vertical center of the input (for icons).|
|
|
18
54
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* label. If a component reorders the DOM, the label may not animate properly.
|
|
55
|
+
* @see {@link sharedStyles} — Token bridge consumed by this stylesheet.
|
|
56
|
+
* @see {@link interactionStyles} — State layer (not used directly in fields).
|
|
22
57
|
*/
|
|
23
58
|
export const fieldStyles = css `
|
|
24
59
|
:host {
|
|
25
60
|
display: block;
|
|
61
|
+
/* Fields are full-width by default; the parent layout controls sizing. */
|
|
26
62
|
inline-size: 100%;
|
|
27
63
|
}
|
|
28
64
|
|
|
65
|
+
/* ─── Base field container ───────────────────────────────────────────────── */
|
|
29
66
|
.field {
|
|
67
|
+
/* Internal height token — overridden by size modifiers (.small, .large, .extra). */
|
|
30
68
|
--_input: 3rem;
|
|
69
|
+
/* Vertical start offset used for textarea padding and label positioning. */
|
|
31
70
|
--_start: 1.2rem;
|
|
71
|
+
/* Computed vertical center — used to position absolutely-placed icons. */
|
|
32
72
|
--_middle: calc(var(--_input, 0) / 2);
|
|
73
|
+
|
|
74
|
+
/* Default field shape: bottom border only (BeerCSS / MD3 "filled" style). */
|
|
33
75
|
border-radius: 0.25rem 0.25rem 0 0;
|
|
34
76
|
min-block-size: var(--_input);
|
|
35
77
|
display: flex;
|
|
@@ -38,17 +80,22 @@ export const fieldStyles = css `
|
|
|
38
80
|
inline-size: 100%;
|
|
39
81
|
}
|
|
40
82
|
|
|
41
|
-
/*
|
|
83
|
+
/* ─── Shape overrides ────────────────────────────────────────────────────── */
|
|
84
|
+
|
|
85
|
+
/* Square: removes all border-radius regardless of other modifiers.
|
|
86
|
+
Uses !important to win specificity over .border and [class*='round']. */
|
|
42
87
|
.field.square,
|
|
43
88
|
.field.square.border,
|
|
44
89
|
.field.square[class*='round'] {
|
|
45
90
|
border-radius: 0 !important;
|
|
46
91
|
}
|
|
47
|
-
|
|
48
92
|
.field.square > :is(input, textarea, select) {
|
|
49
93
|
border-radius: 0 !important;
|
|
50
94
|
}
|
|
51
95
|
|
|
96
|
+
/* ─── Fill variant ───────────────────────────────────────────────────────── */
|
|
97
|
+
/* Unsets background/color on the container; the background is applied
|
|
98
|
+
directly to the <input> so that the floating label overlaps it correctly. */
|
|
52
99
|
.field.fill {
|
|
53
100
|
--_background: var(--surface-container-highest);
|
|
54
101
|
background-color: unset !important;
|
|
@@ -56,9 +103,11 @@ export const fieldStyles = css `
|
|
|
56
103
|
}
|
|
57
104
|
.field.fill > :is(input, select, textarea) {
|
|
58
105
|
background-color: var(--_background);
|
|
106
|
+
/* z-index: 0 ensures the background renders above the ::before layer. */
|
|
59
107
|
z-index: 0;
|
|
60
108
|
}
|
|
61
109
|
|
|
110
|
+
/* ─── Size variants ──────────────────────────────────────────────────────── */
|
|
62
111
|
.field.small {
|
|
63
112
|
--_input: 2.5rem;
|
|
64
113
|
--_start: 1rem;
|
|
@@ -72,10 +121,14 @@ export const fieldStyles = css `
|
|
|
72
121
|
--_start: 1.6rem;
|
|
73
122
|
}
|
|
74
123
|
|
|
124
|
+
/* ─── Border (outlined) variant ─────────────────────────────────────────── */
|
|
125
|
+
/* Adds full border-radius and outline-variant stroke on all four sides. */
|
|
75
126
|
.field.border {
|
|
76
127
|
border-radius: 0.25rem;
|
|
77
128
|
}
|
|
78
129
|
|
|
130
|
+
/* ─── Round / pill variants ──────────────────────────────────────────────── */
|
|
131
|
+
/* Applied when class matches the 'round' substring (e.g. .round, .round-sm). */
|
|
79
132
|
.field[class*='round'].small {
|
|
80
133
|
border-radius: 1.25rem;
|
|
81
134
|
}
|
|
@@ -89,10 +142,8 @@ export const fieldStyles = css `
|
|
|
89
142
|
border-radius: 2rem;
|
|
90
143
|
}
|
|
91
144
|
|
|
92
|
-
/*
|
|
93
|
-
|
|
94
|
-
the position-suffix selectors and guarantee correct placement even when
|
|
95
|
-
the icon is wrapped in a custom element (e.g. <moni-icon>). */
|
|
145
|
+
/* ─── Icon positioning ───────────────────────────────────────────────────── */
|
|
146
|
+
/* Generic rule: absolutely positions any icon/image/svg inside the field. */
|
|
96
147
|
.field > :is(i, img, svg) {
|
|
97
148
|
position: absolute;
|
|
98
149
|
inset: calc((var(--_input, 0) / 2) - 0.75rem) auto auto auto;
|
|
@@ -103,31 +154,37 @@ export const fieldStyles = css `
|
|
|
103
154
|
margin: auto 0;
|
|
104
155
|
pointer-events: none;
|
|
105
156
|
}
|
|
157
|
+
/* Leading icon: explicit class wins over :first-child heuristic. */
|
|
106
158
|
.field > :is(i, img, svg):first-child,
|
|
107
159
|
.field > .leading-icon {
|
|
108
160
|
inset: calc(var(--_middle, 0) - 0.75rem) auto auto 1rem;
|
|
109
161
|
}
|
|
110
162
|
|
|
111
|
-
/* Trailing icon: BeerCSS uses :last-child:not(:first-child) which fails
|
|
112
|
-
|
|
113
|
-
|
|
163
|
+
/* Trailing icon: BeerCSS uses :last-child:not(:first-child) which fails when
|
|
164
|
+
an <output> follows the icon. The explicit class always wins and places
|
|
165
|
+
the icon on the right edge regardless of sibling count. */
|
|
114
166
|
.field > :is(i, img, svg):last-child:not(:first-child),
|
|
115
167
|
.field > .trailing-icon {
|
|
116
168
|
inset: calc(var(--_middle, 0) - 0.75rem) 1rem auto auto;
|
|
169
|
+
/* Prevent the inline-start override from the generic rule above. */
|
|
117
170
|
inset-inline-start: auto !important;
|
|
118
171
|
}
|
|
119
172
|
|
|
173
|
+
/* Error state: trailing icons inherit the error color. */
|
|
120
174
|
.field.invalid > i {
|
|
121
175
|
color: var(--error);
|
|
122
176
|
}
|
|
123
177
|
|
|
124
|
-
/*
|
|
178
|
+
/* ─── Native form element reset ──────────────────────────────────────────── */
|
|
179
|
+
/* 'all: unset' strips browser-default styles (appearance, border, font, etc.)
|
|
180
|
+
so the field's visual design is fully controlled by Moni's CSS. */
|
|
125
181
|
.field > :is(input, textarea, select) {
|
|
126
182
|
all: unset;
|
|
127
183
|
position: relative;
|
|
128
184
|
display: block;
|
|
129
185
|
box-sizing: border-box;
|
|
130
186
|
border-radius: inherit;
|
|
187
|
+
/* Default border is transparent; visible only in .border and focus states. */
|
|
131
188
|
border: 0.0625rem solid transparent;
|
|
132
189
|
padding: 0 0.9375rem;
|
|
133
190
|
font-family: inherit;
|
|
@@ -136,30 +193,42 @@ export const fieldStyles = css `
|
|
|
136
193
|
outline: none;
|
|
137
194
|
z-index: 1;
|
|
138
195
|
background: none;
|
|
139
|
-
resize: none;
|
|
196
|
+
resize: none; /* Textareas use field-sizing:content instead of manual resize. */
|
|
140
197
|
text-align: start;
|
|
141
198
|
cursor: text;
|
|
142
199
|
color: var(--on-surface);
|
|
143
200
|
}
|
|
144
201
|
|
|
202
|
+
/* Ensure date/time input values align to start (browser quirk on some platforms). */
|
|
145
203
|
input::-webkit-date-and-time-value {
|
|
146
204
|
text-align: start;
|
|
147
205
|
}
|
|
206
|
+
|
|
207
|
+
/* Autofill: preserve text color when the browser applies its autofill highlight.
|
|
208
|
+
-webkit-background-clip + -webkit-text-fill-color override the yellow tint. */
|
|
148
209
|
:is(input, select, textarea):is(:-webkit-autofill, :autofill) {
|
|
149
210
|
-webkit-background-clip: text;
|
|
150
211
|
-webkit-text-fill-color: var(--on-surface);
|
|
151
212
|
}
|
|
152
213
|
|
|
214
|
+
/* On focus, increase border width by 1px — shift padding inward by 1px
|
|
215
|
+
to prevent layout shift from the border width change. */
|
|
153
216
|
.field > :is(input, textarea, select):focus {
|
|
154
217
|
border: 0.125rem solid transparent;
|
|
155
218
|
padding-inline: 0.875rem;
|
|
156
219
|
}
|
|
157
220
|
|
|
221
|
+
/* Textareas without explicit rows grow automatically using field-sizing:content.
|
|
222
|
+
A max-height of 12rem (~8 lines) prevents uncontrolled page growth. */
|
|
158
223
|
.field > textarea:not([rows]) {
|
|
159
224
|
field-sizing: content;
|
|
160
225
|
max-block-size: 12rem;
|
|
161
226
|
}
|
|
162
227
|
|
|
228
|
+
/* ─── Transparent native picker controls ─────────────────────────────────── */
|
|
229
|
+
/* File and color inputs, and date/time picker indicators are hidden so the
|
|
230
|
+
component can render its own UI. The native controls are still active for
|
|
231
|
+
accessibility (click propagates through the transparent overlay). */
|
|
163
232
|
input[type='file'],
|
|
164
233
|
input[type='color'],
|
|
165
234
|
:not(.field) > input:is([type^='date'], [type^='time'], [type='month'], [type='week']),
|
|
@@ -176,12 +245,15 @@ export const fieldStyles = css `
|
|
|
176
245
|
z-index: 2 !important;
|
|
177
246
|
}
|
|
178
247
|
|
|
248
|
+
/* On fine-pointer (mouse) devices, push the calendar picker indicator behind
|
|
249
|
+
the field content so it doesn't interfere with other clickable elements. */
|
|
179
250
|
@media (pointer: fine) {
|
|
180
251
|
.field > input::-webkit-calendar-picker-indicator {
|
|
181
252
|
z-index: -1 !important;
|
|
182
253
|
}
|
|
183
254
|
}
|
|
184
255
|
|
|
256
|
+
/* Remove browser-native search field decorations. */
|
|
185
257
|
input::-webkit-search-decoration,
|
|
186
258
|
input::-webkit-search-cancel-button,
|
|
187
259
|
input::-webkit-search-results-button,
|
|
@@ -191,10 +263,12 @@ export const fieldStyles = css `
|
|
|
191
263
|
display: none;
|
|
192
264
|
}
|
|
193
265
|
|
|
266
|
+
/* Remove the browser spinner on number inputs — use explicit stepper UI instead. */
|
|
194
267
|
input[type='number'] {
|
|
195
268
|
appearance: textfield;
|
|
196
269
|
}
|
|
197
270
|
|
|
271
|
+
/* ─── Border variant: field-level border colors ──────────────────────────── */
|
|
198
272
|
.field.border > :is(input, textarea, select) {
|
|
199
273
|
border-color: var(--outline);
|
|
200
274
|
}
|
|
@@ -202,6 +276,7 @@ export const fieldStyles = css `
|
|
|
202
276
|
border-color: var(--primary);
|
|
203
277
|
}
|
|
204
278
|
|
|
279
|
+
/* Round variants add extra inline padding to clear the curved edges. */
|
|
205
280
|
.field[class*='round'] > :is(input, textarea, select) {
|
|
206
281
|
padding-inline: 1.4376rem;
|
|
207
282
|
}
|
|
@@ -209,13 +284,14 @@ export const fieldStyles = css `
|
|
|
209
284
|
padding-inline: 1.375rem;
|
|
210
285
|
}
|
|
211
286
|
|
|
287
|
+
/* ─── Icon padding accommodation ─────────────────────────────────────────── */
|
|
288
|
+
/* .prefix / .suffix shift the input's inline padding to make room for icons. */
|
|
212
289
|
.field.prefix > :is(input, textarea, select) {
|
|
213
290
|
padding-inline-start: 2.9375rem;
|
|
214
291
|
}
|
|
215
292
|
.field.prefix > :is(input, textarea, select):focus {
|
|
216
293
|
padding-inline-start: 2.875rem;
|
|
217
294
|
}
|
|
218
|
-
|
|
219
295
|
.field.suffix > :is(input, textarea, select) {
|
|
220
296
|
padding-inline-end: 2.9375rem;
|
|
221
297
|
}
|
|
@@ -223,6 +299,8 @@ export const fieldStyles = css `
|
|
|
223
299
|
padding-inline-end: 2.875rem;
|
|
224
300
|
}
|
|
225
301
|
|
|
302
|
+
/* ─── Underline (non-border, non-round) bottom border ─────────────────────── */
|
|
303
|
+
/* Default M3 filled field style: only the bottom border is visible. */
|
|
226
304
|
.field:not(.border, [class*='round']) > :is(input, textarea, select) {
|
|
227
305
|
border-block-end-color: var(--outline);
|
|
228
306
|
}
|
|
@@ -230,6 +308,7 @@ export const fieldStyles = css `
|
|
|
230
308
|
border-block-end-color: var(--primary);
|
|
231
309
|
}
|
|
232
310
|
|
|
311
|
+
/* Round non-bordered fields get a subtle elevation shadow instead of a border. */
|
|
233
312
|
.field[class*='round']:not(.border, .fill) > :is(input, textarea, select),
|
|
234
313
|
.field[class*='round']:not(.border) > :is(input, textarea, select):focus {
|
|
235
314
|
box-shadow: var(--elevate1);
|
|
@@ -238,6 +317,7 @@ export const fieldStyles = css `
|
|
|
238
317
|
box-shadow: var(--elevate2);
|
|
239
318
|
}
|
|
240
319
|
|
|
320
|
+
/* ─── Invalid / error state borders ─────────────────────────────────────── */
|
|
241
321
|
.field.invalid:not(.border, [class*='round']) > :is(input, textarea, select),
|
|
242
322
|
.field.invalid:not(.border, [class*='round']) > :is(input, textarea, select):focus {
|
|
243
323
|
border-block-end-color: var(--error);
|
|
@@ -247,6 +327,9 @@ export const fieldStyles = css `
|
|
|
247
327
|
border-color: var(--error);
|
|
248
328
|
}
|
|
249
329
|
|
|
330
|
+
/* ─── Disabled state ─────────────────────────────────────────────────────── */
|
|
331
|
+
/* Reduces opacity on the entire field container when the native control is
|
|
332
|
+
disabled, rather than applying separate rules to each child. */
|
|
250
333
|
.field:has(> :disabled) {
|
|
251
334
|
opacity: 0.5;
|
|
252
335
|
cursor: not-allowed;
|
|
@@ -255,6 +338,8 @@ export const fieldStyles = css `
|
|
|
255
338
|
cursor: not-allowed;
|
|
256
339
|
}
|
|
257
340
|
|
|
341
|
+
/* ─── Select element ─────────────────────────────────────────────────────── */
|
|
342
|
+
/* Remove browser-native select appearance; the component renders its own dropdown. */
|
|
258
343
|
.field > select {
|
|
259
344
|
user-select: none;
|
|
260
345
|
appearance: none;
|
|
@@ -262,17 +347,23 @@ export const fieldStyles = css `
|
|
|
262
347
|
background-image: none;
|
|
263
348
|
}
|
|
264
349
|
|
|
350
|
+
/* ─── Block-start padding for label accommodation ────────────────────────── */
|
|
351
|
+
/* Inputs with a floating label need top padding to create space for the
|
|
352
|
+
label when it lifts above the input. Selects always lift their label. */
|
|
265
353
|
.field > :is(input, select) {
|
|
266
354
|
padding-block-start: 1rem;
|
|
267
355
|
}
|
|
356
|
+
/* No-label and border+fill fields: remove the top padding offset. */
|
|
268
357
|
.field:not(.label) > :is(input, select),
|
|
269
358
|
.field.border:not(.fill) > :is(input, select) {
|
|
270
359
|
padding-block-start: 0;
|
|
271
360
|
}
|
|
361
|
+
/* Textareas use the --_start token to align with the label baseline. */
|
|
272
362
|
.field > textarea {
|
|
273
363
|
padding-block-start: var(--_start) !important;
|
|
274
364
|
}
|
|
275
365
|
.field > textarea:focus {
|
|
366
|
+
/* 0.01rem compensates for the border width increase on focus. */
|
|
276
367
|
padding-block-start: calc(var(--_start, 0) - 0.01rem) !important;
|
|
277
368
|
}
|
|
278
369
|
.field:not(.label) > textarea,
|
|
@@ -284,29 +375,42 @@ export const fieldStyles = css `
|
|
|
284
375
|
padding-block-start: calc(var(--_start, 0) - 0.51rem) !important;
|
|
285
376
|
}
|
|
286
377
|
|
|
287
|
-
/* Floating label */
|
|
378
|
+
/* ─── Floating label ─────────────────────────────────────────────────────── */
|
|
379
|
+
/* The label starts at full font-size (1rem) vertically centered in the field.
|
|
380
|
+
On focus or when value is present, it scales down to 0.75rem and lifts
|
|
381
|
+
to the top of the field container. */
|
|
288
382
|
.field.label > label {
|
|
289
383
|
--_start: 1rem;
|
|
290
384
|
position: absolute;
|
|
291
385
|
inset: -0.5rem 0.9375rem 0 var(--_start);
|
|
292
386
|
display: flex;
|
|
387
|
+
/* Full height + 1rem (for label overhang) centers the label vertically. */
|
|
293
388
|
block-size: calc(var(--_input, 0) + 1rem);
|
|
294
389
|
line-height: calc(var(--_input, 0) + 1rem);
|
|
295
390
|
font-size: 1rem;
|
|
296
391
|
transition: all 0.2s;
|
|
297
392
|
gap: 0.25rem;
|
|
298
393
|
white-space: nowrap;
|
|
394
|
+
/* The label is purely decorative from a layout perspective; it must never
|
|
395
|
+
intercept pointer events meant for the underlying input. */
|
|
299
396
|
pointer-events: none;
|
|
300
397
|
color: var(--on-surface-variant);
|
|
301
398
|
}
|
|
302
399
|
|
|
400
|
+
/* Round fields: label aligns with the increased inline padding. */
|
|
303
401
|
.field.label[class*='round'] > label {
|
|
304
402
|
inset: -0.5rem 1.9375rem 0 var(--_start);
|
|
305
403
|
}
|
|
306
404
|
|
|
307
|
-
/* Label lift
|
|
308
|
-
|
|
309
|
-
the
|
|
405
|
+
/* ─── Label lift selector group ──────────────────────────────────────────── */
|
|
406
|
+
/* The label lifts (scales down + moves up) in four conditions:
|
|
407
|
+
1. label.active — the component sets this class directly (readonly inputs).
|
|
408
|
+
2. :focus + label — when the native control is focused.
|
|
409
|
+
3. [placeholder]:not(:placeholder-shown) + label — when a value is present.
|
|
410
|
+
4. select + label — selects always show their label lifted.
|
|
411
|
+
5. input.active + label — for programmatically activated inputs. */
|
|
412
|
+
|
|
413
|
+
/* Border + prefix + no-fill variant needs a reduced --_start offset. */
|
|
310
414
|
.field.label.border.prefix:not(.fill)
|
|
311
415
|
> :is(
|
|
312
416
|
label.active,
|
|
@@ -318,6 +422,7 @@ export const fieldStyles = css `
|
|
|
318
422
|
--_start: 1rem;
|
|
319
423
|
}
|
|
320
424
|
|
|
425
|
+
/* Round field label and round border prefix field label override. */
|
|
321
426
|
.field.label[class*='round'] > label,
|
|
322
427
|
.field.label.border.prefix[class*='round']:not(.fill)
|
|
323
428
|
> :is(
|
|
@@ -330,10 +435,12 @@ export const fieldStyles = css `
|
|
|
330
435
|
--_start: 1.5rem;
|
|
331
436
|
}
|
|
332
437
|
|
|
438
|
+
/* Prefix fields: shift the label's inline-start to clear the leading icon. */
|
|
333
439
|
.field.label.prefix > label {
|
|
334
440
|
--_start: 3rem;
|
|
335
441
|
}
|
|
336
442
|
|
|
443
|
+
/* Lifted label: shrinks to 0.75rem and collapses to the top of the field. */
|
|
337
444
|
.field.label
|
|
338
445
|
> :is(
|
|
339
446
|
label.active,
|
|
@@ -347,6 +454,7 @@ export const fieldStyles = css `
|
|
|
347
454
|
font-size: 0.75rem;
|
|
348
455
|
}
|
|
349
456
|
|
|
457
|
+
/* Border variant: label collapses to 1rem height with a notch cut effect. */
|
|
350
458
|
.field.label.border:not(.fill)
|
|
351
459
|
> :is(
|
|
352
460
|
label.active,
|
|
@@ -359,6 +467,9 @@ export const fieldStyles = css `
|
|
|
359
467
|
line-height: 1rem;
|
|
360
468
|
}
|
|
361
469
|
|
|
470
|
+
/* ─── Border notch (label gap in the top border) ─────────────────────────── */
|
|
471
|
+
/* The ::after pseudo creates the horizontal line to the right of the lifted
|
|
472
|
+
label, visually cutting a notch into the top border of .field.border. */
|
|
362
473
|
.field.label.border:not(.fill) > label::after {
|
|
363
474
|
content: '';
|
|
364
475
|
display: block;
|
|
@@ -370,9 +481,14 @@ export const fieldStyles = css `
|
|
|
370
481
|
}
|
|
371
482
|
.field.label.border:not(.fill) > :focus + label::after,
|
|
372
483
|
.field.label.border:not(.fill) > input.active + label::after {
|
|
484
|
+
/* On focus, the notch line becomes primary-colored. */
|
|
373
485
|
border-block-start: 0.125rem solid var(--primary);
|
|
374
486
|
}
|
|
375
487
|
|
|
488
|
+
/* ─── Border notch clipping (clip-path) ──────────────────────────────────── */
|
|
489
|
+
/* When the label is lifted, a clip-path cuts a gap in the top border of the
|
|
490
|
+
input element itself, creating the appearance of the label floating within
|
|
491
|
+
the border's top edge. The clip-path dimensions account for label width. */
|
|
376
492
|
.field.label.border:not(.fill)
|
|
377
493
|
> :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
|
|
378
494
|
.field.label.border:not(.fill) > select,
|
|
@@ -390,6 +506,7 @@ export const fieldStyles = css `
|
|
|
390
506
|
);
|
|
391
507
|
}
|
|
392
508
|
|
|
509
|
+
/* Prefix variant: clip starts further right to clear the leading icon text. */
|
|
393
510
|
.field.label.border.prefix:not(.fill)
|
|
394
511
|
> :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
|
|
395
512
|
.field.label.border.prefix:not(.fill) > select,
|
|
@@ -407,6 +524,7 @@ export const fieldStyles = css `
|
|
|
407
524
|
);
|
|
408
525
|
}
|
|
409
526
|
|
|
527
|
+
/* Round and square border fields use a wider notch to clear the curved border. */
|
|
410
528
|
.field.label.border[class*='round']:not(.fill)
|
|
411
529
|
> :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
|
|
412
530
|
.field.label.border[class*='round']:not(.fill) > select,
|
|
@@ -434,18 +552,22 @@ export const fieldStyles = css `
|
|
|
434
552
|
clip-path: polygon(-2% -2%, 1.25rem -2%, 1.25rem 0.5rem, calc(100% - 2rem) 0.5rem, calc(100% - 2rem) -2%, 102% -2%, 102% 102%, -2% 102%);
|
|
435
553
|
}
|
|
436
554
|
|
|
555
|
+
/* ─── Label color changes ─────────────────────────────────────────────────── */
|
|
556
|
+
/* On focus: label turns primary-colored to draw attention. */
|
|
437
557
|
.field.label > :focus + label,
|
|
438
558
|
.field.label > input.active + label {
|
|
439
559
|
color: var(--primary);
|
|
440
560
|
}
|
|
441
561
|
|
|
562
|
+
/* On error: label and notch line turn error-colored. */
|
|
442
563
|
.field.label.invalid > label,
|
|
443
564
|
.field.label.invalid > label::after {
|
|
444
565
|
color: var(--error) !important;
|
|
445
566
|
border-color: var(--error) !important;
|
|
446
567
|
}
|
|
447
568
|
|
|
448
|
-
/* Helper / error output */
|
|
569
|
+
/* ─── Helper / error output ──────────────────────────────────────────────── */
|
|
570
|
+
/* The <output> element below the field shows helper text or validation errors. */
|
|
449
571
|
.field > output {
|
|
450
572
|
display: inline-block;
|
|
451
573
|
font-size: 0.75rem;
|
|
@@ -455,20 +577,23 @@ export const fieldStyles = css `
|
|
|
455
577
|
align-self: start;
|
|
456
578
|
color: var(--on-surface-variant);
|
|
457
579
|
}
|
|
580
|
+
/* Error output overrides the neutral helper color. */
|
|
458
581
|
.field > output.invalid {
|
|
459
582
|
color: var(--error) !important;
|
|
460
583
|
}
|
|
584
|
+
/* Round fields: increase horizontal padding to align with the curved edge. */
|
|
461
585
|
.field[class*='round'] > output {
|
|
462
586
|
padding: 0.25rem 1.5rem;
|
|
463
587
|
}
|
|
588
|
+
/* Show only one output at a time: helper OR error, never both. */
|
|
464
589
|
.field.invalid > output:not(.invalid),
|
|
465
590
|
.field:not(.invalid) > output.invalid {
|
|
466
591
|
display: none;
|
|
467
592
|
}
|
|
468
593
|
|
|
469
|
-
/* Footer wrapper
|
|
470
|
-
|
|
471
|
-
|
|
594
|
+
/* ─── Footer wrapper (textarea & multi-line fields) ───────────────────────── */
|
|
595
|
+
/* Lays out helper text (left) and character counter (right) on the same row,
|
|
596
|
+
matching the M3 spec for supporting-text + character-counter pairs. */
|
|
472
597
|
.field > .footer {
|
|
473
598
|
display: flex;
|
|
474
599
|
align-items: center;
|
|
@@ -489,13 +614,16 @@ export const fieldStyles = css `
|
|
|
489
614
|
.field > .footer > output.invalid {
|
|
490
615
|
color: var(--error) !important;
|
|
491
616
|
}
|
|
617
|
+
/* Character counter — right-aligned, same typographic style as the helper. */
|
|
492
618
|
.field > .footer > .counter {
|
|
493
619
|
padding: 0.25rem 1rem;
|
|
494
620
|
color: var(--on-surface-variant);
|
|
495
621
|
}
|
|
622
|
+
/* Spacer pushes counter to the right when there is no helper text. */
|
|
496
623
|
.field > .footer > .spacer {
|
|
497
624
|
flex: 1;
|
|
498
625
|
}
|
|
626
|
+
/* Same exclusive show logic as direct <output> elements. */
|
|
499
627
|
.field.invalid > .footer > output:not(.invalid),
|
|
500
628
|
.field:not(.invalid) > .footer > output.invalid {
|
|
501
629
|
display: none;
|