Files
sendou.ink/app/components/elements/Select.module.css
2026-09-17 17:34:36 +03:00

255 lines
5.2 KiB
CSS

.select {
width: 100%;
position: relative;
display: flex;
flex-direction: column;
gap: var(--s-1-5);
}
.label {
font-size: var(--font-xs);
font-weight: var(--weight-bold);
margin: 0;
display: block;
text-box: trim-start cap alphabetic;
}
.button {
height: var(--field-size);
padding: 0 var(--field-padding);
border: var(--border-style);
border-radius: var(--radius-field);
background-color: var(--color-bg);
outline: none;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s-1-5);
width: 100%;
cursor: pointer;
text-align: start;
transition: background-color 0.15s;
&:hover:not(:disabled),
&:focus-visible {
background-color: var(--color-bg-high);
}
&:focus-visible,
&[aria-expanded="true"] {
outline: var(--focus-ring);
outline-offset: 1px;
}
&:disabled {
pointer-events: none;
cursor: not-allowed;
opacity: 0.5;
outline: none;
}
}
.selectValue {
font-size: var(--font-sm);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
color: var(--color-text);
display: flex;
align-items: center;
gap: var(--s-2);
&[data-placeholder] {
color: var(--color-text-high);
}
/* two-line items render only their label line inside the trigger */
& [slot="description"] {
display: none;
}
}
.icon {
min-width: 18px;
max-width: 18px;
color: var(--color-text-high);
}
.popover {
position: fixed;
position-area: block-end;
width: anchor-size(width);
min-width: anchor-size(width);
/* fills the space the position-area leaves (its containing block), less the
gap to the anchor (the popover's own margin) and the padding to the
viewport edge; which side that space is on gets pinned when the popover
opens, which also sets the cap in pixels as WebKit does not resolve this
percentage */
max-height: calc(100% - var(--s-2) - 12px);
margin: var(--s-2) 0;
padding: var(--s-1);
border: var(--border-style);
border-radius: var(--radius-box);
background-color: var(--color-bg);
outline: none;
color: var(--color-text);
display: none;
flex-direction: column;
&:popover-open {
display: flex;
}
/* opened upwards the sticky header is the ceiling, not the viewport top */
&[data-side="above"] {
max-height: calc(100% - var(--s-2) - 12px - var(--popover-boundary-top));
}
}
.listBox {
overflow: auto;
flex: 1 1 auto;
outline: none;
}
.item {
font-size: var(--font-sm);
font-weight: var(--weight-semi);
padding: var(--s-1-5);
border-radius: var(--radius-field);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
outline: none;
/* long lists (every weapon) skip laying out and painting the options
scrolled out of view, keeping them in the accessibility tree; the skipped
ones must still be exactly as tall as the rendered ones or the list jumps
while scrolling, and as engines disagree on whether the intrinsic size
includes the padding, the height is pinned with a min-height instead */
content-visibility: auto;
--option-content-height: calc(var(--font-sm) * var(--line-height));
min-block-size: calc(var(--option-content-height) + 2 * var(--s-1-5));
&[data-disabled] {
color: var(--color-text-high);
cursor: not-allowed;
}
}
.itemFocused {
background-color: var(--color-bg-high);
color: var(--color-text);
}
.itemSelected {
color: var(--color-text-accent);
font-weight: var(--weight-bold);
}
.searchField {
position: relative;
display: flex;
gap: var(--s-2);
border-bottom: 1px solid var(--color-border);
border-radius: 0;
accent-color: var(--color-accent);
color: var(--color-text);
outline: none;
padding: var(--s-1-5) var(--s-1-5) calc(var(--s-0-5) + var(--s-2))
var(--s-1-5);
margin-block-end: var(--s-1-5);
}
.searchInput {
all: unset;
font-size: var(--font-xs);
font-weight: var(--weight-semi);
letter-spacing: 0.5px;
flex: 1;
min-width: 0;
padding-inline-end: calc(18px + var(--s-2));
&::-webkit-search-cancel-button {
display: none;
}
&::placeholder {
color: var(--color-text-high);
}
}
.searchClearButton {
position: absolute;
right: var(--s-2);
top: 50%;
transform: translateY(-50%);
background-color: transparent;
border: none;
padding: 0;
cursor: pointer;
color: var(--color-text-high);
transition: color 0.15s;
&:hover,
&:focus-visible {
color: var(--color-text);
}
}
.searchField[data-empty] .searchClearButton {
visibility: hidden;
}
.noResults {
font-size: var(--font-md);
font-weight: var(--weight-bold);
text-align: center;
padding-block: var(--s-8);
color: var(--color-text-high);
}
.clearButton {
position: absolute;
bottom: -21px;
right: 9px;
height: 18px;
&:focus-visible {
outline-offset: 2px;
border-radius: 6px;
}
}
.categoryHeading {
display: flex;
align-items: center;
gap: var(--s-2);
font-weight: var(--weight-extra);
color: var(--color-text-high);
text-transform: uppercase;
font-size: var(--font-2xs);
padding-block-start: var(--s-3);
padding-block-end: var(--s-1);
padding-inline: var(--s-1-5);
white-space: nowrap;
& img {
border-radius: 100%;
background-color: var(--color-bg-higher);
padding: var(--s-1);
min-width: 28px;
}
}
.categoryDivider {
background-color: var(--color-border);
width: 100%;
height: 2px;
margin-block: var(--s-2);
}