mirror of
https://github.com/Nexoniarz/Niveus.git
synced 2026-11-03 04:34:26 +00:00
Glaze is glass with a dial: --nv-glass-frost (0 clear .. 1 heavy) moves backdrop blur, tint and saturation together, read where the surface is drawn so any subtree or slider can change it. A masked rim and a specular bloom follow the pointer via niveus.js; without it the light sits at its default and the material still reads. Falls back to the elevated solid under reduced transparency or without backdrop-filter. New components: .nv-slider (binds to a token with data-nv-var), .nv-calendar, .nv-timepicker (24-hour by default, optional 24H / AM/PM switch, value always HH:MM), and .nv-picker with .nv-menu--listbox (search, type-ahead, keys). All render without niveus.js except where noted. GUIDELINES.md is the normative rulebook for people and AI agents. check.py, build.py and build.py --check pass. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
131 lines
4.1 KiB
CSS
131 lines
4.1 KiB
CSS
/* ==========================================================================
|
||
Niveus — Calendar
|
||
--------------------------------------------------------------------------
|
||
<div class="nv-calendar nv-surface" data-nv-calendar data-nv-value="2026-10-28">
|
||
<div class="nv-calendar__header">
|
||
<button class="nv-button nv-button--ghost nv-button--icon"
|
||
data-nv-calendar-step="-1" aria-label="Previous month">‹</button>
|
||
<h3 class="nv-calendar__title" aria-live="polite">October 2026</h3>
|
||
<button class="nv-button nv-button--ghost nv-button--icon"
|
||
data-nv-calendar-step="1" aria-label="Next month">›</button>
|
||
</div>
|
||
<div class="nv-calendar__grid" role="grid" aria-labelledby="…">
|
||
<div role="row"> <span class="nv-calendar__weekday" role="columnheader">Mo</span> … </div>
|
||
<div role="row">
|
||
<button class="nv-calendar__day" role="gridcell" data-date="2026-10-01">1</button> …
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
A calendar holds content, so it takes no material of its own: put it on
|
||
.nv-surface, or on .nv-material-glaze when it floats over something. The
|
||
grid and its states are plain markup and render without niveus.js; the
|
||
script's only jobs are to build the days for a month, step between months,
|
||
and keep the keyboard model (arrows, PageUp/PageDown, Home/End).
|
||
|
||
State lives in attributes the platform already has a meaning for:
|
||
aria-selected="true" the chosen day
|
||
aria-current="date" today
|
||
data-outside a day that belongs to the neighbouring month
|
||
disabled outside data-nv-min / data-nv-max
|
||
========================================================================== */
|
||
|
||
.nv-calendar {
|
||
--_cell: 2.5rem;
|
||
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--nv-space-3);
|
||
inline-size: fit-content;
|
||
max-inline-size: 100%;
|
||
padding: var(--nv-space-4);
|
||
border-radius: var(--nv-radius-xl);
|
||
color: var(--nv-color-text-primary);
|
||
}
|
||
|
||
.nv-calendar__header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: var(--nv-space-2);
|
||
}
|
||
|
||
.nv-calendar__title {
|
||
margin: 0;
|
||
font: var(--nv-font-label);
|
||
font-size: var(--nv-font-size-md);
|
||
font-weight: var(--nv-font-weight-semibold);
|
||
}
|
||
|
||
.nv-calendar__grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(7, var(--_cell));
|
||
gap: var(--nv-space-0-5) 0;
|
||
}
|
||
|
||
.nv-calendar__grid > [role="row"] {
|
||
display: contents;
|
||
}
|
||
|
||
.nv-calendar__weekday {
|
||
display: grid;
|
||
place-items: center;
|
||
block-size: var(--nv-space-8);
|
||
color: var(--nv-color-text-tertiary);
|
||
font: var(--nv-font-caption);
|
||
font-weight: var(--nv-font-weight-semibold);
|
||
letter-spacing: var(--nv-letter-spacing-wider);
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.nv-calendar__day {
|
||
inline-size: var(--_cell);
|
||
block-size: var(--_cell);
|
||
padding: 0;
|
||
background-color: transparent;
|
||
border: 0;
|
||
border-radius: var(--nv-radius-full);
|
||
color: var(--nv-color-text-primary);
|
||
font: var(--nv-font-label);
|
||
font-variant-numeric: tabular-nums;
|
||
cursor: pointer;
|
||
transition: var(--nv-transition-colors), var(--nv-transition-depth);
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.nv-calendar__day:hover:not(:disabled, [aria-selected="true"]) {
|
||
background-color: var(--nv-color-surface-hover);
|
||
}
|
||
}
|
||
|
||
.nv-calendar__day[data-outside] {
|
||
color: var(--nv-color-text-tertiary);
|
||
}
|
||
|
||
/* Today is ringed, not filled: filled means chosen. */
|
||
.nv-calendar__day[aria-current="date"] {
|
||
color: var(--nv-color-accent-text);
|
||
box-shadow: inset 0 0 0 var(--nv-border-width-strong) var(--nv-color-accent);
|
||
}
|
||
|
||
/* The chosen day is a small raised key, lit like the filled buttons. */
|
||
.nv-calendar__day[aria-selected="true"] {
|
||
background-color: var(--nv-color-accent);
|
||
background-image: var(--nv-sheen-filled);
|
||
color: var(--nv-color-on-accent);
|
||
box-shadow: var(--nv-bevel), var(--nv-outline), var(--nv-elevation-1);
|
||
}
|
||
|
||
.nv-calendar__day:focus-visible {
|
||
outline: none;
|
||
box-shadow: var(--nv-focus-ring);
|
||
}
|
||
|
||
.nv-calendar__day[aria-selected="true"]:focus-visible {
|
||
box-shadow: var(--nv-bevel), var(--nv-focus-ring);
|
||
}
|
||
|
||
.nv-calendar__day:disabled {
|
||
color: var(--nv-color-text-disabled);
|
||
cursor: not-allowed;
|
||
}
|