Packages
noora
0.77.3
0.84.1
0.84.0
0.83.2
0.83.1
0.83.0
0.82.7
0.82.6
0.82.5
0.82.4
0.82.3
0.82.2
0.82.1
0.82.0
0.81.4
0.81.3
0.81.2
0.81.1
0.81.0
0.80.1
0.80.0
0.79.1
0.79.0
0.78.1
0.78.0
0.77.4
0.77.3
0.77.2
0.77.1
0.77.0
0.76.0
0.75.0
0.74.0
0.73.0
0.72.0
0.71.0
0.70.0
0.69.1
0.69.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.2
0.64.1
0.64.0
0.63.2
0.63.1
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.0
0.54.0
0.53.1
0.53.0
0.52.1
0.52.0
0.51.0
0.50.1
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.3
0.44.2
0.44.1
0.44.0
0.43.0
0.42.0
0.41.0
0.40.6
0.40.5
0.40.4
0.40.3
0.40.2
0.40.1
0.40.0
0.39.1
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.1
0.32.0
0.31.0
0.30.0
0.29.2
0.29.1
0.29.0
0.28.5
0.28.4
0.28.3
0.28.2
0.28.1
0.28.0
0.27.0
0.26.1
0.26.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.0
0.1.0
0.1.0-rc.2
0.1.0-rc.1
0.1.0-alpha.6
0.1.0-alpha.5
0.1.0-alpha.4
0.1.0-alpha.3
0.1.0-alpha.2
0.1.0-alpha.1
A component library for Phoenix LiveView applications
Current section
Files
Jump to
Current section
Files
css/date_picker.css
.noora-date-picker {
/* Component-level semantic colors */
--noora-datepicker-range-background: light-dark(
var(--noora-purple-50),
oklch(from var(--noora-purple-500) l c h / 0.24)
);
--noora-datepicker-selected-background: var(--noora-purple-500);
--noora-datepicker-selected-text: var(--noora-neutral-light-50);
--noora-datepicker-range-text: light-dark(
var(--noora-purple-500),
var(--noora-purple-400)
);
--noora-datepicker-today-marker: light-dark(
var(--noora-purple-500),
var(--noora-purple-400)
);
--noora-datepicker-preset-hover-background: light-dark(
var(--noora-neutral-light-200),
var(--noora-neutral-dark-1000)
);
--noora-datepicker-trigger-background: light-dark(
var(--noora-neutral-light-50),
var(--noora-neutral-dark-1100)
);
display: flex;
flex-direction: column;
position: relative;
font: var(--noora-font-body-small);
/* Trigger button */
& [data-part="trigger"] {
--background-base: var(--noora-datepicker-trigger-background);
--background-gradient-start: light-dark(
oklch(78.6% 0.013 248 / 0),
oklch(100% 0 0 / 0.08)
);
--background-gradient-end: light-dark(
oklch(78.6% 0.013 248 / 0.13),
oklch(100% 0 0 / 0)
);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--noora-spacing-4);
cursor: pointer;
outline: unset;
box-shadow: var(--noora-border-light-default);
border: 0;
border-radius: var(--noora-radius-medium);
background:
linear-gradient(
180deg,
var(--background-gradient-start) 0%,
var(--background-gradient-end) 100%
),
var(--background-base);
padding: var(--noora-spacing-3) var(--noora-spacing-4);
color: var(--noora-surface-label-primary);
font: var(--noora-font-body-medium);
width: fit-content;
&:hover:not(:disabled) {
--background-gradient-start: light-dark(
oklch(78.6% 0.013 248 / 0),
oklch(100% 0 0 / 0.04)
);
--background-gradient-end: light-dark(
oklch(78.6% 0.013 248 / 0.26),
oklch(100% 0 0 / 0)
);
}
&:disabled {
cursor: not-allowed;
color: var(--noora-surface-label-disabled);
}
&[data-state="open"] {
box-shadow: var(--noora-border-light-focus);
}
}
& [data-part="trigger-label"] {
font-weight: var(--noora-font-weight-medium);
}
& [data-part="trigger-icon"] {
display: inline-flex;
color: var(--noora-button-secondary-label);
width: var(--noora-icon-size-large);
height: var(--noora-icon-size-large);
& svg {
width: 100%;
height: 100%;
}
}
/* Positioner - Zag handles visibility via hidden attribute */
& [data-part="positioner"] {
/* Zag sets inline positioning styles */
/* Adjust horizontal position to the left */
margin-left: calc(-1 * var(--noora-spacing-2));
/* Prevent flashing of the component before script load */
&:not(:has(> [data-state])) {
display: none;
}
@media (max-width: 767px) {
/* Reset desktop offset and align to available space */
margin-left: 0;
}
}
/* Ensure hidden attribute works (overrides display: flex on children) */
& [data-part="positioner"][hidden],
& [data-part="content"][hidden] {
display: none;
}
/* Content container (the dropdown panel) */
& [data-part="content"] {
display: flex;
flex-direction: row;
background-color: var(--noora-surface-background-tertiary);
box-shadow: var(--noora-border-heavy);
border-radius: var(--noora-radius-xlarge);
@media (max-width: 767px) {
/* Use Zag's --available-width variable to constrain to parent bounds */
flex-direction: column;
width: var(--available-width);
max-width: min(var(--available-width), 302px);
overflow: hidden;
}
}
/* Desktop preset sidebar */
& [data-part="presets"][data-device="desktop"] {
flex-direction: column;
gap: var(--noora-spacing-5);
padding: var(--noora-spacing-6) var(--noora-spacing-2);
width: 140px;
@media (min-width: 768px) {
display: flex;
}
@media (max-width: 767px) {
display: none;
}
}
/* Mobile preset tabs */
& [data-part="presets"][data-device="mobile"] {
flex-direction: row;
gap: var(--noora-spacing-2);
padding: var(--noora-spacing-4);
overflow-x: auto;
/* Hide scrollbar */
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
@media (min-width: 768px) {
display: none;
}
@media (max-width: 767px) {
display: flex;
flex-shrink: 0;
}
& [data-part="preset-item"] {
@media (max-width: 767px) {
flex-shrink: 0;
}
}
}
/* Preset items */
& [data-part="preset-item"] {
display: flex;
align-items: center;
cursor: pointer;
border: 0;
border-radius: var(--noora-radius-medium);
background: transparent;
padding: var(--noora-spacing-2) var(--noora-spacing-4);
color: var(--noora-surface-label-secondary);
font: var(--noora-font-body-small);
white-space: nowrap;
transition: background-color 0.15s ease;
&:hover {
background: var(--noora-datepicker-preset-hover-background);
}
&[data-selected="true"] {
background: var(--noora-datepicker-range-background);
color: var(--noora-datepicker-range-text);
}
}
/* Calendar area container */
& [data-part="calendar"] {
display: flex;
flex-direction: column;
gap: var(--noora-spacing-3);
overflow: hidden;
background-color: var(--noora-surface-background-primary);
border-radius: var(--noora-radius-xlarge);
@media (min-width: 768px) {
box-shadow: var(--noora-border-light-default);
}
@media (max-width: 767px) {
width: 100%;
max-width: 100%;
min-width: 0;
box-sizing: border-box;
border-top: 1px solid var(--noora-content-divider-line);
}
}
/* Months container */
& [data-part="months"] {
display: flex;
gap: var(--noora-spacing-4);
}
/* Individual month */
& [data-part="month"] {
display: flex;
flex-direction: column;
gap: var(--noora-spacing-5);
padding: var(--noora-spacing-6);
&[data-desktop-only] {
@media (min-width: 768px) {
display: flex;
}
@media (max-width: 767px) {
display: none;
}
}
@media (max-width: 767px) {
padding: var(--noora-spacing-4);
}
}
/* Month navigation header */
& [data-part="view-control"] {
display: flex;
align-items: center;
justify-content: space-between;
}
& [data-part="prev-trigger"],
& [data-part="next-trigger"] {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 0;
border-radius: var(--noora-radius-medium);
background: transparent;
padding: var(--noora-spacing-1);
width: var(--noora-icon-size-large);
height: var(--noora-icon-size-large);
color: var(--noora-surface-label-primary);
&:hover {
background: var(--noora-datepicker-preset-hover-background);
}
&:disabled,
&[data-disabled] {
visibility: hidden;
}
& svg {
width: 100%;
height: 100%;
}
}
& [data-part="view-trigger"] {
font: var(--noora-font-body-small);
font-weight: var(--noora-font-weight-medium);
color: var(--noora-surface-label-primary);
}
/* Calendar table */
& [data-part="table"] {
border-collapse: collapse;
border-spacing: 0;
@media (max-width: 767px) {
width: 100%;
table-layout: fixed;
}
}
& [data-part="table-head"] {
& th {
font: var(--noora-font-body-small);
font-weight: var(--noora-font-weight-medium);
color: var(--noora-surface-label-secondary);
padding: var(--noora-spacing-2);
width: 30px;
height: 30px;
text-align: center;
@media (max-width: 767px) {
width: auto;
padding: var(--noora-spacing-1);
}
}
}
& [data-part="table-body"] {
& td {
padding: var(--noora-spacing-2);
position: relative;
@media (max-width: 767px) {
padding: var(--noora-spacing-1);
}
}
}
/* Day cell */
& [data-part="table-cell"] {
position: relative;
}
/* Range/hover-range background - shown behind cells in range or during hover preview */
/* Uses :has() to target td when its child button has data-in-range or data-in-hover-range */
/* Excludes cells with hidden/outside-range/disabled children */
&
[data-part="table-cell"]:has([data-in-range]):not(
:has([data-outside-range])
):not([data-hidden])::before,
&
[data-part="table-cell"]:has([data-in-hover-range]):not(
:has([data-outside-range])
):not(:has([data-disabled])):not(:has([data-selected]))::before {
content: "";
position: absolute;
height: 30px;
top: 50%;
transform: translateY(-50%);
left: 0;
right: 0;
background: var(--noora-datepicker-range-background);
@media (max-width: 767px) {
/* Extend slightly to prevent subpixel gaps between cells */
left: -1px;
right: -1px;
}
}
/* Range start (non-selected) - add rounded left corners and left padding */
&
[data-part="table-cell"]:has(
[data-range-start]:not([data-selected])
)::before {
left: var(--noora-spacing-2);
border-top-left-radius: var(--noora-radius-medium);
border-bottom-left-radius: var(--noora-radius-medium);
}
/* Range end (non-selected) - add rounded right corners and right padding */
&
[data-part="table-cell"]:has(
[data-range-end]:not([data-selected])
)::before {
right: var(--noora-spacing-2);
border-top-right-radius: var(--noora-radius-medium);
border-bottom-right-radius: var(--noora-radius-medium);
}
/* Selected cells - collapse ::before to zero width by default, no radius */
&
[data-part="table-cell"]:has([data-in-range]):has([data-selected]):not(
:has([data-outside-range])
):not([data-hidden])::before {
left: 50%;
right: 50%;
border-radius: 0;
}
/* Selected with hover-range-start (not hover-range-end) - show right half */
&
[data-part="table-cell"]:has(
[data-selected][data-hover-range-start]:not([data-hover-range-end])
):not(:has([data-outside-range])):not([data-hidden])::before {
right: 0;
}
/* Selected with hover-range-end (not hover-range-start) - show left half */
&
[data-part="table-cell"]:has(
[data-selected][data-hover-range-end]:not([data-hover-range-start])
):not(:has([data-outside-range])):not([data-hidden])::before {
left: 0;
}
/* Selected range-start (not also range-end, no hover attrs) - show right half */
&
[data-part="table-cell"]:has(
[data-selected][data-range-start]:not([data-range-end]):not(
[data-hover-range-start]
):not([data-hover-range-end])
):not(:has([data-outside-range])):not([data-hidden])::before {
right: 0;
}
/* Selected range-end (not also range-start, no hover attrs) - show left half */
&
[data-part="table-cell"]:has(
[data-selected][data-range-end]:not([data-range-start]):not(
[data-hover-range-start]
):not([data-hover-range-end])
):not(:has([data-outside-range])):not([data-hidden])::before {
left: 0;
}
/* First cell in row that's in range/hover-range - add rounded left corners and left padding */
&
[data-part="table-cell"]:first-child:has([data-in-range]):not(
:has([data-outside-range])
):not([data-hidden])::before,
&
[data-part="table-cell"]:first-child:has([data-in-hover-range]):not(
:has([data-outside-range])
):not(:has([data-disabled])):not(:has([data-selected]))::before {
left: var(--noora-spacing-2);
border-top-left-radius: var(--noora-radius-medium);
border-bottom-left-radius: var(--noora-radius-medium);
}
/* Cell preceded by hidden cell - treat as first visible, add rounded left corners and left padding */
&
[data-part="day-table-cell"][data-hidden]
+ [data-part="table-cell"]:has([data-in-range]):not([data-hidden])::before {
left: var(--noora-spacing-2);
border-top-left-radius: var(--noora-radius-medium);
border-bottom-left-radius: var(--noora-radius-medium);
}
/* Last cell in row that's in range/hover-range - add rounded right corners and right padding */
&
[data-part="table-cell"]:last-child:has([data-in-range]):not(
:has([data-outside-range])
):not([data-hidden])::before,
&
[data-part="table-cell"]:last-child:has([data-in-hover-range]):not(
:has([data-outside-range])
):not(:has([data-disabled])):not(:has([data-selected]))::before {
right: var(--noora-spacing-2);
border-top-right-radius: var(--noora-radius-medium);
border-bottom-right-radius: var(--noora-radius-medium);
}
/* Cell followed by hidden cell - treat as last visible, add rounded right corners and right padding */
&
[data-part="table-cell"]:has([data-in-range]):not([data-hidden]):has(
+ [data-part="day-table-cell"][data-hidden]
)::before {
right: var(--noora-spacing-2);
border-top-right-radius: var(--noora-radius-medium);
border-bottom-right-radius: var(--noora-radius-medium);
}
/* First hover-range cell in row - add rounded left corners and left padding */
&
[data-part="table-cell"]:has(
[data-in-hover-range]:not([data-outside-range]):not([data-disabled]):not(
[data-selected]
)
)::before {
left: var(--noora-spacing-2);
border-top-left-radius: var(--noora-radius-medium);
border-bottom-left-radius: var(--noora-radius-medium);
}
/* Override: hover-range cells preceded by another hover-range - remove left padding/radius */
&
[data-part="table-cell"]:has([data-in-hover-range])
+ [data-part="table-cell"]:has(
[data-in-hover-range]:not([data-outside-range]):not([data-disabled]):not(
[data-selected]
)
)::before {
left: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
/* Hover range end - add rounded right corners and right padding */
&
[data-part="table-cell"]:has([data-hover-range-end]):not(
:has([data-outside-range])
)::before {
right: var(--noora-spacing-2);
border-top-right-radius: var(--noora-radius-medium);
border-bottom-right-radius: var(--noora-radius-medium);
}
/* Day cell trigger (button) */
& [data-part="table-cell-trigger"] {
display: flex;
align-items: center;
justify-content: center;
position: relative;
cursor: pointer;
border: 0;
border-radius: var(--noora-radius-medium);
background: transparent;
width: 30px;
height: 30px;
font: var(--noora-font-body-small);
color: var(--noora-surface-label-secondary);
transition:
background-color 0.15s ease,
color 0.15s ease;
&:hover:not([data-disabled]):not([data-unavailable]):not(
[data-selected]
):not([data-hidden]) {
background: var(--noora-datepicker-preset-hover-background);
}
/* Hidden cells */
&[data-hidden] {
cursor: default;
}
/* In range state (confirmed selection) */
&[data-in-range]:not([data-selected]) {
color: var(--noora-datepicker-range-text);
}
/* Hover range state (hover preview during range selection) */
&[data-in-hover-range]:not([data-selected]):not([data-disabled]) {
color: var(--noora-datepicker-range-text);
}
/* Selected state (start/end of range) */
&[data-selected] {
background: var(--noora-datepicker-selected-background);
color: var(--noora-datepicker-selected-text);
box-shadow: var(--noora-button-border-primary);
}
/* Today marker */
&[data-today]::after {
content: "";
position: absolute;
bottom: 4px;
left: 50%;
transform: translateX(-50%);
width: 8px;
height: 2px;
background: var(--noora-datepicker-today-marker);
border-radius: var(--noora-radius-max);
}
&[data-today][data-selected]::after {
background: var(--noora-datepicker-selected-text);
}
/* Disabled state */
&[data-disabled],
&[data-unavailable] {
color: var(--noora-surface-label-disabled);
cursor: not-allowed;
}
/* Outside current month - hide completely */
&[data-outside-range] {
visibility: hidden;
}
}
/* Disable trigger hover background when in range selection mode (except for selected elements) */
&[data-selecting-range]
[data-part="table-cell-trigger"]:hover:not([data-disabled]):not(
[data-unavailable]
):not([data-selected]) {
background-color: transparent;
}
/* Disable trigger hover background for in-range cells (except range start/end) */
&
[data-part="table-cell-trigger"][data-in-range]:not([data-range-start]):not(
[data-range-end]
):hover {
background-color: transparent;
}
/* Footer section */
& [data-part="footer"] {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--noora-spacing-6);
@media (max-width: 767px) {
flex-direction: column;
gap: var(--noora-spacing-7);
padding: var(--noora-spacing-4);
}
& [data-part="actions"] {
@media (max-width: 767px) {
display: flex;
flex-direction: row;
width: 100%;
justify-content: flex-end;
gap: var(--noora-spacing-3);
}
}
}
/* Range display */
& [data-part="range-display"] {
display: flex;
align-items: center;
gap: var(--noora-spacing-4);
@media (max-width: 767px) {
width: 100%;
justify-content: center;
}
}
& [data-part="date-display"] {
display: flex;
align-items: center;
gap: var(--noora-spacing-1);
box-shadow: var(--noora-border-light-default);
border-radius: var(--noora-radius-medium);
background: var(--noora-surface-background-primary);
padding: var(--noora-spacing-1);
&:focus-within {
box-shadow: var(--noora-border-light-focus);
}
}
& [data-part="date-input"] {
border: 0;
background: transparent;
padding: var(--noora-spacing-1);
font: var(--noora-font-body-small);
color: var(--noora-surface-label-primary);
text-align: center;
&[data-field="day"],
&[data-field="month"] {
width: 24px;
}
&[data-field="year"] {
width: 40px;
}
&::placeholder {
color: var(--noora-surface-label-tertiary);
}
&:focus {
outline: none;
}
&:disabled {
cursor: not-allowed;
color: var(--noora-surface-label-disabled);
}
}
& [data-part="date-separator"] {
color: var(--noora-surface-label-primary);
font: var(--noora-font-weight-regular) var(--noora-font-body-small);
}
& [data-part="arrow"] {
color: var(--noora-surface-label-secondary);
width: var(--noora-icon-size-medium);
height: var(--noora-icon-size-medium);
& svg {
width: 100%;
height: 100%;
}
}
/* Actions */
& [data-part="actions"] {
display: flex;
align-items: center;
gap: var(--noora-spacing-4);
}
& [data-part="cancel"],
& [data-part="apply"] {
display: flex;
align-items: center;
justify-content: center;
gap: var(--noora-spacing-1);
cursor: pointer;
border: 0;
border-radius: var(--noora-radius-medium);
padding: var(--noora-spacing-3) var(--noora-spacing-4);
font: var(--noora-font-body-small);
font-weight: var(--noora-font-weight-medium);
transition: background-color 0.15s ease;
}
& [data-part="cancel"] {
background: var(--noora-button-background-secondary);
box-shadow: var(--noora-button-border-secondary);
color: var(--noora-button-secondary-label);
&:hover {
background: var(--noora-button-background-secondary-hover);
}
}
& [data-part="apply"] {
background: var(--noora-button-background-primary);
box-shadow: var(--noora-button-border-primary);
color: var(--noora-button-primary-label);
&:hover {
background: var(--noora-button-background-primary-hover);
box-shadow: var(--noora-button-border-primary-hover);
}
}
}