shelving
Version:
Toolkit for using data in JavaScript.
214 lines (187 loc) • 6.26 kB
CSS
@import "../style/base.css";
@layer components {
.input {
/* Identity */
--color-black: var(--input-color-black, inherit);
--color-dark: var(--input-color-dark, inherit);
--color-vivid: var(--input-color-vivid, inherit);
--color-light: var(--input-color-light, inherit);
--color-white: var(--input-color-white, inherit);
/* Box */
box-sizing: border-box;
width: 100%;
margin: var(--input-spacing, var(--space-small)) 0;
border-radius: var(--input-radius, var(--radius-xsmall));
border: var(--input-border, var(--stroke-normal)) solid var(--color-vivid);
padding: var(--input-padding, var(--space-small)) var(--input-padding, var(--space-small));
flex-grow: var(--grow-greedy);
/* Style — Inputs always use the un-variant extremes: `bg=white / text=black` (4 steps apart,
* maximum readability). Variant tints surface as borders and validity colours only. */
color: var(--color-black);
background: var(--color-white);
transition: all 120ms ease-in-out;
cursor: default;
outline: var(--input-border, var(--stroke-focus)) solid transparent;
outline-offset: calc(0px - var(--input-border, var(--stroke-normal)));
box-shadow: none;
/* Typography */
font-family: var(--input-font, var(--font-body));
font-weight: var(--input-weight, var(--weight-normal));
font-size: var(--input-size, var(--size-normal));
line-height: var(--input-leading, var(--leading-normal));
/* Content */
justify-content: start;
align-items: center;
/* Variants. */
&.select {
/* Select inputs have pointer cursor, down arrow image. */
cursor: pointer;
appearance: none;
background-repeat: no-repeat;
background-size: var(--input-icon-size, var(--size-icon));
padding-right: 2.5em;
background-position: right var(--input-padding, var(--space-small)) center;
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iY3VycmVudENvbG9yIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS40NyA0LjcyYS43NS43NSAwIDAgMSAxLjA2IDBsMy43NSAzLjc1YS43NS43NSAwIDAgMS0xLjA2IDEuMDZMMTIgNi4zMSA4Ljc4IDkuNTNhLjc1Ljc1IDAgMCAxLTEuMDYtMS4wNmwzLjc1LTMuNzVabS0zLjc1IDkuNzVhLjc1Ljc1IDAgMCAxIDEuMDYgMEwxMiAxNy42OWwzLjIyLTMuMjJhLjc1Ljc1IDAgMSAxIDEuMDYgMS4wNmwtMy43NSAzLjc1YS43NS43NSAwIDAgMS0xLjA2IDBsLTMuNzUtMy43NWEuNzUuNzUgMCAwIDEgMC0xLjA2WiIgY2xpcC1ydWxlPSJldmVub2RkIiAvPjwvc3ZnPgo=");
/* Placeholder colour if contains checked empty option. */
&:has(.empty:checked) {
color: var(--color-dark);
}
/* Success border if contains a checked value option. */
&:has(.value:checked) {
border-color: var(--vivid-green);
}
}
&.text {
/* Text inputs have text cursor, selection, placeholder. */
cursor: text;
resize: none;
&::selection {
color: var(--color-white);
background-color: var(--color-focus);
}
&::placeholder {
color: var(--color-dark);
}
/* Success border if valid and has content. */
&:valid:not(:placeholder-shown) {
border-color: var(--vivid-green);
}
/* Error border if invalid and not empty. */
&:invalid:not(:placeholder-shown) {
border-color: var(--vivid-red);
}
&.multiline {
/* Textarea has pre-spacing and field-sizing for auto-resizing. */
white-space: pre-wrap;
word-break: break-word;
field-sizing: content;
min-height: calc(1lh * attr(rows number, 2));
}
}
&.button,
&.label {
/* Button and label inputs have a pointer cursor and clip overlong labels. */
cursor: pointer;
overflow: hidden;
white-space: nowrap;
/* Success border if contains a checked control or valid text. */
&:has(.checkbox:checked, .radio:checked, .option:checked, .text:valid:not(:placeholder-shown)) {
border-color: var(--vivid-green);
}
/* Error border if contains invalid text. */
&:has(.text:invalid:not(:placeholder-shown)) {
border-color: var(--vivid-red);
}
}
&.button {
justify-content: center;
}
/* Error if aria invalid or contains aria invalid. */
&[aria-invalid="true"],
&:has([aria-invalid="true"]) {
border-color: var(--vivid-red);
}
/* Important pseudo-classes */
&.disabled,
&:disabled,
&:has(.disabled, :disabled) {
opacity: var(--input-disabled-opacity, 0.5);
cursor: default;
}
&.focus,
&:focus,
&:focus-within,
&:has(.focus) {
border-color: var(--color-focus);
outline-color: var(--color-focus);
}
/* Children */
> .input {
/* Nested inputs don't double up border or padding. */
padding: 0;
border: 0;
margin: 0;
outline: 0;
}
&& > [data-slot="icon"] {
inline-size: var(--input-icon-size, var(--size-icon));
block-size: var(--input-icon-size, var(--size-icon));
flex: none;
}
&.wrapper {
position: relative;
/* Absolutely position any slotted element and center it vertically. */
& > [data-slot] {
position: absolute;
inset-block: 0;
display: flex;
align-items: center;
justify-content: center;
inline-size: calc(var(--input-padding, var(--space-small)) + var(--input-icon-size, var(--size-icon)));
pointer-events: none;
}
/* First [data-slot] child anchors to the left. */
& > [data-slot]:first-child {
inset-inline-start: 0;
}
/* Last [data-slot] child anchors to the right. */
& > [data-slot]:last-child {
inset-inline-end: 0;
}
/* Push the inner .input left padding to clear the left slot. */
&:has(> [data-slot]:first-child) > .input {
padding-inline-start: var(--input-icon-size, var(--size-icon));
}
/* Push the inner .input right padding to clear the right slot. */
&:has(> [data-slot]:last-child) > .input {
padding-inline-end: var(--input-icon-size, var(--size-icon));
}
}
}
.placeholder {
color: var(--color-dark);
}
.checkbox,
.radio {
display: block;
width: calc(var(--input-icon-size, var(--size-icon)) - 4px);
height: calc(var(--input-icon-size, var(--size-icon)) - 4px);
margin: 2px;
flex: 0 0 auto;
accent-color: var(--color-vivid);
cursor: inherit;
outline: none;
font-size: inherit;
line-height: inherit;
}
}
@layer overrides {
.input {
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
}