Skip to content
Merged
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
22 changes: 22 additions & 0 deletions docs/content/docs/2.components/calendar.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,28 @@ props:
---
::

### Variant

Use the `variant` prop to change the variant of the calendar.

::component-code
---
cast:
defaultValue: DateRange
hide:
- range
- defaultValue
- defaultValue.start
- defaultValue.end
props:
variant: subtle
range: true
defaultValue:
start: [2022, 2, 3]
end: [2022, 2, 20]
---
::

### Size

Use the `size` prop to change the size of the calendar.
Expand Down
3 changes: 3 additions & 0 deletions playgrounds/nuxt/app/pages/components/calendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ const rangeValue = shallowRef({
})

const colors = Object.keys(theme.variants.color)
const variants = Object.keys(theme.variants.variant)
const sizes = Object.keys(theme.variants.size)

const attrs = reactive({
color: [theme.defaultVariants.color],
variant: [theme.defaultVariants.variant],
size: [theme.defaultVariants.size]
})

Expand All @@ -24,6 +26,7 @@ const range = ref(false)
<template>
<Navbar>
<USelect v-model="attrs.color" :items="colors" multiple />
<USelect v-model="attrs.variant" :items="variants" multiple />
<USelect v-model="attrs.size" :items="sizes" multiple />
<USwitch v-model="multiple" label="Multiple" />
<USwitch v-model="range" label="Range" />
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/components/Calendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export interface CalendarProps<R extends boolean = false, M extends boolean = fa
* @defaultValue 'primary'
*/
color?: Calendar['variants']['color']
/**
* @defaultValue 'solid'
*/
variant?: Calendar['variants']['variant']
/**
* @defaultValue 'md'
*/
Expand Down Expand Up @@ -126,7 +130,7 @@ defineSlots<CalendarSlots>()
const { code: locale, dir, t } = useLocale()
const appConfig = useAppConfig() as Calendar['AppConfig']

const rootProps = useForwardPropsEmits(reactiveOmit(props, 'range', 'modelValue', 'defaultValue', 'color', 'size', 'monthControls', 'yearControls', 'class', 'ui'), emits)
const rootProps = useForwardPropsEmits(reactiveOmit(props, 'range', 'modelValue', 'defaultValue', 'color', 'variant', 'size', 'monthControls', 'yearControls', 'class', 'ui'), emits)

const nextYearIcon = computed(() => props.nextYearIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleLeft : appConfig.ui.icons.chevronDoubleRight))
const nextMonthIcon = computed(() => props.nextMonthIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronLeft : appConfig.ui.icons.chevronRight))
Expand All @@ -135,6 +139,7 @@ const prevMonthIcon = computed(() => props.prevMonthIcon || (dir.value === 'rtl'

const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.calendar || {}) })({
color: props.color,
variant: props.variant,
size: props.size
}))

Expand Down
64 changes: 60 additions & 4 deletions src/theme/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,25 @@ export default (options: Required<ModuleOptions>) => ({
gridBody: 'grid',
headCell: 'rounded-md',
cell: 'relative text-center',
cellTrigger: ['m-0.5 relative flex items-center justify-center rounded-full whitespace-nowrap focus-visible:ring-2 focus:outline-none data-disabled:text-muted data-unavailable:line-through data-unavailable:text-muted data-unavailable:pointer-events-none data-[selected]:text-inverted data-today:font-semibold data-[outside-view]:text-muted', options.theme.transitions && 'transition']
cellTrigger: ['m-0.5 relative flex items-center justify-center rounded-full whitespace-nowrap focus-visible:ring-2 focus:outline-none data-disabled:text-muted data-unavailable:line-through data-unavailable:text-muted data-unavailable:pointer-events-none data-today:font-semibold data-[outside-view]:text-muted', options.theme.transitions && 'transition']
},
variants: {
color: {
...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, {
headCell: `text-${color}`,
cellTrigger: `focus-visible:ring-${color} data-[selected]:bg-${color} data-today:not-data-[selected]:text-${color} data-[highlighted]:bg-${color}/20 hover:not-data-[selected]:bg-${color}/20`
cellTrigger: `focus-visible:ring-${color}`
}])),
neutral: {
headCell: 'text-highlighted',
cellTrigger: 'focus-visible:ring-inverted data-[selected]:bg-inverted data-today:not-data-[selected]:text-highlighted data-[highlighted]:bg-inverted/20 hover:not-data-[selected]:bg-inverted/10'
cellTrigger: 'focus-visible:ring-inverted'
}
},
variant: {
solid: '',
outline: '',
soft: '',
subtle: ''
},
size: {
xs: {
heading: 'text-xs',
Expand Down Expand Up @@ -57,8 +63,58 @@ export default (options: Required<ModuleOptions>) => ({
}
}
},
compoundVariants: [...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'solid',
class: {
cellTrigger: `data-[selected]:bg-${color} data-[selected]:text-inverted data-today:not-data-[selected]:text-${color} data-[highlighted]:bg-${color}/20 hover:not-data-[selected]:bg-${color}/20`
}
})), ...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'outline',
class: {
cellTrigger: `data-[selected]:ring data-[selected]:ring-inset data-[selected]:ring-${color}/50 data-[selected]:text-${color} data-today:not-data-[selected]:text-${color} data-[highlighted]:bg-${color}/10 hover:not-data-[selected]:bg-${color}/10`
}
})), ...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'soft',
class: {
cellTrigger: `data-[selected]:bg-${color}/10 data-[selected]:text-${color} data-today:not-data-[selected]:text-${color} data-[highlighted]:bg-${color}/20 hover:not-data-[selected]:bg-${color}/20`
}
})), ...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'subtle',
class: {
cellTrigger: `data-[selected]:bg-${color}/10 data-[selected]:text-${color} data-[selected]:ring data-[selected]:ring-inset data-[selected]:ring-${color}/25 data-today:not-data-[selected]:text-${color} data-[highlighted]:bg-${color}/20 hover:not-data-[selected]:bg-${color}/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-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-today:not-data-[selected]:text-highlighted data-[highlighted]:bg-inverted/20 hover:not-data-[selected]:bg-inverted/10'
}
}],
defaultVariants: {
size: 'md',
color: 'primary'
color: 'primary',
variant: 'solid'
}
})
2 changes: 2 additions & 0 deletions test/components/Calendar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CalendarDate } from '@internationalized/date'

describe('Calendar', () => {
const sizes = Object.keys(theme.variants.size) as any
const variants = Object.keys(theme.variants.variant) as any
const date = new Date('2025-01-01')

vi.setSystemTime(date)
Expand Down Expand Up @@ -37,6 +38,7 @@ describe('Calendar', () => {
['without monthControls', { props: { monthControls: false } }],
['without yearControls', { props: { yearControls: false } }],
...sizes.map((size: string) => [`with size ${size}`, { props: { size } }]),
...variants.map((variant: string) => [`with variant ${variant}`, { props: { variant, defaultValue: new CalendarDate(2025, 1, 15) } }]),
['with color neutral', { props: { color: 'neutral' } }],
['with as', { props: { as: 'section' } }],
['with class', { props: { class: 'max-w-sm' } }],
Expand Down
Loading
Loading