Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-games-hammer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@iota/apps-ui-kit': minor
---

add date picker component
412 changes: 412 additions & 0 deletions apps/ui-kit/src/lib/components/molecules/date-picker/DatePicker.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export const DATE_PICKER_TRIGGER_CLASSES =
'date-picker-trigger-border-color focus-visible:enabled:date-picker-trigger-border-focus-color hover:enabled:date-picker-trigger-border-hover-color group-[.errored]:date-picker-trigger-border-error-color flex w-full flex-row items-center gap-x-3 rounded-lg border px-md py-sm disabled:cursor-not-allowed [&_svg]:h-5 [&_svg]:w-5';

export const DATE_PICKER_CALENDAR_CLASSES =
'date-picker-calendar-bg date-picker-calendar-border-color absolute z-50 mt-1 rounded-lg border p-3 shadow-lg';

export const DATE_PICKER_DAY_BASE_CLASSES =
'date-picker-day-text-color flex h-8 w-8 items-center justify-center rounded-full text-body-md transition-colors hover:delay-75';

export const DATE_PICKER_DAY_HOVER_CLASSES =
'enabled:hover:date-picker-day-bg-hover enabled:hover:date-picker-day-text-color-hover cursor-pointer';

export const DATE_PICKER_DAY_SELECTED_CLASSES =
'date-picker-day-bg-selected date-picker-day-text-selected cursor-pointer';

export const DATE_PICKER_DAY_TODAY_CLASSES = 'date-picker-day-today-ring font-semibold';

export const DATE_PICKER_DAY_DISABLED_CLASSES =
'date-picker-day-text-disabled cursor-not-allowed opacity-40';

export const DATE_PICKER_DAY_OUTSIDE_MONTH_CLASSES =
'date-picker-day-text-outside-month cursor-default opacity-30';

export const DATE_PICKER_WEEKDAY_CLASSES =
'date-picker-weekday-text-color flex h-8 w-8 items-center justify-center text-label-sm font-medium';

export const DATE_PICKER_NAV_BUTTON_CLASSES =
'date-picker-nav-icon-color enabled:hover:date-picker-nav-bg-hover flex h-8 w-8 items-center justify-center rounded-full transition-colors hover:delay-75 disabled:cursor-not-allowed disabled:opacity-40 [&_svg]:h-4 [&_svg]:w-4';

export const DATE_PICKER_HEADER_BUTTON_CLASSES =
'date-picker-header-text-color enabled:hover:date-picker-nav-bg-hover rounded-md px-1 py-0.5 text-label-lg font-semibold transition-colors hover:delay-75 shrink-0';

export const DATE_PICKER_YEAR_CELL_BASE_CLASSES =
'date-picker-day-text-color flex w-full items-center justify-center rounded-lg py-2 text-body-md transition-colors hover:delay-75';

export const DATE_PICKER_YEAR_CELL_HOVER_CLASSES = DATE_PICKER_DAY_HOVER_CLASSES;
export const DATE_PICKER_YEAR_CELL_SELECTED_CLASSES = DATE_PICKER_DAY_SELECTED_CLASSES;
export const DATE_PICKER_YEAR_CELL_CURRENT_CLASSES = DATE_PICKER_DAY_TODAY_CLASSES;
export const DATE_PICKER_YEAR_CELL_DISABLED_CLASSES = DATE_PICKER_DAY_DISABLED_CLASSES;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export const WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];

export const MONTHS = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];

export const DECADE_SIZE = 10;

