Skip to content

Commit 772f3e6

Browse files
feat (calendar): add dateInfo (#546)
* feat: add dateInfo section on top of date in calendar * fix: add apt type * style: change color on selection * fix: tests * refactor: change snake case to camelcase * fix: css * merge: merge main * feat: add function | object support
1 parent 32a6aee commit 772f3e6

File tree

15 files changed

+479
-114
lines changed

15 files changed

+479
-114
lines changed

apps/www/src/app/examples/page.tsx

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Avatar,
55
AvatarGroup,
66
Button,
7+
Calendar,
78
Callout,
89
DatePicker,
910
Dialog,
@@ -45,7 +46,7 @@ const Page = () => {
4546
const [selectValue1, setSelectValue1] = useState('');
4647
const [selectValue2, setSelectValue2] = useState('');
4748
const [inputValue, setInputValue] = useState('');
48-
const [rangeValue, setRangeValue] = useState<any>({
49+
const [rangeValue, setRangeValue] = useState({
4950
from: dayjs('2027-11-15').toDate(),
5051
to: dayjs('2027-12-10').toDate()
5152
});
@@ -165,7 +166,6 @@ const Page = () => {
165166
onClear={() => setSearch1('')}
166167
/>
167168
<DatePicker
168-
side='bottom'
169169
dateFormat='D MMM YYYY'
170170
value={dayjs().add(16, 'year').toDate()}
171171
onSelect={(value: Date) => console.log(value)}
@@ -187,10 +187,14 @@ const Page = () => {
187187
/>
188188

189189
<RangePicker
190-
side='bottom'
191190
dateFormat='D MMM YYYY'
192191
value={rangeValue}
193-
onSelect={range => setRangeValue(range)}
192+
onSelect={range =>
193+
setRangeValue({
194+
from: range.from ?? new Date(),
195+
to: range.to ?? new Date()
196+
})
197+
}
194198
calendarProps={{
195199
captionLayout: 'dropdown',
196200
mode: 'range',
@@ -233,6 +237,143 @@ const Page = () => {
233237
}}
234238
/>
235239

240+
<Text
241+
size='large'
242+
weight='medium'
243+
style={{ marginTop: '32px', marginBottom: '16px' }}
244+
>
245+
Calendar with Date Info (Object)
246+
</Text>
247+
248+
<Calendar
249+
numberOfMonths={2}
250+
dateInfo={{
251+
[dayjs().format('DD-MM-YYYY')]: (
252+
<Flex
253+
align='center'
254+
gap={1}
255+
style={{
256+
fontSize: '8px',
257+
color: 'var(--rs-color-foreground-base-secondary)'
258+
}}
259+
>
260+
<BellIcon style={{ width: '8px', height: '8px' }} />
261+
<Text style={{ fontSize: '8px' }} color='secondary'>
262+
25%
263+
</Text>
264+
</Flex>
265+
),
266+
[dayjs().add(5, 'day').format('DD-MM-YYYY')]: (
267+
<Flex
268+
align='center'
269+
gap={1}
270+
style={{
271+
fontSize: '8px',
272+
color: 'var(--rs-color-foreground-base-secondary)'
273+
}}
274+
>
275+
<BellIcon style={{ width: '8px', height: '8px' }} />
276+
<Text style={{ fontSize: '8px' }} color='secondary'>
277+
25%
278+
</Text>
279+
</Flex>
280+
),
281+
[dayjs().add(10, 'day').format('DD-MM-YYYY')]: (
282+
<Flex
283+
align='center'
284+
gap={1}
285+
style={{
286+
fontSize: '8px',
287+
color: 'var(--rs-color-foreground-base-secondary)'
288+
}}
289+
>
290+
<BellIcon style={{ width: '8px', height: '8px' }} />
291+
<Text style={{ fontSize: '8px' }} color='secondary'>
292+
25%
293+
</Text>
294+
</Flex>
295+
)
296+
}}
297+
/>
298+
299+
<Text
300+
size='large'
301+
weight='medium'
302+
style={{ marginTop: '32px', marginBottom: '16px' }}
303+
>
304+
Calendar with Date Info (Function)
305+
</Text>
306+
307+
<Calendar
308+
numberOfMonths={2}
309+
dateInfo={date => {
310+
const today = new Date();
311+
const isToday =
312+
date.getDate() === today.getDate() &&
313+
date.getMonth() === today.getMonth() &&
314+
date.getFullYear() === today.getFullYear();
315+
316+
// Show info on Sundays
317+
if (date.getDay() === 0) {
318+
return (
319+
<Flex
320+
align='center'
321+
gap={1}
322+
style={{
323+
fontSize: '8px',
324+
color: 'var(--rs-color-foreground-base-secondary)'
325+
}}
326+
>
327+
<BellIcon style={{ width: '8px', height: '8px' }} />
328+
<Text style={{ fontSize: '8px' }} color='secondary'>
329+
Sun
330+
</Text>
331+
</Flex>
332+
);
333+
}
334+
335+
// Show info on 15th of any month
336+
if (date.getDate() === 15) {
337+
return (
338+
<Flex
339+
align='center'
340+
gap={1}
341+
style={{
342+
fontSize: '8px',
343+
color: 'var(--rs-color-foreground-base-secondary)'
344+
}}
345+
>
346+
<BellIcon style={{ width: '8px', height: '8px' }} />
347+
<Text style={{ fontSize: '8px' }} color='secondary'>
348+
15th
349+
</Text>
350+
</Flex>
351+
);
352+
}
353+
354+
// Show info for today
355+
if (isToday) {
356+
return (
357+
<Flex
358+
align='center'
359+
gap={1}
360+
style={{
361+
fontSize: '8px',
362+
color: 'var(--rs-color-foreground-base-secondary)'
363+
}}
364+
>
365+
<BellIcon style={{ width: '8px', height: '8px' }} />
366+
<Text style={{ fontSize: '8px' }} color='secondary'>
367+
Today
368+
</Text>
369+
</Flex>
370+
);
371+
}
372+
373+
return null;
374+
}}
375+
/>
376+
236377
<Text
237378
size='large'
238379
weight='medium'
Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,53 @@
1-
"use client";
1+
'use client';
22

33
export const preview = {
4-
type: "code",
4+
type: 'code',
55
tabs: [
66
{
7-
name: "Calendar",
8-
code: `<Calendar />`,
7+
name: 'Calendar',
8+
code: `<Calendar />`
99
},
1010
{
11-
name: "Range Picker",
11+
name: 'Range Picker',
1212
code: `
13-
<RangePicker inputFieldsProps={{ startDate: { size: "small" }, endDate: { size: "small" } }} />`,
13+
<RangePicker inputFieldsProps={{ startDate: { size: "small" }, endDate: { size: "small" } }} />`
1414
},
1515
{
16-
name: "Date Picker",
16+
name: 'Date Picker',
1717
code: `
1818
<Flex style={{height:200}}>
1919
<DatePicker />
20-
</Flex>`,
21-
},
22-
],
20+
</Flex>`
21+
}
22+
]
2323
};
2424

2525
export const calendarDemo = {
26-
type: "code",
26+
type: 'code',
2727
tabs: [
2828
{
29-
name: "Basic",
30-
code: `<Calendar numberOfMonths={2} />`,
29+
name: 'Basic',
30+
code: `<Calendar numberOfMonths={2} />`
3131
},
3232
{
33-
name: "With Loading",
34-
code: `<Calendar loadingData={true} numberOfMonths={2} />`,
35-
},
36-
],
33+
name: 'With Loading',
34+
code: `<Calendar loadingData={true} numberOfMonths={2} />`
35+
}
36+
]
3737
};
3838
export const rangePickerDemo = {
39-
type: "code",
39+
type: 'code',
4040
tabs: [
4141
{
42-
name: "Basic",
43-
code: `<RangePicker />`,
42+
name: 'Basic',
43+
code: `<RangePicker />`
4444
},
4545
{
46-
name: "Without Calendar Icon",
47-
code: `<RangePicker showCalendarIcon={false} />`,
46+
name: 'Without Calendar Icon',
47+
code: `<RangePicker showCalendarIcon={false} />`
4848
},
4949
{
50-
name: "Custom Trigger",
50+
name: 'Custom Trigger',
5151
code: `
5252
<RangePicker
5353
dateFormat="DD/MM/YYYY"
@@ -72,31 +72,56 @@ export const rangePickerDemo = {
7272
{startDate} - {endDate}
7373
</button>
7474
)}
75-
</RangePicker>`,
76-
},
77-
],
75+
</RangePicker>`
76+
}
77+
]
7878
};
7979
export const datePickerDemo = {
80-
type: "code",
80+
type: 'code',
8181
tabs: [
8282
{
83-
name: "Basic",
84-
code: `<DatePicker textFieldProps={{ size: "medium" }} />`,
83+
name: 'Basic',
84+
code: `<DatePicker textFieldProps={{ size: "medium" }} />`
8585
},
8686
{
87-
name: "Without Calendar Icon",
88-
code: `<DatePicker showCalendarIcon={false} textFieldProps={{ size: "medium" }} />`,
87+
name: 'Without Calendar Icon',
88+
code: `<DatePicker showCalendarIcon={false} textFieldProps={{ size: "medium" }} />`
8989
},
9090
{
91-
name: "Custom Trigger",
91+
name: 'Custom Trigger',
9292
code: `
9393
<DatePicker>
9494
{({ selectedDate }) => (
9595
<button>
9696
Selected: {selectedDate}
9797
</button>
9898
)}
99-
</DatePicker>`,
100-
},
101-
],
99+
</DatePicker>`
100+
}
101+
]
102+
};
103+
104+
export const dateInfoDemo = {
105+
type: 'code',
106+
tabs: [
107+
{
108+
name: 'With Date Info',
109+
code: `
110+
<Calendar
111+
numberOfMonths={2}
112+
dateInfo={{
113+
[dayjs().format('DD-MM-YYYY')]: (
114+
<Flex
115+
align='center'
116+
gap={2}
117+
style={{ fontSize: '8px', color: 'var(--rs-color-foreground-base-secondary)' }}
118+
>
119+
<BellIcon style={{ width: '8px', height: '8px' }} />
120+
<Text style={{ fontSize: '8px' }} color='secondary'>25%</Text>
121+
</Flex>
122+
)
123+
}}
124+
/>`
125+
}
126+
]
102127
};

apps/www/src/content/docs/components/calendar/index.mdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
datePickerDemo,
99
rangePickerDemo,
1010
calendarDemo,
11+
dateInfoDemo,
1112
} from "./demo.ts";
1213

1314
<Demo data={preview} />
@@ -42,6 +43,12 @@ Choose between different variants to convey different meanings or importance lev
4243

4344
<Demo data={calendarDemo} />
4445

46+
#### Custom Date Information
47+
48+
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.
49+
50+
<Demo data={dateInfoDemo} />
51+
4552
### Range Picker
4653

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

apps/www/src/content/docs/components/calendar/props.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,24 @@ export interface CalendarProps {
1111
/** Boolean to show loading state */
1212
loadingData?: boolean;
1313

14-
/** Object containing date-specific information like icons and text */
15-
dateInfo?: Record<string, unknown>;
14+
/**
15+
* Custom React components to render above each date.
16+
* Can be either:
17+
* - An object with date strings in "dd-MM-yyyy" format as keys
18+
* - A function that receives a Date and returns a ReactNode or null
19+
* The component will be rendered above the date number.
20+
*
21+
* @example
22+
* // Object approach (static data)
23+
* dateInfo={{ "15-01-2024": <div><Icon /> 17%</div> }}
24+
*
25+
* @example
26+
* // Function approach (dynamic logic)
27+
* dateInfo={(date) => date.getDay() === 0 ? <div>Sunday</div> : null}
28+
*/
29+
dateInfo?:
30+
| Record<string, React.ReactNode>
31+
| ((date: Date) => React.ReactNode | null);
1632

1733
/** Boolean to show days from previous/next months */
1834
showOutsideDays?: boolean;

packages/raystack/components/badge/badge.module.css

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,7 @@
5959
}
6060

6161
.badge-gradient {
62-
background: linear-gradient(
63-
to right,
64-
#AD00E933 0%,
65-
#EF040433 100%
66-
);
62+
background: linear-gradient(to right, #ad00e933 0%, #ef040433 100%);
6763
color: var(--rs-color-foreground-base-primary);
6864
}
6965

0 commit comments

Comments
 (0)