Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
40916ee
feat(dropdown): TEDI-Ready Dropdown component #94
airikej Feb 18, 2026
793bc10
chore: fix stories #94
airikej Feb 18, 2026
a6e6ef2
feat(dropdown): add dropdown separator and divided prop + examples #94
airikej Feb 18, 2026
c0d085a
feat(dropdown): tree variant, placement control #94
airikej Feb 20, 2026
dd27964
feat(separator): match stories with Figma #94
airikej Feb 25, 2026
eb19728
Merge branch 'rc' into feat/94-dropdown-tedi-ready-component-development
airikej Feb 26, 2026
3ee3091
fix(dropdown): fix stories #94
airikej Feb 26, 2026
e13e729
feat(date-picker): initial commit #24
airikej Feb 26, 2026
5c763d7
Merge branch 'feat/94-dropdown-tedi-ready-component-development' into…
airikej Feb 26, 2026
ec73cad
feat(dropdown): add className props, add box-shadow, remove unused ty…
airikej Feb 26, 2026
eeb2bdf
Merge branch 'feat/94-dropdown-tedi-ready-component-development' into…
airikej Feb 26, 2026
672d263
feat(date-field): new TEDI-Ready DateField component #24
airikej Mar 3, 2026
d778f1c
feat(date-field): type error fixes #24
airikej Mar 3, 2026
d5ada60
feat(date-field): fix examples, add unit tests #24
airikej Mar 4, 2026
0957015
feat(date-field): states example, css fixes #24
airikej Mar 4, 2026
664a254
fix(dropdown): focused item indicator fix, fix stories #94
airikej Mar 4, 2026
d547f58
fix(dropdown): fix tab targeting on choice items #94
airikej Mar 4, 2026
ca094c4
fix(dropdown): fix focus scrolling bug #94
airikej Mar 4, 2026
dede6b1
Merge branch 'feat/94-dropdown-tedi-ready-component-development' into…
airikej Mar 4, 2026
a9483dc
feat(date-field): fix month and year grid selections when calendarVie…
airikej Mar 4, 2026
8b0f3de
fix(date-field): today button margin issue fix #24
airikej Mar 4, 2026
4c34025
fix(dropdown): design review fixes #94
airikej Mar 5, 2026
9ca8250
fix(dropdown): checkbox/radio tab targeting fix #94
airikej Mar 5, 2026
ad8fb49
fix(dropdown): add deprecated badge to Community component, update Fi…
airikej Mar 5, 2026
a528d7c
fix(dropdown): add more test coverage #94
airikej Mar 5, 2026
31df95d
fix(dropdown): update tests #94
airikej Mar 5, 2026
061ac3e
fix(dropdown): improve test coverage #94
airikej Mar 5, 2026
73e0e2d
Merge branch 'feat/94-dropdown-tedi-ready-component-development' into…
airikej Mar 5, 2026
9f5ee48
feat(date-field, date-calendar): separate components #24
airikej Mar 17, 2026
b49bb74
Merge branch 'rc' into feat/24-datefield-new-tedi-ready-component
airikej Mar 17, 2026
f6cb4c7
feat(date-field): design review fixes #24
airikej Mar 24, 2026
0d04f75
feat(date-field): update stories #24
airikej Mar 24, 2026
21eeca5
fix(date-field): multivalue calendar positioning #24
airikej Mar 24, 2026
273535f
feat(calendar): design review fixes #24
airikej Mar 25, 2026
808e73f
fix(date-field): design review fixes vol 2 #24
airikej Apr 6, 2026
b653378
feat(date-picker): design review fixes on Calendar #24
airikej Apr 6, 2026
2d2b643
fix(date-field): design review fixes #24
airikej Apr 8, 2026
fceb50a
feat(date-field): calendar fixes #24
airikej Apr 8, 2026
86d13ea
feat(date-field): add tests #24
airikej Apr 9, 2026
aaf57b5
Merge branch 'rc' into feat/24-datefield-new-tedi-ready-component
airikej Apr 9, 2026
2a7d22c
fix(date-field, calendar): code review fixes #24
airikej Apr 10, 2026
67fd752
feat(date-field): code review fixes, update test coverage #24
airikej Apr 13, 2026
ae4bed4
feat(date-field): code review fixes #24
airikej Apr 13, 2026
021048e
fix(date-field): code review fixes #24
airikej Apr 14, 2026
8283b08
fix(date-field): code review fixes #24
airikej Apr 15, 2026
97d4435
fix(date-field): code review fixes #24
airikej Apr 24, 2026
df2683c
Merge branch 'rc' into feat/24-datefield-new-tedi-ready-component
airikej Apr 24, 2026
ddbd662
fix(calendar): code review fixes #24
airikej Apr 24, 2026
d4cfeee
feat(date-field): fix desc formatting for Storybook to show prop desc…
airikej Apr 28, 2026
1ffe798
feat(date-field): improve prop name #24
airikej Apr 30, 2026
f2070ec
Merge branch 'rc' into feat/24-datefield-new-tedi-ready-component
airikej Apr 30, 2026
2a43344
fix(date-field): code review fixes #24
airikej May 4, 2026
7875880
fix(date-field): code review fixes #24
airikej May 5, 2026
ef05ef4
fix(date-field): multiple months mobile fix #24
airikej May 6, 2026
d289e7d
fix(date-field): locale parsing more universal #24
airikej May 6, 2026
ae15d7b
fix(date-field): code review fixes #24
airikej May 11, 2026
7c923a4
fix(date-field): add breakpoint props support #24
airikej May 11, 2026
9090caf
fix(date-field): remove duplicate appearance:none; #24
airikej May 11, 2026
fb55cd3
fix(date-field): textfield focus styles, textfield small input height…
airikej May 11, 2026
b9970c3
fix(text-field): align right area content center #24
airikej May 11, 2026
abc144c
fix(date-field,calendar): cr fixes #24
airikej May 12, 2026
f735235
Merge branch 'rc' into feat/24-datefield-new-tedi-ready-component
airikej May 12, 2026
7009a09
chore: add DateField and Calendar components to consumer skills #24
airikej May 13, 2026
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,351 changes: 3,035 additions & 2,316 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"formik": "^2.4.5",
"lodash-es": "^4.17.22",
"react-animate-height": "^3.2.3",
"react-day-picker": "^9.13.2",
"react-dropzone": "^14.3.5",
"react-select": "^5.10.1",
"react-sticky-box": "2.0.5",
Expand Down
2 changes: 1 addition & 1 deletion skills/tedi-react/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const [email, setEmail] = useState('');
<Checkbox id="agree" label="I agree" value="agree" onChange={(val, checked) => setAgreed(checked)} />
```

Form controls: `TextField`, `Select`, `TextArea`, `NumberField`, `Checkbox`, `Radio`, `ChoiceGroup`, `Search`, `FileUpload`, `FileDropzone`.
Form controls: `TextField`, `Select`, `TextArea`, `NumberField`, `Checkbox`, `Radio`, `ChoiceGroup`, `Search`, `DateField`, `FileUpload`, `FileDropzone`.

## Theming

Expand Down
86 changes: 86 additions & 0 deletions skills/tedi-react/references/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,43 @@ Sub-component: `List.Item`
- `maxLength?: number = 200`
- `expandable?: boolean = true`

### Calendar
> **For plain date inputs use `DateField`.** Calendar is the lower-level primitive — reach for it only when you need an always-visible inline calendar (scheduling grid, availability picker) or are building a custom date control on top.

**Props:** `CalendarProps` extends `DayPickerProps`
- `mode?: 'single' | 'multiple' | 'range' = 'single'`
- `value: Date | Date[] | DateRange | undefined` (required) — shape matches the active `mode`
- `handleSelect: OnSelectHandler<...>` (required) — fires when a day is clicked
- `applyValue: (date: Date) => void` (required) — invoked when a month / year cell commits a selection via `selectionLevel`
- `currentMonth: Date` (required), `setCurrentMonth: (date: Date) => void` (required) — controlled visible month
- `view?: 'days' | 'months' | 'years' = 'days'`, `setView?: (view) => void` — controlled visible grid (independent of `selectionLevel`)
- `selectionLevel?: 'days' | 'months' | 'years' = 'days'` — coarser commit level: `'years'` selects Jan 1 of the picked year, `'months'` selects day 1
- `disabledMatchers?: Matcher[]` — same shape as DayPicker's `disabled`
- `availableDays?: Date[] | ((date) => boolean)`, `unavailableDays?: Date[] | ((date) => boolean)` — overlay highlights without disabling neighbours
- `monthYearSelectType?: 'dropdown' | 'grid' = 'dropdown'` — header picker style
- `showOutsideDays?: boolean = true`, `showNavigation?: boolean = true`
- `locale?: Locale = et`, `localeCode?: string = 'et-EE'`
- `required?: boolean`, `footer?: ReactNode`, `className?: string`

```tsx
import { Calendar } from '@tedi-design-system/react/tedi';

