Calendar

CalendarGitLab
Um componente de calendário para selecionar datas únicas, múltiplas datas ou intervalos de datas.

Uso

Use a diretiva v-model para controlar a data selecionada.

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
1
2
3
4
5
6
7
8
9
10
11
12
Event Date, February 2022
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 2, 3))
</script>

<template>
  <NCalendar v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 2, 3))
</script>

<template>
  <NCalendar v-model="value" />
</template>

Use a prop default-value para definir o valor inicial quando você não precisa controlar o estado.

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
1
2
3
4
5
6
7
8
9
10
11
12
Event Date, February 2022
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const defaultValue = shallowRef(new CalendarDate(2022, 2, 6))
</script>

<template>
  <NCalendar :default-value="defaultValue" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const defaultValue = shallowRef(new CalendarDate(2022, 2, 6))
</script>

<template>
  <NCalendar :default-value="defaultValue" />
</template>
Este componente usa o pacote @internationalized/date para formatação sensível ao locale. O formato da data é determinado pela prop locale do componente App.
Este componente usa o pacote @internationalized/date para formatação sensível ao locale. O formato da data é determinado pela prop locale do componente App.

Tipo 4.9+

Use a prop type para alterar o que o calendário seleciona. O padrão é date.

Ao usar date, clique no título para alternar da visualização de dia para a de mês e depois de ano, para uma navegação rápida, e então retorne para escolher uma data.

Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
Month Picker, 2022
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 2, 1))
</script>

<template>
  <NCalendar type="month" v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 2, 1))
</script>

<template>
  <NCalendar type="month" v-model="value" />
</template>

Use type="year" para renderizar um seletor de ano independente.

2020 - 2031
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
Year Picker, 2020 - 2031
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 1, 1))
</script>

<template>
  <NCalendar type="year" v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef(new CalendarDate(2022, 1, 1))
</script>

<template>
  <NCalendar type="year" v-model="value" />
</template>

Múltiplo

Use a prop multiple para permitir múltiplas seleções.

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
1
2
3
4
5
6
7
8
9
10
11
12
Event Date, February 2022
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef([
  new CalendarDate(2022, 2, 4),
  new CalendarDate(2022, 2, 6),
  new CalendarDate(2022, 2, 8)
])
</script>

<template>
  <NCalendar multiple v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef([
  new CalendarDate(2022, 2, 4),
  new CalendarDate(2022, 2, 6),
  new CalendarDate(2022, 2, 8)
])
</script>

<template>
  <NCalendar multiple v-model="value" />
</template>

Intervalo

Use a prop range para selecionar um intervalo de datas.

Event Date, February 2022
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
1
2
3
4
5
6
7
8
9
10
11
12
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef({
  start: new CalendarDate(2022, 2, 3),
  end: new CalendarDate(2022, 2, 20)
})
</script>

<template>
  <NCalendar range v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef({
  start: new CalendarDate(2022, 2, 3),
  end: new CalendarDate(2022, 2, 20)
})
</script>

<template>
  <NCalendar range v-model="value" />
</template>

A prop range também funciona com type="month" e type="year", permitindo selecionar um intervalo de meses ou anos.

Month Picker, 2022
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'

const value = shallowRef({ start: new CalendarDate(2022, 2, 1), end: new CalendarDate(2022, 6, 1) })
</script>

<template>
  <NCalendar type="month" range v-model="value" />
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
import { CalendarDate } from '@internationalized/date'

const value = shallowRef({ start: new CalendarDate(2022, 2, 1), end: new CalendarDate(2022, 6, 1) })
</script>

<template>
  <NCalendar type="month" range v-model="value" />
</template>

Número de meses

Use a prop numberOfMonths para alterar o número de meses no calendário.

28
29
30
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
31
1
2
3
4
5
6
7
8
26
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
31
1
2
3
4
5
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
8
9
10
Event Date, July - September 2026
<template>
  <NCalendar :number-of-months="3" />
