Files
WRNexusJS/packages/ui/components/DatePicker.wrn
T
ClintchizandClaude Opus 5.5 1bed8e4b74 feat(ui): component redesign pass and fixes, release ui 0.8.87
Redesign
- Shared field foundation rules (duplicated across 15 form components and
  emitted globally) are now identical everywhere, so later copies no longer
  silently override earlier redesigns.
- Drawn checkbox and radio controls, white switch thumbs (the thumb was the
  text colour, a black blob in light mode), recessed field wells, keycap
  actions in Modal, Drawer, Popover, Toaster, Pagination, Stepper, DataTable.
- Menus (Dropdown, ContextMenu, Popover, Select dropdown, Navbar panels) share
  one flat raised panel with neutral hover rows and mono section labels.
- Alerts with an accent rail and icon chip; card headers without the grey
  band; accordion, collapse, list, list group, timeline, stats, metrics,
  chat, skeleton, avatar group, clipboard, splitter, section, sidebar,
  navbar and upload progress restyled.
- Chart rebuilt: nice y-axis ticks, gridlines, rounded bars, line and area
  modes, hover tooltips, hidden series leave the scale.

Fixes
- Checkbox and radio labels toggle their input again (empty for="" broke it).
- TimePicker kept every clicked time pressed; only the chosen hour and
  minute are pressed now, and nothing is pressed before a value exists.
- ColorPicker hex readout now follows the picked colour.
- Disabled FileInput no longer shows the native file-input text.
- Date and time panels float instead of pushing content.
- ContextMenu opened at the pointer closes on scroll.
- Drawer left/top/bottom placements slide from their own edge again.
- Image-only Card no longer renders an empty body strip.
- Timeline supports item.time, current/upcoming states, sizes and
  compact/alternate variants; showcase demos use distinct variants.
- ChatBubble: delivery receipts (sending/sent/delivered/read/failed/error)
  and meta aligned to its bubble.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:18:13 +05:30