const [view, setView] = useState<'days' | 'months' | 'years'>('days');
const [month, setMonth] = useState(new Date());
const [date, setDate] = useState<Date | undefined>();

<Calendar
mode="single"
view={view}
setView={setView}
currentMonth={month}
setCurrentMonth={setMonth}
value={date}
handleSelect={(value) => setDate(value as Date)}
applyValue={setDate}
/>
```

## Form

### TextField
Expand Down Expand Up @@ -252,6 +289,55 @@ Same as Checkbox (without indeterminate)
- `onSearch?: (value: string) => void`
- `button?: Partial<ButtonProps>`

### DateField
**Props:** `DateFieldProps` extends `DayPickerProps` | fRef (`TextFieldForwardRef`), bp, form
- `id: string` (required), `label: string` (required)
- `mode?: 'single' | 'multiple' | 'range' = 'single'` — selection model
- `selected?: Date | Date[] | DateRange`, `defaultValue?: Date | Date[] | DateRange`
- `onSelect?: OnSelectHandler<Date | Date[] | DateRange | undefined>`
- `placeholder?: string`
- `required?: boolean`, `readOnly?: boolean`
- `formatDate?: (date) => string` — display formatter (default: `dd.MM.yyyy`, et-EE)
- `parseDate?: (value: string) => Date | Date[] | DateRange | undefined` — manual-input parser; without it the field is calendar-only
- `locale?: Locale = et`, `localeCode?: string = 'et-EE'`
- `initialMonth?: Date`
- `closeOnSelect?: boolean` — default: `true` for `'single'`, `false` otherwise
- `footer?: ReactNode` — slot below the calendar grid
- `monthYearSelectType?: 'dropdown' | 'grid' = 'dropdown'` — header pickers
- `selectionLevel?: 'days' | 'months' | 'years' = 'days'` — coarser commit level
- `showOutsideDays?: boolean = true`
- **Disabling:** `disabled?: Matcher | Matcher[]`, `minDate?: Date`, `maxDate?: Date`, `disablePast?: boolean`, `disableFuture?: boolean`, `shouldDisableMonth?: (date) => boolean`, `shouldDisableYear?: (date) => boolean`
- `availableDays?: Date[] | ((date) => boolean)` — opposite of `disabled`
- `inputProps?: Omit<TextFieldProps | MultiValueFieldProps, 'label' | 'id'>` — pass-through to the underlying input
- **Breakpoint-aware:** `enableCalendar?: boolean = true`, `calendarTrigger?: 'input' | 'button' = 'button'`, `useNativePicker?: boolean = false` (`'single'` mode only — swaps to `<input type="date">`), `numberOfMonths?: number` (clamped to 1 below `md`)

The ref shape mirrors TextField (`{ input, wrapper }`). In `'multiple'` mode the underlying control is `MultiValueField`, so `ref.current.input` is `null` there. The calendar trigger button carries `aria-haspopup="dialog"` + `aria-expanded`; when `calendarTrigger="input"` those land on the `<input>` instead.

```tsx
<DateField
id="birthdate"
label="Birth date"
defaultValue={new Date(1990, 0, 1)}
onSelect={(date) => console.log(date)}
minDate={new Date(1900, 0, 1)}
disableFuture
/>