</template>

Controles de mês

Use a prop month-controls para exibir os controles de mês. O padrão é true.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar :month-controls="false" />
</template>

Use as props prev-month e next-month para sobrescrever os botões de mês.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar
    :prev-month="{
      color: 'primary',
      variant: 'soft'
    }"
    :next-month="{
      color: 'primary',
      variant: 'soft'
    }"
  />
</template>

Controles de ano

Use a prop year-controls para exibir os controles de ano. O padrão é true.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar :year-controls="false" />
</template>

Use as props prev-year e next-year para sobrescrever os botões de ano.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar
    :prev-year="{
      color: 'primary',
      variant: 'soft'
    }"
    :next-year="{
      color: 'primary',
      variant: 'soft'
    }"
  />
</template>

Controle de visualização 4.9+

Use a prop view-control para tornar o título um botão que alterna entre as visualizações de dia, mês e ano. O padrão é true.

July 2026
28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar :view-control="false" />
</template>

Defina a prop view-control como um objeto para sobrescrever o botão do título.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar
    :view-control="{
      color: 'primary',
      variant: 'soft'
    }"
  />
</template>

Semanas fixas

Use a prop fixed-weeks para exibir o calendário com semanas fixas.

28
29
30
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
31
1
Event Date, July 2026
<template>
  <NCalendar :fixed-weeks="false" />
</template>

Números das semanas 4.4+

Use a prop week-numbers para exibir os números das semanas no calendário.

27
28
29
30
1
2
3
4
28
5
6
7
8
9
10
11
29
12
13
14
15
16
17
18
30
19
20
21
22
23
24
25
31
26
27
28
29
30
31
1
32
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar week-numbers />
</template>

Cor

Use a prop color para alterar a cor do calendário.

Event Date, February 2022
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
1
2
3
4
5
6
7
8
9
10
11
12
<template>
  <NCalendar color="neutral" />
</template>

Variante

Use a prop variant para alterar a variante do calendário.

Event Date, February 2022
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
1
2
3
4
5
6
7
8
9
10
11
12
<template>
  <NCalendar variant="subtle" />
</template>

Tamanho

Use a prop size para alterar o tamanho do calendário.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar size="xl" />
</template>

Desabilitado

Use a prop disabled para desabilitar o calendário.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026
<template>
  <NCalendar disabled />
</template>

Exemplos

Com eventos de chip

Use o componente Chip para adicionar eventos a dias específicos.

26
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
31
1
2
3
4
5
Event Date, January 2022

Com datas desabilitadas

Use a prop is-date-disabled com uma função para marcar datas específicas como desabilitadas. Ao usar type="month" ou type="year", use a prop is-month-disabled ou is-year-disabled.

Event Date, January 2022
26
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
31
1
2
3
4
5

Com datas indisponíveis

Use a prop is-date-unavailable com uma função para marcar datas específicas como indisponíveis. Ao usar type="month" ou type="year", use a prop is-month-unavailable ou is-year-unavailable.

Event Date, January 2022
26
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
31
1
2
3
4
5

Com datas mín/máx

Use as props min-value e max-value para limitar as datas.

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
Event Date, September 2023

Com outros sistemas de calendário

Você pode usar outros calendários do @internationalized/date para implementar um sistema de calendário diferente.

24
25
26
27
28
29
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
Event Date, Tishri 5781
Você pode conferir todos os calendários disponíveis na documentação do @internationalized/date.

Com controles externos

Você pode controlar o calendário com controles externos manipulando a data passada no v-model.

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
8
9
10
Event Date, April 2025

Com a data de hoje

Use a função today do @internationalized/date com getLocalTimeZone para definir o valor como a data atual.

28
29
30
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
31
1
2
3
4
5
6
7
8
Event Date, July 2026

Como seletor de data

