Skip to content

Commit 7526f36

Browse files
authored
docs: more calendar examples (#1272)
1 parent fa036b0 commit 7526f36

File tree

5 files changed

+254
-3
lines changed

5 files changed

+254
-3
lines changed

docs/content/components/calendar.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Displays dates and days of the week, facilitating date-related inte
44
---
55

66
<script>
7-
import { APISection, ComponentPreviewV2, CalendarDemo, Callout } from '$lib/components'
7+
import { APISection, ComponentPreviewV2, CalendarDemo, CalendarDemoSelects, CalendarDemoPresets, Callout } from '$lib/components'
88
let { schemas } = $props()
99
</script>
1010

@@ -369,4 +369,30 @@ To achieve this, you can use the `placeholder` prop to set the month of the the
369369

370370
Updating the `placeholder` will update the calendar view to reflect the new month.
371371

372+
## Examples
373+
374+
### Month and Year Selects
375+
376+
This example demonstrates how to use the `placeholder` prop to set the month and year of the calendar view programmatically.
377+
378+
<ComponentPreviewV2 name="calendar-demo-selects" componentName="Calendar Selects">
379+
380+
{#snippet preview()}
381+
<CalendarDemoSelects />
382+
{/snippet}
383+
384+
</ComponentPreviewV2>
385+
386+
### Preset Dates
387+
388+
This example demonstrates how to programatically set the `value` of the calendar to a specific date when a user presses a button.
389+
390+
<ComponentPreviewV2 name="calendar-demo-presets" componentName="Calendar Presets">
391+
392+
{#snippet preview()}
393+
<CalendarDemoPresets />
394+
{/snippet}
395+
396+
</ComponentPreviewV2>
397+
372398
<APISection {schemas} />
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<script lang="ts">
2+
import { Button, Calendar, Separator } from "bits-ui";
3+
import CaretLeft from "phosphor-svelte/lib/CaretLeft";
4+
import CaretRight from "phosphor-svelte/lib/CaretRight";
5+
import { getLocalTimeZone, today } from "@internationalized/date";
6+
7+
const currentDate = today(getLocalTimeZone());
8+
9+
let value = $state(currentDate);
10+
11+
const presets = [
12+
{
13+
label: "Today",
14+
onclick: () => {
15+
value = currentDate;
16+
},
17+
},
18+
{
19+
label: "Tomorrow",
20+
onclick: () => {
21+
value = currentDate.add({ days: 1 });
22+
},
23+
},
24+
{
25+
label: "In 3 days",
26+
onclick: () => {
27+
value = currentDate.add({ days: 3 });
28+
},
29+
},
30+
{
31+
label: "In a week",
32+
onclick: () => {
33+
value = currentDate.add({ days: 7 });
34+
},
35+
},
36+
{
37+
label: "In a month",
38+
onclick: () => {
39+
value = currentDate.add({ months: 1 });
40+
},
41+
},
42+
{
43+
label: "In a year",
44+
onclick: () => {
45+
value = currentDate.add({ years: 1 });
46+
},
47+
},
48+
];
49+
</script>
50+
51+
<div
52+
class="border-dark-10 bg-background-alt shadow-card mt-6 flex max-w-[324px] flex-col gap-4 rounded-[15px] border p-[22px]"
53+
>
54+
<Calendar.Root weekdayFormat="short" fixedWeeks={true} type="single" bind:value>
55+
{#snippet children({ months, weekdays })}
56+
<Calendar.Header class="flex items-center justify-between">
57+
<Calendar.PrevButton
58+
class="rounded-9px bg-background-alt hover:bg-muted inline-flex size-10 items-center justify-center active:scale-[0.98] active:transition-all"
59+
>
60+
<CaretLeft class="size-6" />
61+
</Calendar.PrevButton>
62+
<Calendar.Heading class="text-[15px] font-medium" />
63+
<Calendar.NextButton
64+
class="rounded-9px bg-background-alt hover:bg-muted inline-flex size-10 items-center justify-center active:scale-[0.98] active:transition-all"
65+
>
66+
<CaretRight class="size-6" />
67+
</Calendar.NextButton>
68+
</Calendar.Header>
69+
<div class="flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0">
70+
{#each months as month, i (i)}
71+
<Calendar.Grid class="w-full border-collapse select-none space-y-1">
72+
<Calendar.GridHead>
73+
<Calendar.GridRow class="mb-1 flex w-full justify-between">
74+
{#each weekdays as day}
75+
<Calendar.HeadCell
76+
class="text-muted-foreground font-normal! w-10 rounded-md text-xs"
77+
>
78+
<div>{day.slice(0, 2)}</div>
79+
</Calendar.HeadCell>
80+
{/each}
81+
</Calendar.GridRow>
82+
</Calendar.GridHead>
83+
<Calendar.GridBody>
84+
{#each month.weeks as weekDates}
85+
<Calendar.GridRow class="flex w-full">
86+
{#each weekDates as date}
87+
<Calendar.Cell
88+
{date}
89+
month={month.value}
90+
class="p-0! relative size-10 text-center text-sm"
91+
>
92+
<Calendar.Day
93+
class="rounded-9px text-foreground hover:border-foreground data-selected:bg-foreground data-disabled:text-foreground/30 data-selected:text-background data-unavailable:text-muted-foreground data-disabled:pointer-events-none data-outside-month:pointer-events-none data-selected:font-medium data-unavailable:line-through group relative inline-flex size-10 items-center justify-center whitespace-nowrap border border-transparent bg-transparent p-0 text-sm font-normal"
94+
>
95+
<div
96+
class="bg-foreground group-data-selected:bg-background group-data-today:block absolute top-[5px] hidden size-1 rounded-full"
97+
></div>
98+
{date.day}
99+
</Calendar.Day>
100+
</Calendar.Cell>
101+
{/each}
102+
</Calendar.GridRow>
103+
{/each}
104+
</Calendar.GridBody>
105+
</Calendar.Grid>
106+
{/each}
107+
</div>
108+
{/snippet}
109+
</Calendar.Root>
110+
<Separator.Root class="bg-dark-10 h-px w-full" />
111+
<div class="flex w-full flex-row flex-wrap items-center gap-2">
112+
{#each presets as preset}
113+
<Button.Root
114+
class="border-dark-10 text-foreground shadow-mini hover:bg-foreground/5 inline-flex h-8 flex-1 select-none items-center justify-center whitespace-nowrap rounded-md border px-[17px] text-xs font-medium transition-all active:scale-[0.98]"
115+
onclick={preset.onclick}
116+
>
117+
<span class="sr-only"> Set date to </span>
118+
{preset.label}
119+
</Button.Root>
120+
{/each}
121+
</div>
122+
</div>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<script lang="ts">
2+
import { Calendar } from "bits-ui";
3+
import { DateFormatter, getLocalTimeZone, today } from "@internationalized/date";
4+
5+
const currentDate = today(getLocalTimeZone());
6+
let value = $state(today(getLocalTimeZone()));
7+
8+
const formatter = new DateFormatter("en-US", {
9+
month: "long",
10+
});
11+
12+
const monthList = Array.from({ length: 12 }, (_, i) => {
13+
const month = currentDate.set({ month: i + 1 });
14+
return {
15+
value: month.month,
16+
label: formatter.format(month.toDate(getLocalTimeZone())),
17+
};
18+
});
19+
20+
const currentYear = new Date().getFullYear();
21+
const yearList = Array.from({ length: 30 }, (_, i) => currentYear - i);
22+
let placeholder = $state(currentDate);
23+
</script>
24+
25+
<Calendar.Root
26+
class="border-dark-10 bg-background-alt shadow-card mt-6 rounded-[15px] border p-[22px]"
27+
weekdayFormat="short"
28+
fixedWeeks={true}
29+
bind:placeholder
30+
type="single"
31+
bind:value
32+
>
33+
{#snippet children({ months, weekdays })}
34+
<Calendar.Header class="flex items-center justify-between gap-3">
35+
<select
36+
aria-label="Select month"
37+
value={placeholder.month}
38+
class="w-full"
39+
onchange={(e) => {
40+
const month = parseInt(e.currentTarget.value);
41+
placeholder = placeholder.set({ month });
42+
}}
43+
>
44+
{#each monthList as month}
45+
<option value={month.value}>{month.label}</option>
46+
{/each}
47+
</select>
48+
<select
49+
aria-label="Select year"
50+
value={placeholder.year}
51+
onchange={(e) => {
52+
const year = parseInt(e.currentTarget.value);
53+
placeholder = placeholder.set({ year });
54+
}}
55+
>
56+
{#each yearList as year}
57+
<option value={year}>{year}</option>
58+
{/each}
59+
</select>
60+
</Calendar.Header>
61+
<div class="flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0">
62+
{#each months as month, i (i)}
63+
<Calendar.Grid class="w-full border-collapse select-none space-y-1">
64+
<Calendar.GridHead>
65+
<Calendar.GridRow class="mb-1 flex w-full justify-between">
66+
{#each weekdays as day}
67+
<Calendar.HeadCell
68+
class="text-muted-foreground font-normal! w-10 rounded-md text-xs"
69+
>
70+
<div>{day.slice(0, 2)}</div>
71+
</Calendar.HeadCell>
72+
{/each}
73+
</Calendar.GridRow>
74+
</Calendar.GridHead>
75+
<Calendar.GridBody>
76+
{#each month.weeks as weekDates}
77+
<Calendar.GridRow class="flex w-full">
78+
{#each weekDates as date}
79+
<Calendar.Cell
80+
{date}
81+
month={month.value}
82+
class="p-0! relative size-10 text-center text-sm"
83+
>
84+
<Calendar.Day
85+
class="rounded-9px text-foreground hover:border-foreground data-selected:bg-foreground data-disabled:text-foreground/30 data-selected:text-background data-unavailable:text-muted-foreground data-disabled:pointer-events-none data-outside-month:pointer-events-none data-selected:font-medium data-unavailable:line-through group relative inline-flex size-10 items-center justify-center whitespace-nowrap border border-transparent bg-transparent p-0 text-sm font-normal"
86+
>
87+
<div
88+
class="bg-foreground group-data-selected:bg-background group-data-today:block absolute top-[5px] hidden size-1 rounded-full"
89+
></div>
90+
{date.day}
91+
</Calendar.Day>
92+
</Calendar.Cell>
93+
{/each}
94+
</Calendar.GridRow>
95+
{/each}
96+
</Calendar.GridBody>
97+
</Calendar.Grid>
98+
{/each}
99+
</div>
100+
{/snippet}
101+
</Calendar.Root>

docs/src/lib/components/demos/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export { default as AspectRatioDemo } from "./aspect-ratio-demo.svelte";
88
export { default as AvatarDemo } from "./avatar-demo.svelte";
99
export { default as ButtonDemo } from "./button-demo.svelte";
1010
export { default as CalendarDemo } from "./calendar-demo.svelte";
11+
export { default as CalendarDemoSelects } from "./calendar-demo-selects.svelte";
12+
export { default as CalendarDemoPresets } from "./calendar-demo-presets.svelte";
1113
export { default as CheckboxDemo } from "./checkbox-demo.svelte";
1214
export { default as CheckboxDemoCustom } from "./checkbox-demo-custom.svelte";
1315
export { default as CheckboxDemoGroup } from "./checkbox-demo-group.svelte";
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import DemoContainer from "$lib/components/demo-container.svelte";
3-
import AccordionDemoCheckoutSteps from "$lib/components/demos/accordion-demo-checkout-steps.svelte";
3+
import CalendarDemoPresets from "$lib/components/demos/calendar-demo-presets.svelte";
44
</script>
55

66
<div class="w-full max-w-[756px]">
77
<DemoContainer>
8-
<AccordionDemoCheckoutSteps />
8+
<CalendarDemoPresets />
99
</DemoContainer>
1010
</div>

0 commit comments

Comments
 (0)