// Range with manual input parsing
<DateField
id="period"
label="Period"
mode="range"
parseDate={(v) => /* return DateRange */}
selected={range}
onSelect={setRange}
closeOnSelect={false}
/>

// Native picker on mobile, custom calendar on desktop
<DateField id="dob" label="Date of birth" useNativePicker md={{ useNativePicker: false }} />
```

### FileUpload
**Props:** `FileUploadProps` | form
- `id: string` (required), `name: string` (required)
Expand Down
70 changes: 70 additions & 0 deletions skills/tedi-react/references/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ TEDI form controls support both **controlled** and **uncontrolled** modes, follo
| Radio | `boolean` (via onChange) | Used in ChoiceGroup |
| ChoiceGroup | `ChoiceGroupValue` | Radio/checkbox groups, segmented variant |
| Search | `string` | Search button, onSearch callback |
| DateField | `Date \| Date[] \| DateRange` | Single/multiple/range, manual input, min/max, native picker, breakpoint-aware |
| FileUpload | `FileUploadFile[]` | Multi-file, validation, loading states |
| FileDropzone | `FileUploadFile[]` | Drag-and-drop |

Expand Down Expand Up @@ -108,6 +109,74 @@ import { NumberField } from '@tedi-design-system/react/tedi';
/>
```