Use a Button and a Popover component to create a date picker.

Como seletor de intervalo de datas

Use a Button and a Popover component to create a date range picker with preset ranges.

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

type'date' "date" | "month" | "year"

The type of picker.

  • date renders a day calendar whose heading can switch to a month then year view.
  • month renders a standalone month picker.
  • year renders a standalone year picker.
nextYearIconappConfig.ui.icons.chevronDoubleRightany

The icon to use for the next year control.

nextYear Omit<ButtonProps, LinkPropsKeys>

Configure the next year button. { color: 'neutral', variant: 'ghost' }

nextMonthIconappConfig.ui.icons.chevronRightany

The icon to use for the next month control.

nextMonth Omit<ButtonProps, LinkPropsKeys>

Configure the next month button. { color: 'neutral', variant: 'ghost' }

prevYearIconappConfig.ui.icons.chevronDoubleLeftany

The icon to use for the previous year control.

prevYear Omit<ButtonProps, LinkPropsKeys>

Configure the prev year button. { color: 'neutral', variant: 'ghost' }

prevMonthIconappConfig.ui.icons.chevronLeftany

The icon to use for the previous month control.

prevMonth Omit<ButtonProps, LinkPropsKeys>

Configure the prev month button. { color: 'neutral', variant: 'ghost' }

viewControltrueboolean | Omit<ButtonProps, LinkPropsKeys>

Whether to make the heading a button that switches between the day, month and year views. Has no effect when type is year. Can be an object to override the button props. { color: 'neutral', variant: 'ghost', block: true }

color'primary' "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral"
variant'solid' "solid" | "outline" | "soft" | "subtle"
size'md' "xs" | "sm" | "md" | "lg" | "xl"
range R

Whether or not a range of dates can be selected

multiple M

Whether or not multiple dates can be selected

monthControlstrueboolean

Show month controls

yearControlstrueboolean

Show year controls

defaultValueCalendarDate | CalendarDateTime | ZonedDateTime | DateRange | DateValue[]
modelValuenull | CalendarDate | CalendarDateTime | ZonedDateTime | DateRange | DateValue[]
weekNumbersboolean
defaultPlaceholderCalendarDate | CalendarDateTime | ZonedDateTime
placeholderCalendarDate | CalendarDateTime | ZonedDateTime
allowNonContiguousRangesboolean

When combined with isDateUnavailable, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected.

pagedNavigationboolean

This property causes the previous and next buttons to navigate by the number of months displayed at once, rather than one month

preventDeselectboolean

Whether or not to prevent the user from deselecting a date without selecting another date first

maximumDays number

The maximum number of days that can be selected in a range

weekStartsOn 0 | 1 | 2 | 4 | 5 | 3 | 6

The day of the week to start the calendar on

weekdayFormat "narrow" | "short" | "long"

The format to use for the weekday strings provided via the weekdays slot prop

fixedWeekstrueboolean

Whether or not to always display 6 weeks in the calendar

maxValueCalendarDate | CalendarDateTime | ZonedDateTime
minValueCalendarDate | CalendarDateTime | ZonedDateTime
locale string

The locale to use for formatting dates

numberOfMonths number

The number of months to display at once

disabledboolean

Whether or not the calendar is disabled

readonlyboolean

Whether or not the calendar is readonly

initialFocusboolean

If true, the calendar will focus the selected day, today, or the first day of the month depending on what is visible when the calendar is mounted

isDateDisabled (date: DateValue): boolean

A function that returns whether or not a date is disabled

isDateUnavailable (date: DateValue): boolean

A function that returns whether or not a date is unavailable

isDateHighlightable (date: DateValue): boolean

A function that returns whether or not a date is hightable

nextPage (placeholder: DateValue): DateValue

A function that returns the next page of the calendar. It receives the current placeholder as an argument inside the component.

prevPage (placeholder: DateValue): DateValue

