Event Card

Pro

The calendar event an assistant drafted, added or moved, shown in its reply: what, when, where and who, with the conflict it found and a way to undo. A full card for one event, a row that opens in place for several.

Q4 roadmap reviewThu, Nov 12 · 10:00 – 11:30 AM (1 hr, 30 min)Draft
Google Meet · meet.google.com
5 guests, 3 going
KLAPD
Walk through what shipped in Q3, agree the three bets for Q4 and who owns each one.
Overlaps Design critique at 11:00 AM

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Activate your Pro license (once per machine)npx koalaui-cli@latest login <key># Add this component (its dependencies come along)npx koalaui-cli@latest add event-card

Usage#

This example is part of Koala UI Pro

The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.

Have a license? Unlock it here

Anatomy#

A header with the date tile, the title, the time and the status, and the content under it: one row per detail, each with its glyph under the tile and its text under the title, then the actions. Every part is droppable: a reminder needs only the header.

import {  EventCardGroup,  EventCard,  EventCardHeader,  EventCardDate,  EventCardTitle,  EventCardTime,  EventCardStatus,  EventCardContent,  EventCardLocation,  EventCardAttendees,  EventCardRecurrence,  EventCardDescription,  EventCardChange,  EventCardConflict,  EventCardActions,  EventCardSkeleton,} from "@/components/ui/event-card"<EventCardGroup>  <EventCard>    <EventCardHeader>      <EventCardDate />      <EventCardTitle />      <EventCardTime />      <EventCardStatus />    </EventCardHeader>    <EventCardContent>      <EventCardChange />      <EventCardLocation />      <EventCardAttendees />      <EventCardRecurrence />      <EventCardDescription />      <EventCardConflict />      <EventCardActions />    </EventCardContent>  </EventCard></EventCardGroup><EventCardSkeleton />

Status#

Four, set once on the root with status. A draft is a proposal the person still has to accept; added is on the calendar; updated was moved or edited; cancelled strikes the time through and mutes the card, so the reply still says what was called off. The chip words itself from the status, and its children rename it, for example “Added to Personal”.

Lunch with LiamTue, Nov 10 · 12:30 – 1:30 PM (1 hr)Draft
Design reviewWed, Nov 11 · 10:30 – 11:15 AM (45 min)Added
1:1 with KatherineFri, Nov 13 · 2:00 – 2:30 PM (30 min)Updated
Yoga classSat, Nov 14 · 8:00 – 9:00 AM (1 hr)Cancelled

Compact#

layout="compact" turns the header into one line you can click, and the card grows in place to show the details. Stack several in an EventCardGroup when the assistant added more than one: they share one frame and part with hairlines. An all-day event over several days shows the range of days and “All day”.

Put next week's plans on my calendar
Three events added. Open one to see where and when.

Changes and conflicts#

When the assistant moves an event, EventCardChange shows the old time struck through and the new one after it, while the header already shows where it landed. When a draft clashes with something on the calendar, EventCardConflict says with what, in the warning tone, before the person commits.

1:1 with KatherineFri, Nov 13 · 3:00 – 3:30 PM (30 min)Updated
Was Thu, Nov 12 · 2:00 PM, now Fri, Nov 13 · 3:00 PM
Katherine accepted
K
Hiring syncWed, Nov 11 · 10:00 – 11:00 AM (1 hr)Draft
Microsoft Teams
Overlaps Design review at 10:30 AM

In a conversation#

The card sits under the reply at the column's width, with no bubble. Add the draft and the same card turns into the added event: the status and the button labels roll to their new words rather than a second card appearing. Undo takes it back.

Book a dentist check-up next Thursday morning, and remind me every six months
Thursday at 9:30 AM is free. Here is the appointment, ready to add.
Dentist check-upThu, Nov 12 · 9:30 – 10:15 AM (45 min)Draft
Brightside Dental, 210 Grand St · Floor 3
Every 6 months on Thursday

Loading#

While the reply streams, EventCardSkeleton holds the card's shape so the text above it does not jump when the event arrives.

API reference#

EventCard

One event, an <article>, and the context every part reads. Every part accepts className, merged last, and forwards its element's props. eventCardVariants is the recipe.

PropTypeDefaultDescription
status"draft" | "added" | "updated" | "cancelled""added"Where the event stands. Words and tones EventCardStatus; cancelled strikes the time through and mutes the title, the day and the details.
layout"full" | "compact""full"full shows everything at once. compact makes the header a one-line disclosure and folds EventCardContent under it, opening in place.
localestring"en-US"The locale EventCardDate and EventCardTime format in.
timeZonestring-The IANA zone the times are shown in. Without it the server renders UTC and the browser switches to the visitor's zone after hydration; pass the event's zone to skip that.
openboolean-Controlled open state of a compact card.
defaultOpenbooleanfalseInitial open state of a compact card.
onOpenChange(open: boolean) => void-Called when a compact card opens or closes.
Data attributeDescription
data-slot"event-card".
data-statusThe status.
data-layout"full" or "compact".
data-stateopen or closed, on a compact card only.

EventCardHeader