## DateField

Three modes (`'single'`, `'multiple'`, `'range'`) sharing one calendar popover. `selected`/`defaultValue`/`onSelect` adapt their value shape to the active mode (`Date`, `Date[]`, or `DateRange`). Manual text input is **off** by default — supply a `parseDate` to enable it.

```tsx
import { DateField } from '@tedi-design-system/react/tedi';

// Single date (controlled)
const [date, setDate] = useState<Date>();
<DateField id="birthdate" label="Birth date" selected={date} onSelect={setDate} required />

// Range with manual input parsing
<DateField
id="period"
label="Period"
mode="range"
selected={range}
onSelect={setRange}
parseDate={(value) => parseDateRange(value)}
closeOnSelect={false}
/>

// Multiple dates (renders MultiValueField as the input)
<DateField id="appointments" label="Appointments" mode="multiple" selected={dates} onSelect={setDates} />
```

**Constraining the calendar** — every option also greys out the corresponding entries in the month / year header dropdowns:
```tsx
<DateField
id="future-only"
label="Pick a future date"
disablePast
maxDate={new Date(2030, 11, 31)}
shouldDisableYear={(year) => year.getFullYear() === 2026}
/>
```

**Native picker on small screens** — uses `<input type="date">` below `md`, custom calendar from `md` up. Only valid with `mode="single"`:
```tsx
<DateField id="dob" label="Date of birth" useNativePicker md={{ useNativePicker: false }} />
```

**Custom display formatting**:
```tsx
<DateField
id="iso"
label="ISO date"
formatDate={(d) => (d instanceof Date ? d.toISOString().slice(0, 10) : '')}
/>
```

**Calendar selection granularity** — `selectionLevel="months"` or `"years"` commits at a coarser level (useful for "pick a year" UIs):
```tsx
<DateField id="year" label="Year" selectionLevel="years" />
```

**Forwarding to the inner input** — pass-through props (e.g. `helper`, `icon`, `isClearable`):
```tsx
<DateField
id="end"
label="End date"
inputProps={{
helper: { type: 'hint', text: 'Leave empty for "ongoing"' },
isClearable: true,
}}
/>
```

## Checkbox & Radio

```tsx
Expand Down Expand Up @@ -213,6 +282,7 @@ import { FileUpload, FileDropzone } from '@tedi-design-system/react/tedi';
- **Choice inputs:** `onChange?: (value: string, checked: boolean) => void`
- **Select:** `onChange?: (value: ISelectOption | ISelectOption[] | null) => void`
- **NumberField:** `onChange?: (value: number) => void`
- **DateField:** `onSelect?: OnSelectHandler<Date | Date[] | DateRange | undefined>` — value shape depends on `mode` (`'single'` → `Date`, `'multiple'` → `Date[]`, `'range'` → `DateRange`)

## Disabled State

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react';
import { UnknownType } from 'libs/react-components/src/tedi/types/commonTypes';

import { useBreakpointProps } from '../../../../helpers';
import { UnknownType } from '../../../../types/commonTypes';
import styles from '../card.module.scss';
import { CardContentProps } from '../card-content/card-content';
import { CardContext } from '../card-context';
Expand Down
Loading
Loading