A function that returns the previous page of the calendar. It receives the current placeholder as an argument inside the component.

disableDaysOutsideCurrentViewboolean

Whether or not to disable days outside the current view.

fixedDate "start" | "end"

Which part of the range should be fixed

isMonthDisabled (date: DateValue): boolean

A function that returns whether or not a month is disabled

isMonthUnavailable (date: DateValue): boolean

A function that returns whether or not a month is unavailable

isYearDisabled (date: DateValue): boolean

A function that returns whether or not a year is disabled

isYearUnavailable (date: DateValue): boolean

A function that returns whether or not a year is unavailable

ui { root?: SlotClass; header?: SlotClass; body?: SlotClass; heading?: SlotClass; headingLabel?: SlotClass; grid?: SlotClass; gridRow?: SlotClass; gridWeekDaysRow?: SlotClass; gridBody?: SlotClass; headCell?: SlotClass; headCellWeek?: SlotClass; cell?: SlotClass; cellTrigger?: SlotClass; cellWeek?: SlotClass; }

Slots

Slot Type
heading{ value: string; view: CalendarView; date: DateValue; setView: (view: CalendarView) => void; setPlaceholder: (date: DateValue) => void; }
dayPick<CalendarCellTriggerProps, "day">
week-day{ day: string; }
month-cell{ month: DateValue; selected: boolean; disabled: boolean; }
year-cell{ year: DateValue; selected: boolean; disabled: boolean; }

Emits

Event Type
update:modelValue[value: CalendarModelValue<R, M>]
update:placeholder[date: DateValue]
update:validModelValue[date: DateRange]
update:startValue[date: DateValue | undefined]

Tema

