Skip to content
Open
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
2 changes: 1 addition & 1 deletion apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@raystack/apsara": "workspace:*",
"@types/mdast": "^4.0.4",
"class-variance-authority": "^0.7.1",
"dayjs": "^1.11.11",
"dayjs": "^1.11.20",
"fumadocs-core": "16.0.7",
"fumadocs-docgen": "^1.3.8",
"fumadocs-mdx": "13.0.5",
Expand Down
22 changes: 4 additions & 18 deletions apps/www/src/app/examples/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,7 @@ const Page = () => {
disabled: {
before: dayjs().add(3, 'month').toDate(),
after: dayjs().add(3, 'year').toDate()
},
mode: 'single',
required: true,
selected: new Date()
}
}}
inputProps={{
size: 'small'
Expand All @@ -302,15 +299,7 @@ const Page = () => {
}
calendarProps={{
captionLayout: 'dropdown',
mode: 'range',
required: true,
selected: {
from: dayjs('2027-11-15').toDate(),
to: dayjs('2027-12-10').toDate()
},
numberOfMonths: 2,
fromYear: 2024,
toYear: 2027,
startMonth: dayjs('2024-01-01').toDate(),
endMonth: dayjs('2027-12-01').toDate(),
defaultMonth: dayjs('2027-11-01').toDate()
Expand All @@ -335,10 +324,7 @@ const Page = () => {

<DatePicker
calendarProps={{
captionLayout: 'dropdown',
mode: 'single',
required: true,
selected: new Date()
captionLayout: 'dropdown'
}}
/>

Expand Down Expand Up @@ -1978,7 +1964,7 @@ const Page = () => {
</Flex>

<Text
size={10}
size='large'
weight='medium'
style={{ marginTop: '32px', marginBottom: '16px' }}
>
Expand Down Expand Up @@ -2514,7 +2500,7 @@ const Page = () => {
No data available
</Text>
<Text
size={2}
size='small'
style={{ color: 'var(--rs-color-text-subtle)' }}
>
There are no users in the system. Create your first
Expand Down
4 changes: 2 additions & 2 deletions apps/www/src/components/playground/calendar-examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export function CalendarExamples() {
<PlaygroundLayout title='Calendar'>
<Flex gap={5} direction='column'>
<Calendar numberOfMonths={2} />
<RangePicker inputFieldsProps={{ startDate: { size: 'small' } }} />
<DatePicker inputFieldProps={{ size: 'small' }} />
<RangePicker inputsProps={{ startDate: { size: 'small' } }} />
<DatePicker inputProps={{ size: 'small' }} />
</Flex>
</PlaygroundLayout>
);
Expand Down
119 changes: 90 additions & 29 deletions apps/www/src/content/docs/components/calendar/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const preview = {
{
name: 'Range Picker',
code: `
<RangePicker inputFieldsProps={{ startDate: { size: "small" }, endDate: { size: "small" } }} />`
<RangePicker slotProps={{ startInput: { size: "small" }, endInput: { size: "small" } }} />`
},
{
name: 'Date Picker',
Expand All @@ -19,20 +19,86 @@ export const preview = {
]
};

// Layout & appearance: how the calendar looks and what chrome it renders.
export const calendarDemo = {
type: 'code',
tabs: [
{
name: 'Basic',
code: `<Calendar numberOfMonths={2} />`
code: `<Calendar
numberOfMonths={2}
defaultMonth={new Date(2025, 5, 1)}
showWeekNumber={false}
weekStartsOn={1}
showOutsideDays={false}
/>`
},
{
name: 'With Loading',
code: `<Calendar loadingData={true} numberOfMonths={2} />`
},
{
name: 'With Dropdowns',
code: `<Calendar captionLayout="dropdown" fromYear={2020} toYear={2030} />`
code: `<Calendar
captionLayout="dropdown"
startMonth={new Date(2020, 0)}
endMonth={new Date(2030, 11)}
/>`
},
{
name: 'With Footer',
code: `<Calendar
footer="Select any date to view details"
/>`
}
]
};

// Data & behavior: tooltips, disabled days, timezone, controlled navigation.
export const calendarBehaviorDemo = {
type: 'code',
tabs: [
{
name: 'With Tooltips',
code: `<Calendar
showTooltip
tooltipMessages={{
'15-06-2026': 'Holiday',
'20-06-2026': 'Team off-site',
}}
/>`
},
{
name: 'With Disabled Dates',
code: `<Calendar
disabled={{
before: new Date(),
after: new Date(2026, 11, 31),
}}
/>`
},
{
name: 'With Timezone',
code: `<Calendar timeZone="America/New_York" />`
},
{
name: 'Controlled Month',
code: `
/*
In a real app, hold \`month\` in parent state and update it from
\`onMonthChange\`:

const [month, setMonth] = useState(new Date(2025, 5, 1));
<Calendar month={month} onMonthChange={setMonth} />

This demo uses a fixed date + logging callback, so the calendar stays
pinned to June 2025 because no parent state advances on chevron clicks.
*/
<Calendar
month={new Date(2025, 5, 1)}
onMonthChange={(month) => console.log('Visible month:', month)}
numberOfMonths={2}
/>`
}
]
};
Expand All @@ -57,15 +123,11 @@ export const rangePickerDemo = {
from: new Date(2024, 0, 1),
to: new Date(2024, 0, 15)
}}
calendarProps={{
mode: "range",
required: true,
selected: {
from: new Date(2024, 0, 1),
to: new Date(2024, 0, 15)
slotProps={{
calendar: {
startMonth: new Date(2024, 0, 1),
endMonth: new Date(2024, 11, 31),
},
fromMonth: new Date(2024, 0, 1),
toMonth: new Date(2024, 11, 31),
}}
>
{({ startDate, endDate }) => (
Expand All @@ -82,11 +144,11 @@ export const datePickerDemo = {
tabs: [
{
name: 'Basic',
code: `<DatePicker textFieldProps={{ size: "medium" }} />`
code: `<DatePicker slotProps={{ input: { size: "medium" } }} />`
},
{
name: 'Without Calendar Icon',
code: `<DatePicker showCalendarIcon={false} textFieldProps={{ size: "medium" }} />`
code: `<DatePicker showCalendarIcon={false} slotProps={{ input: { size: "medium" } }} />`
},
{
name: 'Custom Trigger',
Expand All @@ -107,22 +169,21 @@ export const dateInfoDemo = {
tabs: [
{
name: 'With Date Info',
code: `
<Calendar
numberOfMonths={2}
dateInfo={{
[dayjs().format('DD-MM-YYYY')]: (
<Flex
align='center'
gap={2}
style={{ fontSize: '8px', color: 'var(--rs-color-foreground-base-secondary)' }}
>
<Info style={{ width: '8px', height: '8px' }} />
<Text style={{ fontSize: '8px' }} color='secondary'>25%</Text>
</Flex>
)
}}
/>`
code: `<Calendar
numberOfMonths={2}
dateInfo={{
[dayjs().format('DD-MM-YYYY')]: (
<Flex
align='center'
gap={2}
style={{ fontSize: '8px', color: 'var(--rs-color-foreground-base-secondary)' }}
>
<Info style={{ width: '8px', height: '8px' }} />
<Text style={{ fontSize: '8px' }} color='secondary'>25%</Text>
</Flex>
)
}}
/>`
}
]
};
53 changes: 21 additions & 32 deletions apps/www/src/content/docs/components/calendar/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
datePickerDemo,
rangePickerDemo,
calendarDemo,
calendarBehaviorDemo,
dateInfoDemo,
} from "./demo.ts";

Expand Down Expand Up @@ -38,65 +39,53 @@ Renders a standalone calendar for date selection.

### RangePicker

The RangePicker supports customizing the popover behavior using the `popoverProps` prop.
The RangePicker exposes its slots — `startInput`, `endInput`, `calendar`, `popover` — through the `slotProps` prop.

<auto-type-table path="./props.ts" name="RangePickerProps" />

### DatePicker

The DatePicker supports customizing the popover behavior using the `popoverProps` prop.
The DatePicker exposes its slots — `input`, `calendar`, `popover` — through the `slotProps` prop.

<auto-type-table path="./props.ts" name="DatePickerProps" />

## Examples

### Calendar

Choose between different variants to convey different meanings or importance levels. Default variant is `accent`.
#### Layout & appearance

Number of months, dropdown nav, loading state, footer.

<Demo data={calendarDemo} />

#### Custom Date Information
#### Behavior & data

Tooltips, disabled days, timezone, controlled month navigation.

<Demo data={calendarBehaviorDemo} />

#### Custom date information

You can display custom components above each date using the `dateInfo` prop. The keys should be date strings in `"dd-MM-yyyy"` format, and the values are React components that will be rendered above the date number.

<Demo data={dateInfoDemo} />

### Range Picker

The Range Picker component allows selecting a date range with the following behaviors:

1. When selecting two different dates:
- The UI will show the exact selected dates
- The callback will return the start and end date as selected
```tsx
// Example: If user selects April 1st and April 10th, 2025
// UI will show: April 1st, 2025 - April 10th, 2025
// Callback will return:
{
"from": "2025-03-31T18:30:00.000Z",
"to": "2025-04-09T18:30:00.000Z"
}
```

2. When clicking the same date twice:
- The UI will show the same date for both start and end
- The callback will return the start and end date as selected
```tsx
// Example: If user clicks April 1st, 2025 twice
// UI will show: April 1st, 2025 - April 1st, 2025
// Callback will return:
{
"from": "2025-03-31T18:30:00.000Z",
"to": "2025-03-31T18:30:00.000Z"
}
```
Selects a date range across two inputs. The grid uses a state machine that branches on the current `from` / `to`:

- **Empty** — first click sets `from` and advances focus to the end input.
- **Only `from` set** — clicking a later date completes the range and closes the popover; clicking an earlier date resets `from`.
- **Both set** — clicking again restarts: the new date becomes `from`, `to` clears.

`onSelect` fires on every step (the shape is `{ from?: Date; to?: Date }` — partial during interaction). Gate on `range.to` if you only want the completed-range event.

<Demo data={rangePickerDemo} />

### Date Picker

Badges can include an icon to provide additional visual context. By default there is no icon.
Single-date selection with a typable input. The popover opens on focus; pressing Enter, blurring, or clicking outside commits the value and fires `onSelect`.

<Demo data={datePickerDemo} />

Expand Down
Loading
Loading