Range Calendar
Presents a calendar view tailored for selecting date ranges.
<script lang="ts">
import { RangeCalendar } from "$lib";
import { cn } from "@/utils";
import { CaretRight, CaretLeft } from "phosphor-svelte";
</script>
<RangeCalendar.Root
class="mt-6 rounded-15px border border-dark-10 bg-background p-[22px] shadow-card"
let:months
let:weekdays
weekdayFormat="short"
fixedWeeks={true}
>
<RangeCalendar.Header class="flex items-center justify-between">
<RangeCalendar.PrevButton
class="inline-flex items-center justify-center rounded-9px bg-background transition-all sq-10 hover:bg-muted active:scale-98"
>
<CaretLeft class="sq-6" />
</RangeCalendar.PrevButton>
<RangeCalendar.Heading class="text-[15px] font-medium" />
<RangeCalendar.NextButton
class="inline-flex items-center justify-center rounded-9px bg-background transition-all sq-10 hover:bg-muted active:scale-98"
>
<CaretRight class="sq-6" />
</RangeCalendar.NextButton>
</RangeCalendar.Header>
<div
class="flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0"
>
{#each months as month}
<RangeCalendar.Grid class="w-full border-collapse select-none space-y-1">
<RangeCalendar.GridHead>
<RangeCalendar.GridRow class="mb-1 flex w-full justify-between">
{#each weekdays as day}
<RangeCalendar.HeadCell
class="w-10 rounded-md text-xs !font-normal text-muted-foreground"
>
<div>{day.slice(0, 2)}</div>
</RangeCalendar.HeadCell>
{/each}
</RangeCalendar.GridRow>
</RangeCalendar.GridHead>
<RangeCalendar.GridBody>
{#each month.weeks as weekDates}
<RangeCalendar.GridRow class="flex w-full">
{#each weekDates as date}
<RangeCalendar.Cell
{date}
class="relative m-0 !p-0 text-center text-sm sq-10"
>
<RangeCalendar.Day
{date}
month={month.value}
class={cn(
"group relative inline-flex items-center justify-center whitespace-nowrap rounded-9px border border-transparent bg-background bg-transparent p-0 text-sm font-normal text-foreground transition-all sq-10 hover:border-foreground data-[disabled]:pointer-events-none data-[outside-month]:pointer-events-none data-[highlighted]:rounded-none data-[selection-end]:rounded-9px data-[selection-start]:rounded-9px data-[highlighted]:bg-muted data-[selected]:bg-muted data-[selection-end]:bg-foreground data-[selection-start]:bg-foreground data-[selected]:font-medium data-[selection-end]:font-medium data-[selection-start]:font-medium data-[disabled]:text-foreground/30 data-[selected]:text-foreground data-[selection-end]:text-background data-[selection-start]:text-background data-[unavailable]:text-muted-foreground data-[unavailable]:line-through data-[selected]:[&:not([data-selection-start])]:[&:not([data-selection-end])]:rounded-none"
)}
>
<div
class="absolute top-[5px] hidden rounded-full bg-foreground transition-all sq-1 group-data-[today]:block group-data-[selected]:bg-background"
/>
{date.day}
</RangeCalendar.Day>
</RangeCalendar.Cell>
{/each}
</RangeCalendar.GridRow>
{/each}
</RangeCalendar.GridBody>
</RangeCalendar.Grid>
{/each}
</div>
</RangeCalendar.Root>
<script lang="ts">
import { RangeCalendar } from "$lib";
import { cn } from "@/utils";
import { CaretRight, CaretLeft } from "phosphor-svelte";
</script>
<RangeCalendar.Root
class="mt-6 rounded-15px border border-dark-10 bg-background p-[22px] shadow-card"
let:months
let:weekdays
weekdayFormat="short"
fixedWeeks={true}
>
<RangeCalendar.Header class="flex items-center justify-between">
<RangeCalendar.PrevButton
class="inline-flex items-center justify-center rounded-9px bg-background transition-all sq-10 hover:bg-muted active:scale-98"
>
<CaretLeft class="sq-6" />
</RangeCalendar.PrevButton>
<RangeCalendar.Heading class="text-[15px] font-medium" />
<RangeCalendar.NextButton
class="inline-flex items-center justify-center rounded-9px bg-background transition-all sq-10 hover:bg-muted active:scale-98"
>
<CaretRight class="sq-6" />
</RangeCalendar.NextButton>
</RangeCalendar.Header>
<div
class="flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0"
>
{#each months as month}
<RangeCalendar.Grid class="w-full border-collapse select-none space-y-1">
<RangeCalendar.GridHead>
<RangeCalendar.GridRow class="mb-1 flex w-full justify-between">
{#each weekdays as day}
<RangeCalendar.HeadCell
class="w-10 rounded-md text-xs !font-normal text-muted-foreground"
>
<div>{day.slice(0, 2)}</div>
</RangeCalendar.HeadCell>
{/each}
</RangeCalendar.GridRow>
</RangeCalendar.GridHead>
<RangeCalendar.GridBody>
{#each month.weeks as weekDates}
<RangeCalendar.GridRow class="flex w-full">
{#each weekDates as date}
<RangeCalendar.Cell
{date}
class="relative m-0 !p-0 text-center text-sm sq-10"
>
<RangeCalendar.Day
{date}
month={month.value}
class={cn(
"group relative inline-flex items-center justify-center whitespace-nowrap rounded-9px border border-transparent bg-background bg-transparent p-0 text-sm font-normal text-foreground transition-all sq-10 hover:border-foreground data-[disabled]:pointer-events-none data-[outside-month]:pointer-events-none data-[highlighted]:rounded-none data-[selection-end]:rounded-9px data-[selection-start]:rounded-9px data-[highlighted]:bg-muted data-[selected]:bg-muted data-[selection-end]:bg-foreground data-[selection-start]:bg-foreground data-[selected]:font-medium data-[selection-end]:font-medium data-[selection-start]:font-medium data-[disabled]:text-foreground/30 data-[selected]:text-foreground data-[selection-end]:text-background data-[selection-start]:text-background data-[unavailable]:text-muted-foreground data-[unavailable]:line-through data-[selected]:[&:not([data-selection-start])]:[&:not([data-selection-end])]:rounded-none"
)}
>
<div
class="absolute top-[5px] hidden rounded-full bg-foreground transition-all sq-1 group-data-[today]:block group-data-[selected]:bg-background"
/>
{date.day}
</RangeCalendar.Day>
</RangeCalendar.Cell>
{/each}
</RangeCalendar.GridRow>
{/each}
</RangeCalendar.GridBody>
</RangeCalendar.Grid>
{/each}
</div>
</RangeCalendar.Root>
Su | Mo | Tu | We | Th | Fr | Sa |
---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 31 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
Structure
<script lang="ts">
import { RangeCalendar } from "bits-ui";
</script>
<RangeCalendar.Root let:months let:weekdays>
<RangeCalendar.Header>
<RangeCalendar.PrevButton />
<RangeCalendar.Heading />
<RangeCalendar.NextButton />
</RangeCalendar.Header>
{#each months as month}
<RangeCalendar.Grid>
<RangeCalendar.GridHead>
<RangeCalendar.GridRow>
{#each weekdays as day}
<RangeCalendar.HeadCell>
{day}
</RangeCalendar.HeadCell>
{/each}
</RangeCalendar.GridRow>
</RangeCalendar.GridHead>
<RangeCalendar.GridBody>
{#each month.weeks as weekDates}
<RangeCalendar.GridRow>
{#each weekDates as date}
<RangeCalendar.Cell {date}>
<RangeCalendar.Day {date} month={month.value} />
</RangeCalendar.Cell>
{/each}
</RangeCalendar.GridRow>
{/each}
</RangeCalendar.GridBody>
</RangeCalendar.Grid>
{/each}
</RangeCalendar.Root>
<script lang="ts">
import { RangeCalendar } from "bits-ui";
</script>
<RangeCalendar.Root let:months let:weekdays>
<RangeCalendar.Header>
<RangeCalendar.PrevButton />
<RangeCalendar.Heading />
<RangeCalendar.NextButton />
</RangeCalendar.Header>
{#each months as month}
<RangeCalendar.Grid>
<RangeCalendar.GridHead>
<RangeCalendar.GridRow>
{#each weekdays as day}
<RangeCalendar.HeadCell>
{day}
</RangeCalendar.HeadCell>
{/each}
</RangeCalendar.GridRow>
</RangeCalendar.GridHead>
<RangeCalendar.GridBody>
{#each month.weeks as weekDates}
<RangeCalendar.GridRow>
{#each weekDates as date}
<RangeCalendar.Cell {date}>
<RangeCalendar.Day {date} month={month.value} />
</RangeCalendar.Cell>
{/each}
</RangeCalendar.GridRow>
{/each}
</RangeCalendar.GridBody>
</RangeCalendar.Grid>
{/each}
</RangeCalendar.Root>
Component API
The root range calendar component which contains all other calendar components.
Property | Type | Description |
---|---|---|
value | DateRange | The selected date range. Default:
—— undefined |
onValueChange | function | A function that is called when the selected date range changes. Default:
—— undefined |
placeholder | DateValue | The placeholder date, which is used to determine what month to display when no date range is selected. This updates as the user navigates the calendar, and can be used to programatically control the calendar's view. Default:
—— undefined |
onPlaceholderChange | function | A function that is called when the placeholder date changes. Default:
—— undefined |
pagedNavigation | boolean | Whether or not to use paged navigation for the calendar. Paged navigation causes the previous and next buttons to navigate by the number of months displayed at once, rather than by one month. Default:
false |
preventDeselect | boolean | Whether or not to prevent the user from deselecting a date without selecting another date first. Default:
false |
weekdayFormat | enum | The format to use for the weekday strings provided via the Default:
'narrow' |
weekStartsOn | number | The day of the week to start the calendar on. 0 is Sunday, 1 is Monday, etc. Default:
0 |
calendarLabel | string | The accessible label for the calendar. Default:
—— undefined |
fixedWeeks | boolean | Whether or not to always display 6 weeks in the calendar. Default:
false |
isDateDisabled | function | A function that returns whether or not a date is disabled. Default:
—— undefined |
isDateUnavailable | function | A function that returns whether or not a date is unavailable. Default:
—— undefined |
maxValue | DateValue | The maximum date that can be selected. Default:
—— undefined |
minValue | DateValue | The minimum date that can be selected. Default:
—— undefined |
locale | string | The locale to use for formatting dates. Default:
—— undefined |
numberOfMonths | number | The number of months to display at once. Default:
1 |
disabled | boolean | Whether or not the accordion is disabled. Default:
false |
readonly | boolean | Whether or not the calendar is readonly. Default:
false |
initialFocus | boolean | If Default:
false |
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
months | Month[] | The current months to display in the calendar. Used to render the calendar. |
weekdays | string[] | The days of the week to display in the calendar, typically used within the table header. |
builder | object | The builder attributes and actions to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-invalid | —— | Present on the root element when the calendar is invalid. |
data-disabled | —— | Present on the root element when the calendar is disabled. |
data-readonly | —— | Present on the root element when the calendar is readonly. |
data-calendar-root | —— | Present on the root element. |
The header of the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-header | —— | Present on the header element. |
The heading of the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
builder | object | The builder attributes and actions to apply to the element if using the |
headingValue | string | The heading value. |
Data Attribute | Value | Description |
---|---|---|
data-calendar-heading | —— | Present on the heading element. |
The next button of the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
builder | object | The builder attributes and actions to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-next-button | —— | Present on the next button element. |
The previous button of the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
builder | object | The builder attributes and actions to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-prev-button | —— | Present on the prev button element. |
A cell in the calendar grid.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
date | DateValue | The date for the cell. Default:
—— undefined |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-disabled | —— | Present on the element when the date is disabled. |
data-calendar-cell | —— | Present on the cell element. |
A day in the calendar grid.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
date | DateValue | The date for the cell. Default:
—— undefined |
month | DateValue | The current month the date is being displayed in. Default:
—— undefined |
Slot Property | Type | Description |
---|---|---|
disabled | boolean | Whether or not the date is disabled. |
unavailable | boolean | Whether or not the date is unavailable. |
selected | boolean | Whether or not the date is selected. |
builder | object | The builder attributes and actions to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-disabled | —— | Present on the element when the date is disabled. |
data-selected | —— | Present on the element when the date is selected. |
data-unavailable | —— | Present on the element when the date is unavailable. |
data-value | —— | The date in the format "YYYY-MM-DD". |
data-today | —— | Present on the element when the date is today. |
data-outside-month | —— | Present on the element when the date is outside the current month. |
data-outside-visible-months | —— | Present on the element when the date is outside the visible months. |
data-selection-start | —— | Present on the element when the date is the start of the selection. |
data-selection-end | —— | Present on the element when the date is the end of the selection. |
data-highlighted | —— | Present on the element when the date is in the range as its still being selected. |
data-focused | —— | Present on the element when the date is focused. |
data-calendar-day | —— | Present on the day element. |
The grid of dates in the calendar, typically representing a month.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
builder | object | The builder attributes and actions to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-grid | —— | Present on the grid element. |
The body of the grid of dates in the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-grid-body | —— | Present on the grid body element. |
The head of the grid of dates in the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-grid-head | —— | Present on the grid head element. |
A row in the grid of dates in the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-grid-row | —— | Present on the grid row element. |
A cell in the head of the grid of dates in the calendar.
Property | Type | Description |
---|---|---|
asChild | boolean | Whether to use render delegation with this component or not. Default:
false |
Slot Property | Type | Description |
---|---|---|
attrs | object | Additional attributes to apply to the element if using the |
Data Attribute | Value | Description |
---|---|---|
data-calendar-head-cell | —— | Present on the head cell element. |