Calendar
@vincisys/eyeson
agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
26 jul
27 jul
28 jul
29 jul
30 jul
31 jul
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 set
2 set
3 set
4 set
5 set
Visualizar
import { Calendar } from "@vincisys/eyeson";

export function CalendarBasicDemo() {
	return (
		<div className="h-[640px] w-full">
			<Calendar defaultMonth={today} events={events} />
		</div>
	);
}

Instalação

import { Calendar } from '@vincisys/eyeson';

Uso

import { Calendar, type CalendarEvent } from '@vincisys/eyeson';

const events: CalendarEvent[] = [
{
id: '1',
date: new Date(2026, 6, 10),
label: 'SDU → GRU | 6:30',
color: 'blue-main',
},
];

export function Example() {
return <Calendar defaultMonth={new Date(2026, 6, 1)} events={events} />;
}

Exemplos

Básico

agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
26 jul
27 jul
28 jul
29 jul
30 jul
31 jul
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 set
2 set
3 set
4 set
5 set
Visualizar
import { Calendar } from "@vincisys/eyeson";

export function CalendarBasicDemo() {
	return (
		<div className="h-[640px] w-full">
			<Calendar defaultMonth={today} events={events} />
		</div>
	);
}

Controlado

agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
26 jul
27 jul
28 jul
29 jul
30 jul
31 jul
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 set
2 set
3 set
4 set
5 set
Visualizar
import { Calendar } from "@vincisys/eyeson";
import { useState } from "react";

export function CalendarControlledDemo() {
	const [month, setMonth] = useState(today);

	return (
		<div className="h-[640px] w-full">
			<Calendar month={month} onMonthChange={setMonth} events={events} />
		</div>
	);
}

Cores dos eventos

A bolinha de cada evento aceita qualquer cor semântica do design system (EdsSemanticColor), permitindo usar a paleta para indicar status diferentes.

agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
26 jul
27 jul
28 jul
29 jul
30 jul
31 jul
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 set
2 set
3 set
4 set
5 set
Visualizar
import { Calendar } from "@vincisys/eyeson";

export function CalendarColorsDemo() {
	return (
		<div className="h-[640px] w-full">
			<Calendar
				defaultMonth={today}
				events={statusColors}
				maxVisibleEvents={statusColors.length}
			/>
		</div>
	);
}

Customizando o conteúdo do evento

Use renderEvent para substituir a pill padrão por qualquer conteúdo — inclusive controlando você mesmo o clique, em vez de usar onEventClick.

agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
26 jul
27 jul
28 jul
29 jul
30 jul
31 jul
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 set
2 set
3 set
4 set
5 set
Visualizar
import { Calendar, CalendarEvent } from "@vincisys/eyeson";
import { Plane } from "lucide-react";
import { useState, CSSProperties } from "react";

export function CalendarCustomEventDemo() {
	const [selected, setSelected] = useState<CalendarEvent | null>(null);

	return (
		<div className="h-[640px] w-full">
			<Calendar
				defaultMonth={today}
				events={events}
				renderEvent={(event) => (
					<button
						type="button"
						onClick={() => setSelected(event)}
						className="flex h-8 w-full shrink-0 items-center gap-1.5 rounded-eds-md border border-eds-neutral-disabled bg-white px-2 text-left text-xs font-medium text-eds-neutral-main"
					>
						<Plane
							className="shrink-0 text-[var(--eds-flight-color)]"
							style={
								{
									'--eds-flight-color': `var(--color-eds-${event.color})`,
								} as CSSProperties
							}
							size={12}
						/>
						<span className="truncate">{event.label}</span>
					</button>
				)}
			/>
			{selected && (
				<p className="mt-2 text-sm text-eds-neutral-elements">
					Selecionado: {selected.label}
				</p>
			)}
		</div>
	);
}

Abrindo um modal ao clicar no dia

onDayClick dispara ao clicar em qualquer lugar do cartão do dia (não só no número) e recebe a data clicada — basta guardar esse valor no estado do seu app para abrir um modal (aqui usando @base-ui/react/dialog) com um formulário para adicionar um novo evento naquele dia.

agosto 2026
Dom
Seg
Ter
Qua
Qui
Sex
Sáb
Visualizar
import { Dialog } from "@base-ui/react/dialog";
import { Button, Calendar, CalendarEvent, Input, Select, SelectOption } from "@vincisys/eyeson";
import { format, isSameDay } from "date-fns";
import { ptBR } from "date-fns/locale";
import { useState } from "react";

export function CalendarDayModalDemo() {
	const [dayEvents, setDayEvents] = useState<CalendarEvent[]>(events);
	const [openDay, setOpenDay] = useState<Date | null>(null);
	const [label, setLabel] = useState('');
	const [color, setColor] = useState<SelectOption | null>(
		EVENT_COLOR_OPTIONS[0],
	);

	const eventsForOpenDay = openDay
		? dayEvents.filter((event) => isSameDay(event.date, openDay))
		: [];

	function handleAddEvent() {
		if (!openDay || !label.trim() || !color) return;
		setDayEvents((prev) => [
			...prev,
			{
				id: crypto.randomUUID(),
				date: openDay,
				label: label.trim(),
				color: color.value as CalendarEvent['color'],
			},
		]);
		setLabel('');
	}

	return (
		<div className="h-[640px] w-full">
			<Calendar
				defaultMonth={today}
				events={dayEvents}
				onDayClick={setOpenDay}
			/>

			<Dialog.Root
				open={openDay !== null}
				onOpenChange={(open) => !open && setOpenDay(null)}
			>
				<Dialog.Portal>
					<Dialog.Backdrop className="fixed inset-0 z-40 bg-black/40" />
					<Dialog.Popup className="fixed top-1/2 left-1/2 z-50 flex max-h-[85vh] w-80 -translate-x-1/2 -translate-y-1/2 flex-col rounded-eds-md bg-white p-4 shadow-lg">
						<Dialog.Title className="shrink-0 text-base font-medium text-eds-neutral-main capitalize">
							{openDay
								? format(openDay, "d 'de' MMMM", {
										locale: ptBR,
									})
								: ''}
						</Dialog.Title>

						<div className="mt-3 flex flex-col gap-2 overflow-y-auto">
							{eventsForOpenDay.length === 0 && (
								<p className="text-sm text-eds-neutral-elements">
									Nenhum evento neste dia.
								</p>
							)}
							{eventsForOpenDay.map((event) => (
								<div
									key={event.id}
									className="text-sm text-eds-neutral-main"
								>
									{event.label}
								</div>
							))}
						</div>

						<div className="mt-4 flex shrink-0 flex-col gap-3 border-t border-eds-hairline pt-4">
							<Input
								label="Novo evento"
								placeholder="Ex: Reunião com cliente"
								value={label}
								onChange={setLabel}
							/>
							<Select
								label="Cor"
								items={EVENT_COLOR_OPTIONS}
								value={color}
								onValueChange={setColor}
							/>
							<Button
								text="Adicionar evento"
								size="sm"
								onClick={handleAddEvent}
								disabled={!label.trim()}
							/>
						</div>

						<Dialog.Close className="mt-4 shrink-0 cursor-pointer text-sm text-eds-blue-main">
							Fechar
						</Dialog.Close>
					</Dialog.Popup>
				</Dialog.Portal>
			</Dialog.Root>
		</div>
	);
}

Página completa

O Calendar ocupa 100% da altura do seu contêiner. Veja um exemplo de página real, com um cabeçalho simples e o calendário preenchendo o restante da tela: /examples/voos.