UNPKG

@sandlada/mdc

Version:

@sandlada/mdc is an open source component library that follows the Material Design 3 design specifications.

576 lines (515 loc) 21.6 kB
import{css as e,unsafeCSS as t}from"../../node_modules/@lit/reactive-element/css-tag.js";import"../../node_modules/lit/index.js";import{defineVars as n}from"../../node_modules/@sandlada/jss/dist/define-vars.js";import{defineTokenRefsRecord as r}from"../../node_modules/@sandlada/jss/dist/define-token-refs.js";import{FilledFieldDefinition as i,OutlinedFieldDefinition as a}from"../../component-definitions/field.definition.js"; /** * @license * Copyright 2026 Kai-Orion & Sandlada * SPDX-License-Identifier: MIT */ const o=n(r(i,{expandShapes:!0,useBaseFallback:!0,prefix:`--mdc-field`}),!0).join(``),s=n(r(a,{expandShapes:!0,useBaseFallback:!0,prefix:`--mdc-field`}),!0).join(``),c=e` @layer mdc.field.base { :host { display: inline-flex; flex-direction: column; position: relative; box-sizing: border-box; color: var(--_enabled-label-color); min-width: 240px; -webkit-tap-highlight-color: transparent; vertical-align: top; } /* ---------- Container (the visible bounding box) ---------- */ .container { position: relative; display: flex; align-items: center; box-sizing: border-box; height: var(--_container-height); padding-inline-start: var(--_container-inline-leading-padding-space); padding-inline-end: var(--_container-inline-trailing-padding-space); border-start-start-radius: var(--_container-shape-start-start); border-start-end-radius: var(--_container-shape-start-end); border-end-start-radius: var(--_container-shape-end-start); border-end-end-radius: var(--_container-shape-end-end); cursor: text; } :host([multiline]) .container { height: auto; min-height: var(--_container-height); align-items: flex-start; padding-block-start: 8px; padding-block-end: 8px; } /* ---------- Filled Variant: Background & Animated Active Indicator (Underline) ---------- */ :host([variant="filled"]) .container { background-color: var(--_enabled-container-color); transition: background-color 200ms cubic-bezier(0.2, 0, 0, 1); } :host([variant="filled"]:not([disabled]):hover) .container { background-color: var(--_hovered-container-color); } :host([variant="filled"][disabled]) .container { background-color: var(--_disabled-container-color); } /* Filled resting 1px indicator */ :host([variant="filled"]) .container::before { content: ''; position: absolute; inset-inline: 0; bottom: 0; height: var(--_enabled-active-indicator-height); background-color: var(--_enabled-active-indicator-color); transition: background-color 150ms cubic-bezier(0.2, 0, 0, 1); pointer-events: none; z-index: 1; } :host([variant="filled"]:not([focused]):not(:focus-within):not([disabled]):hover) .container::before { background-color: var(--_hovered-active-indicator-color); } :host([variant="filled"][invalid]:not([disabled])) .container::before { background-color: var(--_invalid-active-indicator-color); } :host([variant="filled"][disabled]) .container::before { background-color: var(--_disabled-active-indicator-color); opacity: var(--_disabled-label-opacity); } /* Filled focus 2px active indicator with smooth scaleX & opacity transition */ :host([variant="filled"]) .container::after { content: ''; position: absolute; inset-inline: 0; bottom: 0; height: var(--_focused-active-indicator-height); background-color: var(--_focused-active-indicator-color); pointer-events: none; z-index: 2; transform: scaleX(0); opacity: 0; transform-origin: center bottom; transition: transform 200ms cubic-bezier(0.2, 0, 0, 1), opacity 150ms cubic-bezier(0.2, 0, 0, 1), background-color 150ms cubic-bezier(0.2, 0, 0, 1); } :host([variant="filled"][focused]) .container::after, :host([variant="filled"]:not([disabled]):focus-within) .container::after { transform: scaleX(1); opacity: 1; } :host([variant="filled"][invalid]) .container::after { background-color: var(--_invalid-active-indicator-color); } :host([variant="filled"][disabled]) .container::after { display: none; } /* ---------- Outlined Variant: Dual-Layer Animated Outline (Zero Layout Shift) ---------- */ :host([variant="outlined"]) .container { background-color: transparent; } /* Outlined resting 1px border */ :host([variant="outlined"]) .container::before { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-sizing: border-box; border: var(--_outline-width) solid var(--_enabled-outline-color); transition: border-color 150ms cubic-bezier(0.2, 0, 0, 1); z-index: 0; } :host([variant="outlined"]:not([focused]):not(:focus-within):not([disabled]):hover) .container::before { border-color: var(--_hovered-outline-color); } :host([variant="outlined"][invalid]) .container::before { border-color: var(--_invalid-outline-color); } :host([variant="outlined"][disabled]) .container::before { border-color: var(--_disabled-outline-color); opacity: var(--_disabled-label-opacity); } /* Outlined focus 2px active border with smooth opacity transition */ :host([variant="outlined"]) .container::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-sizing: border-box; border: 2px solid var(--_focused-outline-color); opacity: 0; transition: opacity 150ms cubic-bezier(0.2, 0, 0, 1), border-color 150ms cubic-bezier(0.2, 0, 0, 1); z-index: 1; } :host([variant="outlined"][focused]) .container::after, :host([variant="outlined"]:not([disabled]):focus-within) .container::after { opacity: 1; } :host([variant="outlined"][invalid]) .container::after { border-color: var(--_invalid-outline-color); } :host([variant="outlined"][invalid][focused]) .container::after, :host([variant="outlined"][invalid]:not([disabled]):focus-within) .container::after { opacity: 1; border-color: var(--_invalid-outline-color); } :host([variant="outlined"][disabled]) .container::after { display: none; } /* ---------- Disabled Host State ---------- */ :host([disabled]) { pointer-events: none; } :host([disabled]) .container { cursor: default; } :host([disabled]) .supporting-wrapper { opacity: var(--_disabled-supporting-text-opacity); } /* ---------- Content area (prefix, input, suffix) ---------- */ .content { flex: 1; min-width: 0; display: flex; align-items: center; height: 100%; box-sizing: border-box; z-index: 2; } /* In filled variant with label, align input text in the lower half of container */ :host([variant="filled"]) .container.has-label .content { padding-top: 24px; padding-bottom: 8px; } :host([variant="filled"]:not(.has-label)) .content, :host([variant="outlined"]) .content { padding-top: 0; padding-bottom: 0; } /* Multiline textarea content padding */ :host([multiline][variant="filled"]) .container.has-label .content { padding-top: 16px; padding-bottom: 4px; } :host([multiline][variant="outlined"]) .content, :host([multiline][variant="filled"]:not(.has-label)) .content { padding-top: 4px; padding-bottom: 4px; } /* ---------- Slotted input / textarea / select reset ---------- */ .input { flex: 1; min-width: 0; display: flex; align-items: center; height: 100%; position: relative; } .input ::slotted(input), .input ::slotted(select) { background: transparent; border: none; outline: none; padding: 0; margin: 0; box-shadow: none; box-sizing: border-box; appearance: none; -webkit-appearance: none; -moz-appearance: none; width: 100%; min-width: 0; height: 24px; line-height: 24px; font-family: var(--_enabled-label-font); font-size: var(--_enabled-label-size); font-weight: var(--_enabled-label-weight); letter-spacing: var(--_enabled-label-tracking); color: inherit; vertical-align: middle; -webkit-tap-highlight-color: transparent; } .input ::slotted(textarea) { background: transparent; border: none; outline: none; padding: 0; margin: 0; box-shadow: none; box-sizing: border-box; appearance: none; -webkit-appearance: none; -moz-appearance: none; width: 100%; min-width: 0; height: 100%; min-height: 24px; line-height: 24px; font-family: var(--_enabled-label-font); font-size: var(--_enabled-label-size); font-weight: var(--_enabled-label-weight); letter-spacing: var(--_enabled-label-tracking); color: inherit; resize: none; -webkit-tap-highlight-color: transparent; } :host([resizable]) .input ::slotted(textarea) { resize: vertical; } .input ::slotted(input:disabled), .input ::slotted(textarea:disabled), .input ::slotted(select:disabled) { cursor: default; pointer-events: none; opacity: var(--_disabled-label-opacity); } /* Slotted Placeholder */ .input ::slotted(input::placeholder), .input ::slotted(textarea::placeholder) { color: var(--_enabled-label-color); opacity: 0.6; transition: opacity 150ms cubic-bezier(0.2, 0, 0, 1); } /* Hide placeholder when label is resting in an empty field */ .container.has-label.resting-label .input ::slotted(input::placeholder), .container.has-label.resting-label .input ::slotted(textarea::placeholder) { opacity: 0; } /* Hide native spinner buttons on number inputs */ .input ::slotted(input[type="number"])::-webkit-inner-spin-button, .input ::slotted(input[type="number"])::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } .input ::slotted(input[type="number"]) { -moz-appearance: textfield; } /* ---------- Leading / Trailing icons ---------- */ .leading, .trailing { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--_enabled-icon-color); z-index: 2; } .leading { width: var(--_leading-icon-size); height: var(--_leading-icon-size); margin-inline-end: 12px; } .trailing { width: var(--_trailing-icon-size); height: var(--_trailing-icon-size); margin-inline-start: 12px; } .container:not(.has-leading-icon) .leading { display: none; } .container:not(.has-trailing-icon) .trailing { display: none; } :host([focused]:not([disabled])) .leading, :host([focused]:not([disabled])) .trailing { color: var(--_focused-icon-color); } :host([invalid]:not([disabled])) .trailing { color: var(--_invalid-icon-color); } :host([disabled]) .leading, :host([disabled]) .trailing { color: var(--_disabled-icon-color); opacity: var(--_disabled-icon-opacity); } /* ---------- Prefix / Suffix (text + slot) ---------- */ .prefix, .suffix { display: inline-flex; align-items: center; flex-shrink: 0; color: var(--_enabled-label-color); font-family: var(--_enabled-label-font); font-size: var(--_enabled-label-size); font-weight: var(--_enabled-label-weight); letter-spacing: var(--_enabled-label-tracking); line-height: 24px; height: 24px; white-space: nowrap; opacity: 1; transition: opacity 150ms cubic-bezier(0.2, 0, 0, 1); } .prefix { padding-inline-start: var(--_prefix-inline-leading-padding-space); padding-inline-end: var(--_prefix-inline-trailing-padding-space); } .suffix { padding-inline-start: var(--_suffix-inline-leading-padding-space); padding-inline-end: var(--_suffix-inline-trailing-padding-space); } .container:not(.has-prefix) .prefix { display: none; } .container:not(.has-suffix) .suffix { display: none; } /* Hide prefix/suffix when label is resting in an empty field */ .container.has-label.resting-label .prefix, .container.has-label.resting-label .suffix { opacity: 0; pointer-events: none; } /* ---------- Floating label & Smooth Expanding Animation ---------- */ .label { position: absolute; inset-inline-start: var(--_container-inline-leading-padding-space); top: 50%; transform: translateY(-50%); transform-origin: top start; pointer-events: auto; cursor: text; color: var(--_enabled-label-color); font-family: var(--_enabled-label-font); font-size: var(--_enabled-label-size); font-weight: var(--_enabled-label-weight); letter-spacing: var(--_enabled-label-tracking); line-height: var(--_enabled-label-line-height); max-width: calc(100% - 32px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; z-index: 3; transition: transform 150ms cubic-bezier(0.2, 0, 0, 1), top 150ms cubic-bezier(0.2, 0, 0, 1), font-size 150ms cubic-bezier(0.2, 0, 0, 1), line-height 150ms cubic-bezier(0.2, 0, 0, 1), color 150ms cubic-bezier(0.2, 0, 0, 1), inset-inline-start 150ms cubic-bezier(0.2, 0, 0, 1), background-color 150ms cubic-bezier(0.2, 0, 0, 1); } /* When there is a leading icon and label is resting, offset label start to match input column */ .container.has-leading-icon.resting-label .label, .container.has-leading-icon:not(.floating-label) .label { inset-inline-start: calc(var(--_container-inline-leading-padding-space) + var(--_leading-icon-size) + 12px); } /* Filled variant floating label */ :host([variant="filled"]) .container.floating-label .label, :host([variant="filled"]) .label.floating, :host([variant="filled"][floating-label-behavior="always"]) .label { top: 8px; transform: translateY(0); inset-inline-start: var(--_container-inline-leading-padding-space); font-family: var(--_floating-label-font); font-size: var(--_floating-label-size); font-weight: var(--_floating-label-weight); letter-spacing: var(--_floating-label-tracking); line-height: var(--_floating-label-line-height); } /* Outlined variant floating label with notch mask */ :host([variant="outlined"]) .container.floating-label .label, :host([variant="outlined"]) .label.floating, :host([variant="outlined"][floating-label-behavior="always"]) .label { top: 0; transform: translateY(-50%); inset-inline-start: 12px; padding-inline: 4px; background-color: var(--mdc-field-label-background, var(--mdc-theme-surface, #ffffff)); font-family: var(--_floating-label-font); font-size: var(--_floating-label-size); font-weight: var(--_floating-label-weight); letter-spacing: var(--_floating-label-tracking); line-height: var(--_floating-label-line-height); border-radius: 2px; } /* Multiline textarea resting label alignment */ :host([multiline]) .container.has-label:not(.floating-label) .label { top: 16px; transform: translateY(0); } /* Label hidden when behavior==='never' and not populated */ :host([floating-label-behavior="never"]:not([populated])) .label { display: none; } /* Label colors across interaction states */ :host(:hover:not([disabled])) .label { color: var(--_hovered-label-color); } :host([focused]:not([disabled])) .label, :host(:not([disabled]):focus-within) .label { color: var(--_focused-label-color); } :host([invalid]:not([disabled])) .label { color: var(--_invalid-label-color); } :host([disabled]) .label { color: var(--_disabled-label-color); opacity: var(--_disabled-label-opacity); } /* Required asterisk */ .required-asterisk { color: var(--_invalid-label-color); } /* ---------- Supporting text / error text / counter row ---------- */ .supporting-wrapper { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; box-sizing: border-box; padding-inline-start: var(--_container-inline-leading-padding-space); padding-inline-end: var(--_container-inline-trailing-padding-space); padding-block-start: 4px; min-height: 16px; font-family: var(--_supporting-text-font); font-size: var(--_supporting-text-size); font-weight: var(--_supporting-text-weight); letter-spacing: var(--_supporting-text-tracking); line-height: var(--_supporting-text-line-height); color: var(--_enabled-supporting-text-color); } .supporting-text { flex: 1; min-width: 0; } .counter { flex-shrink: 0; margin-inline-start: auto; white-space: nowrap; color: var(--_enabled-counter-color); } :host([invalid]:not([disabled])) .supporting-text { color: var(--_invalid-supporting-text-color); } :host([invalid]:not([disabled])) .counter { color: var(--_invalid-counter-color); } /* ---------- Align-end (RTL-aware row reversal) ---------- */ :host([align-end]) .container { flex-direction: row-reverse; } :host([align-end]) .content { flex-direction: row-reverse; } /* ---------- Reduced motion ---------- */ @media (prefers-reduced-motion: reduce) { .container, .container::after, .container::before, .label, .prefix, .suffix { transition: none; } } /* ---------- Forced colors (Windows High Contrast) ---------- */ @media (forced-colors: active) { .container::before { border-color: CanvasText; } :host([disabled]) { opacity: 1; border-color: GrayText; } :host([variant="outlined"]) .label { background-color: Canvas; } } } `,l=e` @layer mdc.field.variant { :host([variant="filled"]) { ${t(o)}; } :host([variant="outlined"]) { ${t(s)}; } } `,u=[c,l];export{c as baseFieldStyles,u as fieldStyles,l as fieldVariantStyles}; //# sourceMappingURL=field.style.js.map