883 lines
38 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import TimePicker from "./TimePicker.wrn"
component DatePicker {
outputs {
input(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
change(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
open(payload: { value: string; name: string; sourceEvent: Event })
close(payload: { value: string; name: string; sourceEvent: Event })
focus(payload: { value: string; name: string; sourceEvent: Event })
blur(payload: { value: string; name: string; sourceEvent: Event })
invalid(payload: { name: string; message: string; sourceEvent: Event })
}
props {
size: string = "default"
color: string = "primary"
label: string = "Date Picker"
id: string = ""
name: string = ""
value: string = ""
placeholder: string = ""
type: string = "date"
locale: string = "en-US"
firstDayOfWeek: number = 0
months: { label: string; value: string }[] = [{ label: "Jan", value: "01" }, { label: "Feb", value: "02" }, { label: "Mar", value: "03" }, { label: "Apr", value: "04" }, { label: "May", value: "05" }, { label: "Jun", value: "06" }, { label: "Jul", value: "07" }, { label: "Aug", value: "08" }, { label: "Sep", value: "09" }, { label: "Oct", value: "10" }, { label: "Nov", value: "11" }, { label: "Dec", value: "12" }]
days: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
years: number[] = [2024, 2025, 2026, 2027, 2028, 2029, 2030]
min: string = ""
max: string = ""
step: string = ""
helperText: string = ""
cornerHint: string = ""
error: string = ""
variant: string = "normal"
inline: boolean = false
readonly: boolean = false
disabled: boolean = false
required: boolean = false
class: string = ""
}
state currentValue = value
state selectedYear = value ? value.split("-")[0] : String(new Date().getFullYear())
state selectedMonth = value ? value.split("-")[1] : String(new Date().getMonth() + 1).padStart(2, "0")
state selectedDay = value ? value.slice(8, 10) : ""
state selectedTime = value.includes("T") ? value.split("T")[1].slice(0, 5) : "09:00"
state expanded: boolean = false
functions {
client function updateTime(sourceEvent) {
selectedTime = sourceEvent.currentTarget.value
currentValue = (currentValue ? currentValue.slice(0, 10) : selectedYear + "-" + selectedMonth + "-01") + "T" + selectedTime
output.input({ value: currentValue, name: name, sourceEvent: sourceEvent })
output.change({ value: currentValue, name: name, sourceEvent: sourceEvent })
}
shared function calendarYears() {
if (years.includes(Number(selectedYear))) { return years }
return years.concat(Number(selectedYear))
}
shared function weekdayName(index, first) {
first = ((firstDayOfWeek % 7) + 7) % 7
return Intl.DateTimeFormat(locale, { weekday: "short", timeZone: "UTC" }).format(Date.UTC(2024, 0, 7 + first + index))
}
shared function weekdays() { return [0, 1, 2, 3, 4, 5, 6].map(weekdayName) }
shared function validDay(day, year, leap, count) {
year = Number(selectedYear)
leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
count = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][Number(selectedMonth) - 1]
return Number(day) >= 1 && Number(day) <= count
}
shared function dayView(day, year, month, first, offset, date, today) {
year = Number(selectedYear)
month = Number(selectedMonth)
first = ((firstDayOfWeek % 7) + 7) % 7
offset = ((Math.floor(Date.UTC(year, month - 1, 1) / 86400000) + 4) % 7 - first + 7) % 7
date = selectedYear + "-" + selectedMonth + "-" + String(day).padStart(2, "0")
today = Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit" }).format(Date.now())
return { day: day, value: date, column: ((offset + Number(day) - 1) % 7) + 1, disabled: disabled || readonly || !!(min && date < min.slice(0, 10)) || !!(max && date > max.slice(0, 10)), today: date === today, label: Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(Date.UTC(year, month - 1, Number(day))) }
}
shared function calendarDays() { return days.filter(validDay).map(dayView) }
client function openCalendar(sourceEvent) {
if (disabled || readonly) { return }
expanded = !expanded
syncCalendarSelectors(sourceEvent)
if (expanded) { output.open({ value: currentValue, name: name, sourceEvent: sourceEvent }) }
else { output.close({ value: currentValue, name: name, sourceEvent: sourceEvent }) }
}
client function updateDate(part, nextValue, sourceEvent) {
if (disabled || readonly) { return }
if (part === "year") { selectedYear = String(nextValue) }
if (part === "month") { selectedMonth = String(nextValue).padStart(2, "0") }
syncCalendarSelectors(sourceEvent)
}
client function syncCalendarSelectors(sourceEvent) {
var root = sourceEvent.currentTarget.closest(".wrn-next--date-picker")
setTimeout(applyCalendarSelectors, 0, root)
}
client function applyCalendarSelectors(root) {
var selectors = root.querySelectorAll(".wrn-next__date-selectors select")
selectors[0].value = selectedMonth
selectors[1].value = selectedYear
}
client function finishDate(sourceEvent) {
var root = sourceEvent.currentTarget.closest(".wrn-next--date-picker")
root.querySelector(".wrn-next__date-trigger").focus()
expanded = false
output.close({ value: currentValue, name: name, sourceEvent: sourceEvent })
}
client function selectDay(sourceEvent) {
if (disabled || readonly || sourceEvent.currentTarget.disabled) { return }
var nextDate = sourceEvent.currentTarget.dataset.value
if ((min && nextDate < min.slice(0, 10)) || (max && nextDate > max.slice(0, 10))) { return }
currentValue = nextDate + (type === "datetime-local" ? "T" + selectedTime : "")
selectedDay = nextDate.slice(8)
syncCalendarSelectors(sourceEvent)
var detail = { value: currentValue, year: selectedYear, month: selectedMonth, day: selectedDay, name: name, sourceEvent: sourceEvent }
output.input(detail)
output.change(detail)
}
client function calendarKeydown(sourceEvent) {
if (sourceEvent.key === "Escape" && expanded) { sourceEvent.preventDefault(); finishDate(sourceEvent); return }
var keys = { ArrowRight: 1, ArrowLeft: -1, ArrowDown: 7, ArrowUp: -7 }
if (!keys[sourceEvent.key] || !sourceEvent.target.closest(".wrn-next__calendar-grid")) { return }
sourceEvent.preventDefault()
var root = sourceEvent.currentTarget
var buttons = Array.from(root.querySelectorAll(".wrn-next__calendar-grid button"))
var index = buttons.indexOf(sourceEvent.target) + keys[sourceEvent.key]
while (index >= 0 && index < buttons.length && buttons[index].disabled) { index += keys[sourceEvent.key] > 0 ? 1 : -1 }
if (buttons[index]) { buttons[index].focus() }
}
client function clearDate(sourceEvent) {
if (disabled || readonly) { return }
currentValue = ""
selectedDay = ""
var detail = { value: currentValue, name: name, sourceEvent: sourceEvent }
output.input(detail)
output.change(detail)
}
client function handleFocus(sourceEvent) { output.focus({ value: currentValue, name: name, sourceEvent: sourceEvent }) }
client function handleBlur(sourceEvent) { output.blur({ value: currentValue, name: name, sourceEvent: sourceEvent }) }
client function handleInvalid(sourceEvent) { output.invalid({ name: name, message: sourceEvent.currentTarget.validationMessage, sourceEvent: sourceEvent }) }
}
view {
<div {...attrs} class="wrn-component wrn-component--color-{color} wrn-component--size-{size} wrn-next--field wrn-next--date-picker {class}" data-variant="{variant}" data-inline="{inline}" data-invalid="{error ? 'true' : 'false'}" data-expanded="{expanded}" @keydown="calendarKeydown(event)">
<div class="wrn-next__field-heading"><label for="{id || name}">{label}</label>{#if cornerHint}<span class="wrn-next__field-hint">{cornerHint}</span>{/if}</div>
<div class="wrn-next__picker-control"><input id="{id || name}" class="wrn-next__sr-only wrn-next__picker-value" type="text" name="{name}" value="{currentValue}" required="{required}" readonly aria-hidden="true" tabindex="-1" @invalid="handleInvalid(event)" /><button type="button" class="wrn-next__date-trigger" aria-label="{label}" disabled="{disabled || readonly}" aria-haspopup="dialog" aria-expanded="{expanded}" @click="openCalendar(event)" @focus="handleFocus(event)" @blur="handleBlur(event)"><span>{currentValue || placeholder || "Select date"}</span><i class="icon-[lucide--calendar-days]" aria-hidden="true"></i></button>{#if currentValue && !readonly && !disabled}<button type="button" class="wrn-next__picker-clear" aria-label="Clear date" @click="clearDate(event)">×</button>{/if}</div>
<button type="button" class="wrn-picker-dismiss" aria-label="Close calendar" data-show="expanded" @click="finishDate(event)"></button><div data-show="expanded" class="wrn-next__calendar" role="dialog" aria-label="{label}"><div class="wrn-next__date-selectors"><label>Month<select value="{selectedMonth}" @change="updateDate('month', event.currentTarget.value, event)">{#each months as month}<option value="{month.value}" selected="{month.value === selectedMonth}">{month.label}</option>{/each}</select></label><label>Year<select value="{selectedYear}" @change="updateDate('year', event.currentTarget.value, event)">{#each calendarYears() as calendarYear}<option value="{calendarYear}" selected="{String(calendarYear) === selectedYear}" data-text="calendarYear"></option>{/each}</select></label></div><div class="wrn-next__calendar-weekdays" aria-hidden="true">{#each weekdays() as weekday}<span>{weekday}</span>{/each}</div><div class="wrn-next__calendar-grid">{#each calendarDays() as day}<button type="button" data-value="{day.value}" data-today="{day.today}" style="grid-column: {day.column}" disabled="{day.disabled}" aria-label="{day.label}" aria-pressed="{day.value === currentValue.slice(0, 10)}" @click="selectDay(event)">{day.day}</button>{/each}</div>{#if type === "datetime-local"}<TimePicker label="Time" value="{selectedTime}" @change="selectedTime = payload.value; currentValue = (currentValue ? currentValue.slice(0, 10) : selectedYear + '-' + selectedMonth + '-01') + 'T' + selectedTime; output.change({ value: currentValue, name: name })" />{/if}<button type="button" class="wrn-next__date-done" disabled="{!currentValue}" @click="finishDate(event)">Done</button></div>
{#if helperText}<small class="wrn-next__field-help">{helperText}</small>{/if}<small class="wrn-next__field-error" data-error="{name}">{error}</small>
</div>
}
style {
.wrn-picker-dismiss { position:fixed; inset:0; z-index:39; opacity:0; cursor:default; border:0; }
.wrn-next__picker-clear {
position: absolute;
right: 2.5rem;
display: inline-grid;
place-items: center;
width: 1.375rem;
height: 1.375rem;
padding: 0;
border: 0;
border-radius: 999px;
background: transparent;
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-size: 1rem;
line-height: 1;
cursor: pointer;
}
.wrn-next__date-selectors {
display: grid;
grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
gap: 0.5rem;
}
.wrn-next__date-selectors label {
display: grid;
gap: 0.25rem;
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-family: var(--wrn-font-mono, monospace);
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.wrn-next__date-selectors select {
appearance: none;
width: 100%;
min-height: 2.125rem;
padding: 0.375rem 1.75rem 0.375rem 0.625rem;
border: 1px solid var(--wrn-color-input-border, var(--wrn-color-border));
border-radius: calc(var(--wrn-radius-sm) - 2px);
background: var(--wrn-color-input-background, var(--wrn-color-surface)) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23888' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E") right 0.5rem center / 0.875rem no-repeat;
color: var(--wrn-color-text);
font: inherit;
font-family: var(--wrn-font-sans, inherit);
font-size: 0.8125rem;
font-weight: 600;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
}
.wrn-next__date-done {
min-height: 2.25rem;
border: 1px solid color-mix(in srgb, var(--wrn-field-color) 82%, black) !important;
border-bottom-color: color-mix(in srgb, var(--wrn-field-color) 64%, black) !important;
background: linear-gradient(180deg, color-mix(in srgb, var(--wrn-field-color) 92%, white), var(--wrn-field-color)) !important;
box-shadow: var(--wrn-highlight-edge, none);
color: var(--wrn-color-primary-contrast, #fff) !important;
font-weight: 600;
}
.wrn-next__calendar > header {
display: grid;
grid-template-columns: 2.25rem 1fr 2.25rem;
align-items: center;
text-align: center;
}
.wrn-next__calendar-grid button[data-outside="true"] {
color: var(--wrn-color-muted);
opacity: 0.55;
}
.wrn-next__calendar-grid button[data-today="true"] {
box-shadow: none;
color: var(--wrn-color-primary-text, var(--wrn-field-color));
font-weight: 700;
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: 0.3em;
}
.wrn-next__calendar-grid button:disabled { opacity: 0.35; cursor: not-allowed; }
.wrn-next__calendar-grid button:not(:disabled):focus-visible { outline: 2px solid var(--wrn-field-color); outline-offset: 1px; }
.wrn-next__calendar-weekdays {
padding-bottom: 0.375rem;
border-bottom: 1px solid var(--wrn-color-border);
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-family: var(--wrn-font-mono, monospace);
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
/* Shared component foundation. */
.wrn-component {
--wrn-component-color: var(--wrn-color-primary);
--wrn-component-scale: 1;
margin: 0;
color: var(--wrn-color-text);
font-family: var(--wrn-font-sans, inherit);
}
.wrn-component--color-primary {
--wrn-component-color: var(--wrn-color-primary);
}
.wrn-component--color-secondary {
--wrn-component-color: var(--wrn-color-secondary);
}
.wrn-component--color-success {
--wrn-component-color: var(--wrn-color-success);
}
.wrn-component--color-warning {
--wrn-component-color: var(--wrn-color-warning);
}
.wrn-component--color-danger {
--wrn-component-color: var(--wrn-color-danger);
}
.wrn-component--color-info {
--wrn-component-color: var(--wrn-color-info);
}
.wrn-component--size-xs {
--wrn-component-scale: 0.78;
}
.wrn-component--size-sm {
--wrn-component-scale: 0.88;
}
.wrn-component--size-default,
.wrn-component--size-md {
--wrn-component-scale: 1;
}
.wrn-component--size-lg {
--wrn-component-scale: 1.14;
}
.wrn-component--size-xl {
--wrn-component-scale: 1.28;
}
.wrn-component:not(.wrn-btn) {
font-size: calc(1em * var(--wrn-component-scale));
}
.wrn-component :is(a, button, input, select, textarea):focus-visible {
outline-color: var(--wrn-component-color);
}
.wrn-component p {
margin: 0;
color: var(--wrn-color-text-muted, var(--wrn-color-muted));
line-height: 1.6;
}
/* Shared field foundation. */
/* Validation states set by the browser validation runtime. */
.wrn-invalid {
border-color: var(--wrn-color-danger) !important;
}
.wrn-field-error {
display: block;
min-height: 1em;
margin-top: 0.25rem;
color: var(--wrn-color-danger-text, var(--wrn-color-danger));
font-size: 0.78rem;
font-weight: 550;
}
.wrn-next--choice {
display: inline-flex;
align-items: center;
gap: 0.55rem;
cursor: pointer;
}
.wrn-next--choice input {
width: 1.1rem;
height: 1.1rem;
accent-color: var(--wrn-color-primary);
}
.wrn-next--field {
display: grid;
width: min(100%, 28rem);
gap: 0.4rem;
font-size: 0.78rem;
font-weight: 700;
}
.wrn-next--field :where(input, textarea, select) {
width: 100%;
min-height: var(--wrn-control-height, 2.5rem);
padding: 0.5rem 0.75rem;
border: 1px solid var(--wrn-color-input-border, var(--wrn-color-border));
border-radius: var(--wrn-radius-sm, 8px);
outline: 0;
color: var(--wrn-color-text);
background: var(--wrn-color-input-background, var(--wrn-color-surface));
font: inherit;
font-weight: 500;
transition: border-color var(--wrn-motion-fast) var(--wrn-ease-standard), box-shadow var(--wrn-motion-fast) var(--wrn-ease-standard), background-color var(--wrn-motion-fast) var(--wrn-ease-standard);
}
.wrn-auth-form form > .wrn-next--field,
.wrn-auth-form form > .wrn-field {
width: 100%;
max-width: none;
}
.wrn-auth-form__submit > .wrn-btn {
width: 100%;
min-height: var(--wrn-control-height, 2.5rem);
border-radius: var(--wrn-radius-sm, 6px);
box-shadow: none;
}
.wrn-next--field :where(input, textarea, select):focus-visible {
border-color: var(--wrn-field-color, var(--wrn-color-primary));
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.04), 0 0 0 3px color-mix(in srgb, var(--wrn-field-color, var(--wrn-color-primary)) 18%, transparent);
}
.wrn-next--field textarea {
resize: vertical;
}
.wrn-next--field,
.wrn-next--choice-field {
--wrn-field-color: var(--wrn-component-color, var(--wrn-color-primary));
width: min(100%, 34rem);
min-width: 0;
color: var(--wrn-color-text);
font-size: 0.8125rem;
font-weight: 500;
}
.wrn-next--field.wrn-next--size-sm,
.wrn-next--choice-field.wrn-next--size-sm {
font-size: 0.8125rem;
}
.wrn-next--field.wrn-next--size-lg,
.wrn-next--choice-field.wrn-next--size-lg {
font-size: 1rem;
}
.wrn-next__field-heading {
display: flex;
min-width: 0;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
}
.wrn-next__field-heading label {
color: var(--wrn-color-text);
font-size: 0.8125rem;
font-weight: 600;
line-height: 1.35;
letter-spacing: -0.005em;
}
.wrn-next__field-hint,
.wrn-next__field-help {
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-size: 0.75rem;
font-weight: 450;
line-height: 1.45;
}
.wrn-next__field-control {
position: relative;
min-width: 0;
}
.wrn-next__field-control > :is(input, textarea, select) {
padding-inline: 0.85rem;
border-color: var(--wrn-color-input-border, var(--wrn-color-border));
border-radius: var(--wrn-radius-sm);
background: var(--wrn-color-input-background, var(--wrn-color-surface));
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.04);
font-size: 0.875rem;
}
.wrn-next__field-control[data-has-icon="true"][data-icon-position="start"] > :is(input, textarea, select) {
padding-inline-start: 2.5rem;
}
.wrn-next__field-control[data-has-icon="true"][data-icon-position="end"] > :is(input, textarea, select) {
padding-inline-end: 2.5rem;
}
.wrn-next__field-icon {
position: absolute;
z-index: 1;
top: 50%;
left: 0.85rem;
color: var(--wrn-color-muted);
pointer-events: none;
transform: translateY(-50%);
}
.wrn-next__field-control[data-icon-position="end"] > .wrn-next__field-icon {
right: 0.85rem;
left: auto;
}
.wrn-next--field[data-variant="outlined"]
.wrn-next__field-control
> :is(input, textarea, select) {
border-width: 2px;
}
.wrn-next--field[data-variant="underline"]
.wrn-next__field-control
> :is(input, textarea, select) {
padding-inline: 0;
border-width: 0 0 1px;
border-radius: 0;
background: transparent;
box-shadow: none;
}
.wrn-next--field[data-variant="pill"] .wrn-next__field-control > :is(input, select) {
border-radius: 999px;
padding-inline: 1.15rem;
}
.wrn-next--field[data-variant="ghost"] .wrn-next__field-control > :is(input, textarea, select) {
border-color: transparent;
background: color-mix(in srgb, var(--wrn-field-color) 6%, var(--wrn-color-surface-soft, var(--wrn-color-surface)));
box-shadow: none;
}
.wrn-next__field-floating-label {
position: absolute;
top: 50%;
left: 0.85rem;
color: var(--wrn-color-muted);
pointer-events: none;
transform: translateY(-50%);
transition: 150ms ease;
}
.wrn-next--textarea .wrn-next__field-floating-label {
top: 1.35rem;
}
.wrn-next--field[data-floating="true"] .wrn-next__field-control > :is(input, textarea, select) {
padding-top: 1.2rem;
padding-bottom: 0.3rem;
}
.wrn-next--field[data-floating="true"] .wrn-next__field-heading > label {
position: absolute !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
margin: -1px !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
}
.wrn-next--field[data-floating="true"]
.wrn-next__field-heading:not(:has(.wrn-next__field-hint)) {
display: none;
}
.wrn-next--field[data-floating="true"]
.wrn-next__field-control
> :is(input, textarea):is(:focus, :not(:placeholder-shown))
+ .wrn-next__field-floating-label {
top: 0.42rem;
font-size: 0.7em;
transform: none;
}
.wrn-next__field-error {
min-height: 1em;
color: var(--wrn-color-danger-text, var(--wrn-color-danger));
font-size: 0.78rem;
font-weight: 550;
}
.wrn-next__field-error:empty {
display: none;
}
.wrn-next--field[data-invalid="true"] :is(input, textarea, select),
.wrn-next--choice-field[data-invalid="true"] input {
border-color: var(--wrn-color-danger);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--wrn-color-danger) 12%, transparent);
}
.wrn-next--field :is(input, textarea, select):disabled,
.wrn-next--choice-field input:disabled {
cursor: not-allowed;
opacity: 0.55;
background: var(--wrn-color-surface-soft, var(--wrn-color-surface-2));
}
.wrn-next--field :is(input, textarea, select):read-only {
background: var(--wrn-color-surface-soft, var(--wrn-color-surface-2));
}
.wrn-next--field[data-inline="true"],
.wrn-next--choice-field[data-inline="true"] {
display: grid;
width: 100%;
max-width: none;
grid-template-columns: minmax(7rem, max-content) minmax(12rem, 20rem) minmax(10rem, 1fr);
justify-content: center;
align-items: center;
gap: 0.75rem;
}
.wrn-next--field[data-inline="true"] .wrn-next__field-heading,
.wrn-next--choice-field[data-inline="true"] .wrn-next__field-heading {
min-height: var(--wrn-control-height, 2.5rem);
align-items: center;
}
.wrn-next--field[data-inline="true"] .wrn-next__field-heading {
justify-content: flex-end;
}
.wrn-next--field[data-inline="true"] .wrn-next__field-help,
.wrn-next--choice-field[data-inline="true"] .wrn-next__field-help {
display: flex;
min-height: var(--wrn-control-height, 2.5rem);
align-items: center;
}
.wrn-next--choice-field[data-inline="true"] {
grid-template-columns: minmax(12rem, 20rem) minmax(10rem, 1fr);
}
.wrn-next--choice-field[data-inline="true"] .wrn-next__field-heading:empty {
display: none;
}
.wrn-next--field[data-inline="true"] .wrn-next__field-error,
.wrn-next--choice-field[data-inline="true"] .wrn-next__field-error {
grid-column: 2 / -1;
}
.wrn-next__sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
border: 0 !important;
margin: -1px !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
}
.wrn-next__choice-field {
display: grid;
width: 100%;
max-width: none;
gap: 0.4rem;
}
.wrn-next__choice {
display: flex;
min-width: 0;
align-items: center;
gap: 0.625rem;
color: var(--wrn-color-text);
width: 100%;
font-size: 0.875rem;
font-weight: 500;
line-height: 1.4;
cursor: pointer;
}
.wrn-next__checkbox-content > .wrn-next__choice {
width: 100%;
min-width: 0;
align-items: flex-start;
}
.wrn-next__choice input {
flex: 0 0 auto;
margin: 0;
accent-color: var(--wrn-field-color);
}
.wrn-next__choice-copy {
display: grid;
min-width: 0;
gap: 0.125rem;
line-height: 1.4;
}
.wrn-next__choice-copy small {
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-size: 0.78rem;
font-weight: 450;
}
.wrn-next__radio-group,
.wrn-next__checkbox-group {
display: grid;
min-width: 0;
gap: 0.65rem;
}
.wrn-next--radio-field[data-orientation="horizontal"] .wrn-next__radio-group,
.wrn-next--checkbox-field[data-orientation="horizontal"] .wrn-next__checkbox-group {
grid-template-columns: repeat(auto-fit, minmax(8rem, max-content));
align-items: stretch;
}
.wrn-next--radio-field[data-card="true"] .wrn-next__radio-group,
.wrn-next--checkbox-field[data-card="true"] .wrn-next__checkbox-group {
grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
}
.wrn-next--radio-field[data-card="true"] .wrn-next--radio,
.wrn-next--checkbox-field[data-card="true"] .wrn-next--checkbox {
min-height: 4.5rem;
padding: 0.9rem 1rem;
border: 1px solid var(--wrn-color-border);
border-radius: var(--wrn-radius);
background: var(--wrn-color-surface);
box-shadow: var(--wrn-shadow-1);
transition: border-color var(--wrn-motion-fast) var(--wrn-ease-standard), box-shadow var(--wrn-motion-fast) var(--wrn-ease-standard), background-color var(--wrn-motion-fast) var(--wrn-ease-standard);
}
.wrn-next--radio-field[data-card="true"] .wrn-next--radio:has(input:checked),
.wrn-next--checkbox-field[data-card="true"] .wrn-next--checkbox:has(input:checked) {
border-color: var(--wrn-field-color);
background: color-mix(in srgb, var(--wrn-field-color) 5%, var(--wrn-color-surface));
box-shadow: 0 0 0 1px var(--wrn-field-color), var(--wrn-shadow-1);
}
.wrn-next--radio-field[data-list="true"] .wrn-next--radio,
.wrn-next--checkbox-field[data-list="true"] .wrn-next--checkbox {
padding-block: 0.75rem;
border-bottom: 1px solid var(--wrn-color-border);
}
.wrn-next--radio-field[data-right-aligned="true"] .wrn-next--radio,
.wrn-next--checkbox-field[data-right-aligned="true"] .wrn-next--checkbox {
justify-content: space-between;
}
.wrn-next--radio-field[data-right-aligned="true"] .wrn-next--radio input,
.wrn-next--checkbox-field[data-right-aligned="true"] .wrn-next--checkbox input {
order: 2;
}
.wrn-next--radio-field[data-right-aligned="true"] .wrn-next__choice-copy,
.wrn-next--checkbox-field[data-right-aligned="true"] .wrn-next__choice-copy {
order: 1;
}
.wrn-next__choice[data-variant="outlined"],
.wrn-next__choice[data-variant="floating"] {
padding: 0.7rem 0.85rem;
border: 1px solid var(--wrn-color-border);
border-radius: var(--wrn-radius-sm);
background: var(--wrn-color-surface);
}
.wrn-next__choice[data-variant="pill"] {
padding: 0.6rem 1rem;
border: 1px solid color-mix(in srgb, var(--wrn-field-color) 22%, var(--wrn-color-border));
border-radius: 999px;
background: color-mix(in srgb, var(--wrn-field-color) 6%, var(--wrn-color-surface));
}
.wrn-next__choice[data-variant="ghost"] {
padding: 0.65rem 0.85rem;
border-radius: var(--wrn-radius-sm);
background: color-mix(in srgb, var(--wrn-field-color) 6%, transparent);
}
.wrn-next__choice[data-variant="underline"] {
padding-block: 0.5rem;
border-bottom: 1px solid var(--wrn-color-border);
}
.wrn-next--select .wrn-next__field-control {
display: flex;
align-items: center;
}
.wrn-next__color-control,
.wrn-next__range-control,
.wrn-next__input-group-control,
.wrn-next__file-control {
display: flex;
min-width: 0;
align-items: center;
gap: 0.65rem;
}
.wrn-next__picker-control,
.wrn-next--time-picker .wrn-next__field-control {
position: relative;
display: flex;
min-width: 0;
align-items: center;
}
.wrn-next__picker-control > button:first-of-type,
.wrn-next__time-trigger {
display: flex;
width: 100%;
min-height: var(--wrn-control-height, 2.5rem);
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.55rem 0.85rem;
border: 1px solid var(--wrn-color-input-border, var(--wrn-color-border));
border-radius: var(--wrn-radius-sm);
background: var(--wrn-color-input-background, var(--wrn-color-surface));
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.04);
color: var(--wrn-color-text);
font: inherit;
font-size: 0.875rem;
font-variant-numeric: tabular-nums;
text-align: left;
cursor: pointer;
transition: border-color 120ms ease, box-shadow 120ms ease;
}
.wrn-next--date-picker, .wrn-next--time-picker { position: relative; }
.wrn-next__calendar,
.wrn-next__time-panel {
position: absolute;
z-index: 40;
top: 100%;
left: 0;
display: grid;
width: min(calc(100vw - 2rem), 19.5rem);
gap: 0.75rem;
margin-top: 0.375rem;
padding: 0.75rem;
border: 1px solid var(--wrn-color-border);
border-radius: var(--wrn-radius);
background: var(--wrn-color-surface-raised, var(--wrn-color-surface));
box-shadow: var(--wrn-highlight-edge, none), var(--wrn-shadow-3);
animation: wrn-popover-enter var(--wrn-motion-base, 160ms) var(--wrn-ease-emphasized, ease) both;
}
.wrn-next--date-picker[data-expanded="false"] .wrn-next__calendar,
.wrn-next--time-picker[data-expanded="false"] .wrn-next__time-panel {
display: none;
}
.wrn-next__calendar button,
.wrn-next__time-panel button {
min-height: 2.25rem;
border: 0;
border-radius: calc(var(--wrn-radius-sm) - 2px);
background: transparent;
color: inherit;
font: inherit;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
cursor: pointer;
transition: background-color 120ms ease, color 120ms ease;
}
.wrn-next__calendar-weekdays,
.wrn-next__calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 0.125rem;
text-align: center;
}
.wrn-next__calendar-weekdays {
padding-bottom: 0.375rem;
border-bottom: 1px solid var(--wrn-color-border);
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
font-family: var(--wrn-font-mono, monospace);
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.wrn-next__calendar-grid button:hover,
.wrn-next__time-panel button:hover {
background: var(--wrn-color-surface-muted, var(--wrn-color-surface-2));
}
.wrn-next__calendar-grid button[aria-pressed="true"],
.wrn-next__time-panel button[aria-pressed="true"] {
background: var(--wrn-field-color);
color: var(--wrn-color-primary-contrast, #fff);
box-shadow: var(--wrn-highlight-edge, none), 0 1px 2px color-mix(in srgb, var(--wrn-field-color) 35%, transparent);
font-weight: 650;
}
.wrn-next__time-period {
display: flex;
gap: 0.35rem;
}
.wrn-next--file-upload-progress .wrn-next__row,
.wrn-next__upload-actions {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
}
.wrn-next--file-upload-progress .wrn-next__row > span {
display: grid;
min-width: 0;
}
.wrn-next--field[data-variant="underline"]
:is(.wrn-next__input-group-control, .wrn-next__file-control, .wrn-next__color-control) {
border-width: 0 0 1px;
border-radius: 0;
background: transparent;
}
.wrn-next--field[data-variant="outlined"]
:is(.wrn-next__input-group-control, .wrn-next__file-control) {
border-width: 2px;
}
.wrn-next--field[data-variant="pill"]
:is(.wrn-next__input-group-control, .wrn-next__file-control) {
border-radius: 999px;
}
.wrn-next--field[data-variant="ghost"]
:is(.wrn-next__input-group-control, .wrn-next__file-control, .wrn-next__color-control) {
border-color: transparent;
background: color-mix(in srgb, var(--wrn-field-color) 6%, var(--wrn-color-surface-soft, var(--wrn-color-surface)));
}
@media (max-width: 640px) {
.wrn-next--field[data-inline="true"],
.wrn-next--choice-field[data-inline="true"] {
grid-template-columns: 1fr;
}
.wrn-next--field[data-inline="true"] .wrn-next__field-error,
.wrn-next--choice-field[data-inline="true"] .wrn-next__field-error {
grid-column: auto;
}
}
.wrn-next--toggle-password:has(input.wrn-invalid) .wrn-next__password-control > input,
.wrn-next--toggle-password.wrn-next--invalid .wrn-next__password-control > input {
border-color: var(--wrn-color-danger);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--wrn-color-danger) 14%, transparent);
}
.wrn-next--strong-password.wrn-next--invalid input,
.wrn-next--strong-password input.wrn-invalid {
border-color: var(--wrn-color-danger);
}
.wrn-next__picker-clear:hover {
background: var(--wrn-color-surface-muted, var(--wrn-color-surface-2));
color: var(--wrn-color-text);
}
.wrn-next__picker-control > button:first-of-type > i {
width: 1rem;
height: 1rem;
flex: none;
color: var(--wrn-color-text-subtle, var(--wrn-color-muted));
}
.wrn-next--date-picker[data-expanded="true"] .wrn-next__picker-control > button:first-of-type {
border-color: var(--wrn-field-color);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--wrn-field-color) 18%, transparent);
}
.wrn-next__calendar-grid button[data-today="true"][aria-pressed="true"] {
color: var(--wrn-color-primary-contrast, #fff);
}
.wrn-next__date-done:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.wrn-next__calendar .wrn-next--time-picker {
width: 100%;
padding-top: 0.625rem;
border-top: 1px solid var(--wrn-color-border);
}
}
}