export const YEAR_GRID_SIZE = 12;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export enum DatePickerFormat {
DayMonthYear = 'DD/MM/YYYY',
MonthDayYear = 'MM/DD/YYYY',
YearMonthDay = 'YYYY/MM/DD',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { DECADE_SIZE } from './date-picker.constants';
import { DatePickerFormat } from './date-picker.enums';

export function isSameDay(a: Date, b: Date): boolean {
return (
a.getFullYear() === b.getFullYear() &&
a.getMonth() === b.getMonth() &&
a.getDate() === b.getDate()
);
}

export function startOfDay(date: Date): Date {
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

/** Returns true when date falls outside the [min, max] inclusive range. */
export function isDateDisabled(date: Date, min?: Date, max?: Date): boolean {
const d = startOfDay(date);
if (min && d < startOfDay(min)) return true;
if (max && d > startOfDay(max)) return true;
return false;
}

/** Returns true when every day in year is outside [min, max]. */
export function isYearDisabled(year: number, min?: Date, max?: Date): boolean {
if (min && new Date(year, 11, 31) < startOfDay(min)) return true;
if (max && new Date(year, 0, 1) > startOfDay(max)) return true;
return false;
}

export function formatDate(date: Date, format: DatePickerFormat): string {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
switch (format) {
case DatePickerFormat.DayMonthYear:
return `${day}/${month}/${year}`;
case DatePickerFormat.MonthDayYear:
return `${month}/${day}/${year}`;
case DatePickerFormat.YearMonthDay:
return `${year}/${month}/${day}`;
default:
return `${day}/${month}/${year}`;
}
}

/**
* Builds the 6×7 grid of dates for the calendar day view
* starts on Sunday of the week containing the 1st of the month.
*/
export function buildCalendarGrid(year: number, month: number): Date[] {
const firstDay = new Date(year, month, 1);
const startOffset = firstDay.getDay(); // 0 = Sunday
const grid: Date[] = [];
for (let i = -startOffset; i < 42 - startOffset; i++) {
grid.push(new Date(year, month, 1 + i));
}
return grid;
}

/** Returns the first year of the decade that contains year */
export function decadeStart(year: number): number {
return Math.floor(year / DECADE_SIZE) * DECADE_SIZE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (c) 2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

export * from './DatePicker';
export * from './date-picker.enums';
1 change: 1 addition & 0 deletions apps/ui-kit/src/lib/components/molecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from './search';
export * from './card';
export * from './display-stats';
export * from './visual-asset-card';
export * from './date-picker';
81 changes: 81 additions & 0 deletions apps/ui-kit/src/lib/styles/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,87 @@
color: var(--table-text-color);
}

/* DATE PICKER */
.date-picker-trigger-text-color {
color: var(--date-picker-text-color);
}

.date-picker-trigger-placeholder-color {
color: var(--date-picker-trigger-placeholder-color);
}

.date-picker-trigger-border-color {
border-color: var(--date-picker-border-color);
}

.date-picker-trigger-border-hover-color {
border-color: var(--date-picker-trigger-border-hover-color);
}

.date-picker-trigger-border-focus-color {
border-color: var(--date-picker-focus-color);
}

.date-picker-trigger-border-error-color {
border-color: var(--date-picker-trigger-border-error-color);
}

.date-picker-calendar-bg {
background-color: var(--date-picker-calendar-bg);
}

.date-picker-calendar-border-color {
border-color: var(--date-picker-border-color);
}

.date-picker-header-text-color {
color: var(--date-picker-text-color);
}

.date-picker-nav-icon-color {
color: var(--date-picker-muted-text-color);
}

.date-picker-nav-bg-hover:enabled:hover {
background-color: var(--date-picker-hover-bg);
}

.date-picker-weekday-text-color {
color: var(--date-picker-muted-text-color);
}

.date-picker-day-text-color {
color: var(--date-picker-text-color);
}

.date-picker-day-bg-hover:enabled:hover {
background-color: var(--date-picker-hover-bg);
}

.date-picker-day-text-color-hover:enabled:hover {
color: var(--date-picker-text-color);
}

.date-picker-day-bg-selected {
background-color: var(--date-picker-day-bg-selected);
}

.date-picker-day-text-selected {
color: var(--date-picker-day-text-selected);
}

.date-picker-day-today-ring {
box-shadow: inset 0 0 0 1.5px var(--date-picker-focus-color);
}

.date-picker-day-text-disabled {
color: var(--date-picker-day-text-disabled);
}

.date-picker-day-text-outside-month {
color: var(--date-picker-day-text-outside-month);
}

/* DIALOG */
.dialog-outline {
outline: var(--dialog-outline);
Expand Down
15 changes: 15 additions & 0 deletions apps/ui-kit/src/lib/styles/variables/dark-variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,21 @@
/* TABLE */
--table-text-color: theme('colors.iota-neutral.60');

/* DATE PICKER */
--date-picker-text-color: theme('colors.iota-neutral.92');
--date-picker-trigger-placeholder-color: rgba(136, 146, 161, 0.4);
--date-picker-border-color: theme('colors.iota-neutral.20');
--date-picker-trigger-border-hover-color: theme('colors.iota-neutral.60');
--date-picker-focus-color: theme('colors.iota-primary.80');
--date-picker-trigger-border-error-color: theme('colors.iota-error.80');
--date-picker-calendar-bg: theme('colors.iota-neutral.6');
--date-picker-muted-text-color: theme('colors.iota-neutral.60');
--date-picker-hover-bg: theme('colors.iota-neutral.12');
--date-picker-day-bg-selected: theme('colors.iota-primary.30');
--date-picker-day-text-selected: theme('colors.iota-primary.100');
--date-picker-day-text-disabled: theme('colors.iota-neutral.60');
--date-picker-day-text-outside-month: theme('colors.iota-neutral.40');

/* DIALOG */
--dialog-outline: none;
--dialog-overlay-bg: theme('colors.shader-neutral-light.48');
Expand Down
15 changes: 15 additions & 0 deletions apps/ui-kit/src/lib/styles/variables/light-variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,21 @@
/* TABLE */
--table-text-color: theme('colors.iota-neutral.40');

/* DATE PICKER */
--date-picker-text-color: theme('colors.iota-neutral.10');
--date-picker-trigger-placeholder-color: rgba(84, 94, 110, 0.4);
--date-picker-border-color: theme('colors.iota-neutral.80');
--date-picker-trigger-border-hover-color: theme('colors.iota-neutral.50');
--date-picker-focus-color: theme('colors.iota-primary.30');
--date-picker-trigger-border-error-color: theme('colors.iota-error.30');
--date-picker-calendar-bg: theme('colors.iota-neutral.100');
--date-picker-muted-text-color: theme('colors.iota-neutral.40');
--date-picker-hover-bg: theme('colors.iota-neutral.92');
--date-picker-day-bg-selected: theme('colors.iota-primary.30');
--date-picker-day-text-selected: theme('colors.iota-primary.100');
--date-picker-day-text-disabled: theme('colors.iota-neutral.40');
--date-picker-day-text-outside-month: theme('colors.iota-neutral.60');

/* DIALOG */
--dialog-outline: none;
--dialog-overlay-bg: theme('colors.shader-neutral-light.48');
Expand Down
15 changes: 15 additions & 0 deletions apps/ui-kit/src/lib/styles/variables/names-variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,19 @@

/* TABLE */
--table-text-color: theme('colors.names-neutral.70');

/* DATE PICKER */
--date-picker-text-color: theme('colors.names-neutral.92');
--date-picker-trigger-placeholder-color: rgba(136, 146, 161, 0.4);
--date-picker-border-color: theme('colors.names-neutral.20');
--date-picker-trigger-border-hover-color: theme('colors.names-neutral.60');
--date-picker-focus-color: theme('colors.names-primary.80');
--date-picker-trigger-border-error-color: theme('colors.names-error.80');
--date-picker-calendar-bg: theme('colors.names-neutral.6');
--date-picker-muted-text-color: theme('colors.names-neutral.70');
--date-picker-hover-bg: theme('colors.names-neutral.12');
--date-picker-day-bg-selected: theme('colors.names-primary.30');
--date-picker-day-text-selected: theme('colors.names-primary.100');
--date-picker-day-text-disabled: theme('colors.names-neutral.60');
--date-picker-day-text-outside-month: theme('colors.names-neutral.40');
}
Loading
Loading