What and when, a two-row grid: the date tile, the title over the time, then the status. In a compact card it is the Radix Collapsible.Trigger (a <button>) and adds the caret; in a full card it is a <div>.

Data attributeDescription
data-slot"event-card-header".

EventCardDate

The calendar leaf: the month over the day, 44px in a full card and 36px in a compact one. Decorative (aria-hidden), since EventCardTime carries the date in words.

PropTypeDefaultDescription
dateDate-Formats the month and day in the root's locale and timeZone.
monthReact.ReactNode-Pre-formatted month, instead of date.
dayReact.ReactNode-Pre-formatted day, instead of date.
color"default" | "brand" | "purple" | "pink" | "teal" | "orange" | "red""default"The calendar's colour, on the month. A cancelled event drops it.
Data attributeDescription
data-slot"event-card-date".
data-colorThe color.

EventCardTitle

The event's name, a <span>. Truncates on one line.

Data attributeDescription
data-slot"event-card-title".

EventCardTime

When, a muted <span> in tabular-nums under the title: the day, the time range in the locale's own form and the length in parentheses, "(1 hr, 30 min)". Spans several days when the end falls on another day. Children replace the formatted text.

PropTypeDefaultDescription
startDate-When it starts.
endDate-When it ends. For an all-day event, the last day.
allDaybooleanfalseShows the day or days and the allDayLabel instead of times, with no duration.
allDayLabelstring"All day"The words for an all-day event.
durationReact.ReactNode-Overrides the length in parentheses, worked out from start and end. Pass null to drop it.
Data attributeDescription
data-slot"event-card-time"; the length is "event-card-duration".

EventCardStatus

A dot Badge worded and toned from the root's status, sm in a compact card. The label rolls when the status changes. Forwards Badge props.

PropTypeDefaultDescription
variantBadgeProps["variant"]-Overrides the tone the status picks.
childrenReact.ReactNode-Overrides the wording (Draft, Added, Updated, Cancelled), for example "Added to Personal".
Data attributeDescription
data-slot"event-card-status".

EventCardContent

The details under the header, a <div>. Each detail is a row with a 16px glyph centred under the date tile and its text in the title's column. In a compact card it is the Radix Collapsible.Content.

Data attributeDescription
data-slot"event-card-content".
data-stateopen or closed, in a compact card.

EventCardLocation

Where: a place, a video call or a phone line. Children are the name.

PropTypeDefaultDescription
kind"place" | "video" | "phone""place"Picks the glyph: a pin, a camera or a handset.
hrefstring-Links the name, opening in a new tab: the call's join link, a map.
detailReact.ReactNode-A muted second part after a dot: a floor, a domain.
iconReact.ReactNode-Replaces the glyph.
Data attributeDescription
data-slot"event-card-location".

EventCardAttendees

Who: the RSVP summary, and the guests' faces at the end of the row in an AvatarGroup. Children are Avatars at size="xs".

PropTypeDefaultDescription
summaryReact.ReactNode-The headcount and replies ("5 guests, 3 going").
maxnumber4Faces shown before the +N chip.
totalnumber-The real headcount when you pass fewer avatars than guests.
iconReact.ReactNode-Replaces the glyph.
Data attributeDescription
data-slot"event-card-attendees".

EventCardRecurrence

How it repeats ("Every weekday at 9:00 AM"), a row with the repeat glyph.

PropTypeDefaultDescription
iconReact.ReactNode-Replaces the glyph.
Data attributeDescription
data-slot"event-card-recurrence".

EventCardDescription

The agenda or note, muted and clamped to three lines.

PropTypeDefaultDescription
iconReact.ReactNode-Replaces the glyph.
Data attributeDescription
data-slot"event-card-description".

EventCardChange

What moved: the old value struck through in a <del>, an arrow, the new one in an <ins>. Reads "Was …, now …" to a screen reader.

PropTypeDefaultDescription
from*React.ReactNode-The value before the change.
children*React.ReactNode-The value after it.
fromLabelstring"Was"Screen reader word before the old value.
toLabelstring"now"Screen reader word before the new value.
iconReact.ReactNode-Replaces the glyph.
Data attributeDescription
data-slot"event-card-change".

EventCardConflict

A clash with another event, in the warning tone, a role="note" row.

PropTypeDefaultDescription
iconReact.ReactNode-Replaces the warning glyph.
Data attributeDescription
data-slot"event-card-conflict".

EventCardActions

The buttons, a <div> aligned with the title's column. App UI: size="sm" buttons, text only, the main one first.

Data attributeDescription
data-slot"event-card-actions".

EventCardGroup

Several events in one frame, a <div>. The cards inside drop their own frame and part with hairlines. Usually holds compact cards.

Data attributeDescription
data-slot"event-card-group".

EventCardSkeleton

The card's shape while the reply streams: the tile, two lines and the status, plus two details and the buttons in a full card.

PropTypeDefaultDescription
layout"full" | "compact""full"Which card it stands in for.
Data attributeDescription
data-slot"event-card-skeleton".

FAQ#

Event Calendar is a whole calendar: weeks, days and many events. Event Card is one event the assistant created, proposed or changed, shown inside its reply with a way to confirm or undo.