rewrite datepicker, v0.1.18
This commit is contained in:
@@ -11,7 +11,7 @@ const meta = {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'Date selection field with InputField-compatible API, supporting date/time/datetime-local values, size/layout variants, and validation state.',
|
||||
'In-house date/time selection field with InputField-compatible API. Uses a custom popup (not native browser pickers) and supports date, time, and date-time modes.',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -27,10 +27,10 @@ const meta = {
|
||||
table: { type: { summary: 'string' } },
|
||||
},
|
||||
type: {
|
||||
description: 'Native date input type.',
|
||||
options: ['date', 'datetime-local', 'time'],
|
||||
description: 'DatePicker mode.',
|
||||
options: ['date', 'date-time', 'time'],
|
||||
control: 'inline-radio',
|
||||
table: { type: { summary: "'date' | 'datetime-local' | 'time'" } },
|
||||
table: { type: { summary: "'date' | 'date-time' | 'time'" } },
|
||||
},
|
||||
size: {
|
||||
description: 'Input size.',
|
||||
@@ -55,6 +55,22 @@ const meta = {
|
||||
control: 'text',
|
||||
table: { type: { summary: 'string' } },
|
||||
},
|
||||
format: {
|
||||
description:
|
||||
'Optional input/output format. Supported tokens: `dd`, `mm`, `yyyy`, `HH` (for example `dd/mm/yyyy HH:mm`).',
|
||||
control: 'text',
|
||||
table: { type: { summary: 'string' } },
|
||||
},
|
||||
min: {
|
||||
description: 'Optional minimum value in the same format as `value`.',
|
||||
control: 'text',
|
||||
table: { type: { summary: 'string' } },
|
||||
},
|
||||
max: {
|
||||
description: 'Optional maximum value in the same format as `value`.',
|
||||
control: 'text',
|
||||
table: { type: { summary: 'string' } },
|
||||
},
|
||||
name: {
|
||||
description: 'Native input `name` attribute.',
|
||||
control: 'text',
|
||||
@@ -108,7 +124,7 @@ const meta = {
|
||||
},
|
||||
args: {
|
||||
label: 'Schedule at',
|
||||
type: 'datetime-local',
|
||||
type: 'date-time',
|
||||
value: '',
|
||||
size: 'md',
|
||||
width: 'md',
|
||||
@@ -125,7 +141,7 @@ export const DateOnly: Story = {
|
||||
label: 'Publish date',
|
||||
},
|
||||
render: function DateOnlyRender(args) {
|
||||
const [value, setValue] = useState('2031-05-20');
|
||||
const [value, setValue] = useState('2031/05/20');
|
||||
return (
|
||||
<DatePicker
|
||||
{...args}
|
||||
@@ -141,11 +157,11 @@ export const DateOnly: Story = {
|
||||
|
||||
export const DateTime: Story = {
|
||||
args: {
|
||||
type: 'datetime-local',
|
||||
type: 'date-time',
|
||||
label: 'Schedule at',
|
||||
},
|
||||
render: function DateTimeRender(args) {
|
||||
const [value, setValue] = useState('2031-05-20T14:30');
|
||||
const [value, setValue] = useState('2031/05/20 14:30');
|
||||
return (
|
||||
<DatePicker
|
||||
{...args}
|
||||
@@ -185,7 +201,7 @@ export const TimeOnlyInline: Story = {
|
||||
export const ErrorState: Story = {
|
||||
name: 'Error',
|
||||
args: {
|
||||
type: 'datetime-local',
|
||||
type: 'date-time',
|
||||
label: 'Schedule at',
|
||||
value: '',
|
||||
error: 'Pick a valid future date and time',
|
||||
@@ -194,20 +210,20 @@ export const ErrorState: Story = {
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
type: 'datetime-local',
|
||||
type: 'date-time',
|
||||
label: 'Published at',
|
||||
value: '2031-05-20T14:30',
|
||||
value: '2031/05/20 14:30',
|
||||
disabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const SizeMatrix: Story = {
|
||||
args: {
|
||||
type: 'datetime-local',
|
||||
type: 'date-time',
|
||||
label: 'Schedule at',
|
||||
},
|
||||
render: function SizeMatrixRender(args) {
|
||||
const [value, setValue] = useState('2031-05-20T14:30');
|
||||
const [value, setValue] = useState('2031/05/20 14:30');
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-3">
|
||||
<DatePicker
|
||||
@@ -239,3 +255,26 @@ export const SizeMatrix: Story = {
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomFormatWithRange: Story = {
|
||||
args: {
|
||||
type: 'date-time',
|
||||
label: 'Starts at',
|
||||
format: 'dd/mm/yyyy HH:mm',
|
||||
min: '10/03/2026 09:00',
|
||||
max: '24/03/2026 18:30',
|
||||
},
|
||||
render: function CustomFormatWithRangeRender(args) {
|
||||
const [value, setValue] = useState('22/03/2026 14:30');
|
||||
return (
|
||||
<DatePicker
|
||||
{...args}
|
||||
value={value}
|
||||
onChange={(event) => {
|
||||
setValue(event.target.value);
|
||||
args.onChange?.(event);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@
|
||||
--bg-page: #16121a;
|
||||
--surface-bg: rgba(24, 24, 27, 0.45);
|
||||
--surface-bg-strong: rgba(24, 24, 27, 0.62);
|
||||
--datepicker-menu-bg: #18181b;
|
||||
--surface-border: rgba(82, 82, 91, 0.6);
|
||||
--surface-divider: rgba(63, 63, 70, 0.85);
|
||||
--text-primary: #d5cfdf;
|
||||
@@ -59,6 +60,7 @@
|
||||
--bg-page: #f7f7fb;
|
||||
--surface-bg: rgba(255, 255, 255, 0.9);
|
||||
--surface-bg-strong: rgba(255, 255, 255, 0.98);
|
||||
--datepicker-menu-bg: #ffffff;
|
||||
--surface-border: rgba(161, 161, 170, 0.45);
|
||||
--surface-divider: rgba(212, 212, 216, 0.9);
|
||||
--text-primary: #52485c;
|
||||
|
||||
@@ -327,3 +327,190 @@
|
||||
color: var(--text-secondary);
|
||||
@apply px-4 py-3 text-sm;
|
||||
}
|
||||
|
||||
.datepicker-icon-btn {
|
||||
color: var(--text-muted);
|
||||
@apply absolute inset-y-0 right-2 my-auto inline-flex h-6 w-6 items-center justify-center rounded-md border border-transparent bg-transparent p-0 transition;
|
||||
}
|
||||
|
||||
.datepicker-icon-btn:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--ghost-hover);
|
||||
}
|
||||
|
||||
.datepicker-icon-btn:focus-visible {
|
||||
outline: none;
|
||||
border-color: rgb(var(--accent-400));
|
||||
box-shadow: 0 0 0 2px rgb(var(--accent-400) / 0.3);
|
||||
}
|
||||
|
||||
.datepicker-icon-btn:disabled {
|
||||
color: var(--ghost-disabled-text);
|
||||
background-color: transparent;
|
||||
@apply cursor-not-allowed;
|
||||
}
|
||||
|
||||
.datepicker-popup {
|
||||
border: 1px solid var(--surface-divider);
|
||||
background-color: var(--surface-bg-strong);
|
||||
box-shadow: var(--shadow-glow);
|
||||
color: var(--text-primary);
|
||||
backdrop-filter: saturate(145%) blur(var(--auth-glass-blur));
|
||||
-webkit-backdrop-filter: saturate(145%) blur(var(--auth-glass-blur));
|
||||
will-change: backdrop-filter;
|
||||
max-width: min(96vw, 440px);
|
||||
@apply fixed z-[70] flex flex-col gap-3 rounded-xl p-3;
|
||||
}
|
||||
|
||||
.datepicker-popup-top {
|
||||
transform-origin: bottom center;
|
||||
}
|
||||
|
||||
.datepicker-popup-bottom {
|
||||
transform-origin: top center;
|
||||
}
|
||||
|
||||
@screen sm {
|
||||
.datepicker-popup {
|
||||
@apply flex-row;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-panel {
|
||||
@apply min-w-0;
|
||||
}
|
||||
|
||||
.datepicker-calendar-nav {
|
||||
@apply mb-2 flex items-center justify-between gap-2;
|
||||
}
|
||||
|
||||
.datepicker-nav-btn {
|
||||
border: 1px solid var(--ghost-border);
|
||||
background-color: var(--ghost-bg);
|
||||
color: var(--text-secondary);
|
||||
@apply inline-flex h-8 w-8 items-center justify-center rounded-lg transition;
|
||||
}
|
||||
|
||||
.datepicker-nav-btn:hover {
|
||||
background-color: var(--ghost-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.datepicker-heading-controls {
|
||||
@apply relative flex items-center gap-2;
|
||||
}
|
||||
|
||||
.datepicker-chooser {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.datepicker-chooser-btn {
|
||||
border: 1px solid var(--field-border);
|
||||
background-color: var(--field-bg);
|
||||
color: var(--text-primary);
|
||||
@apply inline-flex h-8 items-center rounded-lg px-2.5 text-xs font-semibold;
|
||||
}
|
||||
|
||||
.datepicker-chooser-menu {
|
||||
border: 1px solid var(--surface-divider);
|
||||
background-color: var(--datepicker-menu-bg);
|
||||
box-shadow: var(--shadow-glow);
|
||||
@apply absolute left-0 top-full z-20 mt-1 max-h-48 min-w-[9rem] overflow-y-auto rounded-lg p-1;
|
||||
}
|
||||
|
||||
.datepicker-chooser-option {
|
||||
color: var(--text-secondary);
|
||||
@apply block w-full rounded-md px-2 py-1.5 text-left text-xs font-medium transition;
|
||||
}
|
||||
|
||||
.datepicker-chooser-option:hover {
|
||||
background-color: var(--ghost-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.datepicker-chooser-option.is-selected {
|
||||
background-color: rgb(var(--accent-500) / 0.22);
|
||||
color: rgb(var(--accent-300));
|
||||
}
|
||||
|
||||
.datepicker-weekdays {
|
||||
@apply mb-1 grid grid-cols-7 gap-1;
|
||||
}
|
||||
|
||||
.datepicker-weekday {
|
||||
color: var(--text-muted);
|
||||
@apply text-center text-[0.65rem] font-semibold uppercase tracking-[0.08em];
|
||||
}
|
||||
|
||||
.datepicker-grid {
|
||||
@apply grid grid-cols-7 gap-1;
|
||||
}
|
||||
|
||||
.datepicker-day {
|
||||
color: var(--text-secondary);
|
||||
@apply inline-flex h-8 w-8 items-center justify-center rounded-lg text-sm transition;
|
||||
}
|
||||
|
||||
.datepicker-day:hover {
|
||||
background-color: var(--ghost-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.datepicker-day.is-selected {
|
||||
background-color: rgb(var(--accent-500));
|
||||
color: rgb(var(--accent-contrast));
|
||||
}
|
||||
|
||||
.datepicker-day.is-today {
|
||||
border: 1px solid rgb(var(--accent-400) / 0.65);
|
||||
}
|
||||
|
||||
.datepicker-day.is-outside-month {
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
.datepicker-day:disabled {
|
||||
color: var(--ghost-disabled-text);
|
||||
background-color: transparent;
|
||||
@apply cursor-not-allowed opacity-50;
|
||||
}
|
||||
|
||||
.datepicker-time-root {
|
||||
@apply grid min-w-[180px] grid-cols-2 gap-2;
|
||||
}
|
||||
|
||||
.datepicker-time-column {
|
||||
@apply flex min-w-0 flex-col gap-1;
|
||||
}
|
||||
|
||||
.datepicker-time-title {
|
||||
color: var(--text-muted);
|
||||
@apply text-[0.65rem] font-semibold uppercase tracking-[0.08em];
|
||||
}
|
||||
|
||||
.datepicker-time-list {
|
||||
border: 1px solid var(--field-border);
|
||||
background-color: var(--field-bg);
|
||||
@apply max-h-52 overflow-y-auto rounded-lg p-1;
|
||||
}
|
||||
|
||||
.datepicker-time-option {
|
||||
color: var(--text-secondary);
|
||||
@apply block w-full rounded-md px-2 py-1.5 text-left text-xs font-semibold transition;
|
||||
}
|
||||
|
||||
.datepicker-time-option:hover {
|
||||
background-color: var(--ghost-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.datepicker-time-option.is-selected {
|
||||
background-color: rgb(var(--accent-500) / 0.22);
|
||||
color: rgb(var(--accent-300));
|
||||
}
|
||||
|
||||
.datepicker-time-option:disabled {
|
||||
color: var(--ghost-disabled-text);
|
||||
background-color: transparent;
|
||||
@apply cursor-not-allowed opacity-55;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user