app.config.ts
export default defineAppConfig({
  ui: {
    calendar: {
      slots: {
        root: '',
        header: 'flex items-center justify-between',
        body: 'flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0',
        heading: 'flex-1 min-w-0 text-center',
        headingLabel: 'font-medium block truncate p-1.5',
        grid: 'w-full border-collapse select-none space-y-1 focus:outline-none',
        gridRow: 'grid',
        gridWeekDaysRow: 'mb-1 grid w-full grid-cols-7',
        gridBody: 'grid',
        headCell: 'rounded-md',
        headCellWeek: 'rounded-md text-muted',
        cell: 'relative text-center',
        cellTrigger: [
          'm-0.5 relative flex items-center justify-center whitespace-nowrap focus-visible:outline-3 data-disabled:text-muted data-unavailable:line-through data-unavailable:text-muted data-unavailable:pointer-events-none data-today:font-semibold',
          'transition'
        ],
        cellWeek: 'relative text-center text-muted'
      },
      variants: {
        color: {
          primary: {
            headCell: 'text-primary',
            cellTrigger: 'outline-primary/25'
          },
          secondary: {
            headCell: 'text-secondary',
            cellTrigger: 'outline-secondary/25'
          },
          accent: {
            headCell: 'text-accent',
            cellTrigger: 'outline-accent/25'
          },
          success: {
            headCell: 'text-success',
            cellTrigger: 'outline-success/25'
          },
          info: {
            headCell: 'text-info',
            cellTrigger: 'outline-info/25'
          },
          warning: {
            headCell: 'text-warning',
            cellTrigger: 'outline-warning/25'
          },
          error: {
            headCell: 'text-error',
            cellTrigger: 'outline-error/25'
          },
          neutral: {
            headCell: 'text-highlighted',
            cellTrigger: 'outline-inverted/25'
          }
        },
        variant: {
          solid: '',
          outline: '',
          soft: '',
          subtle: ''
        },
        size: {
          xs: {
            headingLabel: 'text-xs',
            cell: 'text-xs',
            cellWeek: 'text-xs',
            headCell: 'text-[10px]',
            headCellWeek: 'text-[10px]',
            body: 'space-y-2 pt-2'
          },
          sm: {
            headingLabel: 'text-xs',
            headCell: 'text-xs',
            headCellWeek: 'text-xs',
            cellWeek: 'text-xs',
            cell: 'text-xs'
          },
          md: {
            headingLabel: 'text-sm',
            headCell: 'text-xs',
            headCellWeek: 'text-xs',
            cellWeek: 'text-xs',
            cell: 'text-sm'
          },
          lg: {
            headingLabel: 'text-md',
            headCell: 'text-md',
            headCellWeek: 'text-md'
          },
          xl: {
            headingLabel: 'text-lg',
            headCell: 'text-lg',
            headCellWeek: 'text-lg'
          }
        },
        view: {
          day: {
            gridRow: 'grid-cols-7 place-items-center',
            cellTrigger: 'rounded-full data-outside-view:text-muted'
          },
          month: {
            gridRow: 'grid-cols-4',
            cellTrigger: 'rounded-md'
          },
          year: {
            gridRow: 'grid-cols-4',
            cellTrigger: 'rounded-md'
          }
        },
        weekNumbers: {
          true: ''
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: 'solid',
          class: {
            cellTrigger: 'data-selected:bg-primary data-selected:text-inverted data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
          }
        },
        {
          color: 'primary',
          variant: 'outline',
          class: {
            cellTrigger: 'data-selected:ring data-selected:ring-inset data-selected:ring-primary/50 data-selected:text-primary data-selected:focus-visible:ring-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/10 hover:not-data-selected:bg-primary/10'
          }
        },
        {
          color: 'primary',
          variant: 'soft',
          class: {
            cellTrigger: 'data-selected:bg-primary/10 data-selected:text-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
          }
        },
        {
          color: 'primary',
          variant: 'subtle',
          class: {
            cellTrigger: 'data-selected:bg-primary/10 data-selected:text-primary data-selected:ring data-selected:ring-inset data-selected:ring-primary/25 data-selected:focus-visible:ring-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
          }
        },
        {
          color: 'neutral',
          variant: 'solid',
          class: {
            cellTrigger: 'data-selected:bg-inverted data-selected:text-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
          }
        },
        {
          color: 'neutral',
          variant: 'outline',
          class: {
            cellTrigger: 'data-selected:ring data-selected:ring-inset data-selected:ring-accented data-selected:text-default data-selected:bg-default data-selected:focus-visible:ring-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/10 hover:not-data-selected:bg-inverted/10'
          }
        },
        {
          color: 'neutral',
          variant: 'soft',
          class: {
            cellTrigger: 'data-selected:bg-elevated data-selected:text-default data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
          }
        },
        {
          color: 'neutral',
          variant: 'subtle',
          class: {
            cellTrigger: 'data-selected:bg-elevated data-selected:text-default data-selected:ring data-selected:ring-inset data-selected:ring-accented data-selected:focus-visible:ring-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
          }
        },
        {
          size: 'xs',
          view: 'day',
          class: {
            cellTrigger: 'size-7'
          }
        },
        {
          size: 'sm',
          view: 'day',
          class: {
            cellTrigger: 'size-7'
          }
        },
        {
          size: 'md',
          view: 'day',
          class: {
            cellTrigger: 'size-8'
          }
        },
        {
          size: 'lg',
          view: 'day',
          class: {
            cellTrigger: 'size-9 text-md'
          }
        },
        {
          size: 'xl',
          view: 'day',
          class: {
            cellTrigger: 'size-10 text-lg'
          }
        },
        {
          size: 'xs',
          view: [
            'month',
            'year'
          ],
          class: {
            cellTrigger: 'h-7 px-2'
          }
        },
        {
          size: 'sm',
          view: [
            'month',
            'year'
          ],
          class: {
            cellTrigger: 'h-7 px-2'
          }
        },
        {
          size: 'md',
          view: [
            'month',
            'year'
          ],
          class: {
            cellTrigger: 'h-8 px-3'
          }
        },
        {
          size: 'lg',
          view: [
            'month',
            'year'
          ],
          class: {
            cellTrigger: 'h-9 px-4 text-md'
          }
        },
        {
          size: 'xl',
          view: [
            'month',
            'year'
          ],
          class: {
            cellTrigger: 'h-10 px-5 text-lg'
          }
        },
        {
          view: 'day',
          weekNumbers: true,
          class: {
            gridRow: 'grid-cols-8',
            gridWeekDaysRow: 'grid-cols-8 [&>*:first-child]:col-start-2'
          }
        }
      ],
      defaultVariants: {
        size: 'md',
        color: 'accent',
        variant: 'solid',
        view: 'day'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        calendar: {
          slots: {
            root: '',
            header: 'flex items-center justify-between',
            body: 'flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0',
            heading: 'flex-1 min-w-0 text-center',
            headingLabel: 'font-medium block truncate p-1.5',
            grid: 'w-full border-collapse select-none space-y-1 focus:outline-none',
            gridRow: 'grid',
            gridWeekDaysRow: 'mb-1 grid w-full grid-cols-7',
            gridBody: 'grid',
            headCell: 'rounded-md',
            headCellWeek: 'rounded-md text-muted',
            cell: 'relative text-center',
            cellTrigger: [
              'm-0.5 relative flex items-center justify-center whitespace-nowrap focus-visible:outline-3 data-disabled:text-muted data-unavailable:line-through data-unavailable:text-muted data-unavailable:pointer-events-none data-today:font-semibold',
              'transition'
            ],
            cellWeek: 'relative text-center text-muted'
          },
          variants: {
            color: {
              primary: {
                headCell: 'text-primary',
                cellTrigger: 'outline-primary/25'
              },
              secondary: {
                headCell: 'text-secondary',
                cellTrigger: 'outline-secondary/25'
              },
              accent: {
                headCell: 'text-accent',
                cellTrigger: 'outline-accent/25'
              },
              success: {
                headCell: 'text-success',
                cellTrigger: 'outline-success/25'
              },
              info: {
                headCell: 'text-info',
                cellTrigger: 'outline-info/25'
              },
              warning: {
                headCell: 'text-warning',
                cellTrigger: 'outline-warning/25'
              },
              error: {
                headCell: 'text-error',
                cellTrigger: 'outline-error/25'
              },
              neutral: {
                headCell: 'text-highlighted',
                cellTrigger: 'outline-inverted/25'
              }
            },
            variant: {
              solid: '',
              outline: '',
              soft: '',
              subtle: ''
            },
            size: {
              xs: {
                headingLabel: 'text-xs',
                cell: 'text-xs',
                cellWeek: 'text-xs',
                headCell: 'text-[10px]',
                headCellWeek: 'text-[10px]',
                body: 'space-y-2 pt-2'
              },
              sm: {
                headingLabel: 'text-xs',
                headCell: 'text-xs',
                headCellWeek: 'text-xs',
                cellWeek: 'text-xs',
                cell: 'text-xs'
              },
              md: {
                headingLabel: 'text-sm',
                headCell: 'text-xs',
                headCellWeek: 'text-xs',
                cellWeek: 'text-xs',
                cell: 'text-sm'
              },
              lg: {
                headingLabel: 'text-md',
                headCell: 'text-md',
                headCellWeek: 'text-md'
              },
              xl: {
                headingLabel: 'text-lg',
                headCell: 'text-lg',
                headCellWeek: 'text-lg'
              }
            },
            view: {
              day: {
                gridRow: 'grid-cols-7 place-items-center',
                cellTrigger: 'rounded-full data-outside-view:text-muted'
              },
              month: {
                gridRow: 'grid-cols-4',
                cellTrigger: 'rounded-md'
              },
              year: {
                gridRow: 'grid-cols-4',
                cellTrigger: 'rounded-md'
              }
            },
            weekNumbers: {
              true: ''
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: 'solid',
              class: {
                cellTrigger: 'data-selected:bg-primary data-selected:text-inverted data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
              }
            },
            {
              color: 'primary',
              variant: 'outline',
              class: {
                cellTrigger: 'data-selected:ring data-selected:ring-inset data-selected:ring-primary/50 data-selected:text-primary data-selected:focus-visible:ring-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/10 hover:not-data-selected:bg-primary/10'
              }
            },
            {
              color: 'primary',
              variant: 'soft',
              class: {
                cellTrigger: 'data-selected:bg-primary/10 data-selected:text-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
              }
            },
            {
              color: 'primary',
              variant: 'subtle',
              class: {
                cellTrigger: 'data-selected:bg-primary/10 data-selected:text-primary data-selected:ring data-selected:ring-inset data-selected:ring-primary/25 data-selected:focus-visible:ring-primary data-today:not-data-selected:text-primary data-highlighted:bg-primary/20 hover:not-data-selected:bg-primary/20'
              }
            },
            {
              color: 'neutral',
              variant: 'solid',
              class: {
                cellTrigger: 'data-selected:bg-inverted data-selected:text-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
              }
            },
            {
              color: 'neutral',
              variant: 'outline',
              class: {
                cellTrigger: 'data-selected:ring data-selected:ring-inset data-selected:ring-accented data-selected:text-default data-selected:bg-default data-selected:focus-visible:ring-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/10 hover:not-data-selected:bg-inverted/10'
              }
            },
            {
              color: 'neutral',
              variant: 'soft',
              class: {
                cellTrigger: 'data-selected:bg-elevated data-selected:text-default data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
              }
            },
            {
              color: 'neutral',
              variant: 'subtle',
              class: {
                cellTrigger: 'data-selected:bg-elevated data-selected:text-default data-selected:ring data-selected:ring-inset data-selected:ring-accented data-selected:focus-visible:ring-inverted data-today:not-data-selected:text-highlighted data-highlighted:bg-inverted/20 hover:not-data-selected:bg-inverted/10'
              }
            },
            {
              size: 'xs',
              view: 'day',
              class: {
                cellTrigger: 'size-7'
              }
            },
            {
              size: 'sm',
              view: 'day',
              class: {
                cellTrigger: 'size-7'
              }
            },
            {
              size: 'md',
              view: 'day',
              class: {
                cellTrigger: 'size-8'
              }
            },
            {
              size: 'lg',
              view: 'day',
              class: {
                cellTrigger: 'size-9 text-md'
              }
            },
            {
              size: 'xl',
              view: 'day',
              class: {
                cellTrigger: 'size-10 text-lg'
              }
            },
            {
              size: 'xs',
              view: [
                'month',
                'year'
              ],
              class: {
                cellTrigger: 'h-7 px-2'
              }
            },
            {
              size: 'sm',
              view: [
                'month',
                'year'
              ],
              class: {
                cellTrigger: 'h-7 px-2'
              }
            },
            {
              size: 'md',
              view: [
                'month',
                'year'
              ],
              class: {
                cellTrigger: 'h-8 px-3'
              }
            },
            {
              size: 'lg',
              view: [
                'month',
                'year'
              ],
              class: {
                cellTrigger: 'h-9 px-4 text-md'
              }
            },
            {
              size: 'xl',
              view: [
                'month',
                'year'
              ],
              class: {
                cellTrigger: 'h-10 px-5 text-lg'
              }
            },
            {
              view: 'day',
              weekNumbers: true,
              class: {
                gridRow: 'grid-cols-8',
                gridWeekDaysRow: 'grid-cols-8 [&>*:first-child]:col-start-2'
              }
            }
          ],
          defaultVariants: {
            size: 'md',
            color: 'accent',
            variant: 'solid',
            view: 'day'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitLab.

Changelog

No recent changes