taw-ui
Domain Surface

EventCard

Canonical calendar event surface for Google Calendar, Outlook, Cal.com, and any event provider. One component, any data source — your app authenticates, fetches, and maps to the canonical schema.

Theme
State
MAR10
Work

Q1 Planning — Product & Engineering Sync

Today · 6:00 PM 7:30 PM(1h 30m)

Quarterly planning session to align on product roadmap priorities, engineering capacity, and key deliverables for Q1. Please review the pre-read doc before joining.

Conference Room 4B
SSarah Chen(organizer)
James WilsonPriya PatelAlex KimMaria Garcia

Installation

Terminal
npx shadcn@latest add "https://taw-ui.com/r/event-card.json"

This copies the component source and schema into your project. You own the code — customize anything.

Usage with Data Mapping

The recommended pattern: your app fetches data from the provider and maps it to the EventCard schema inline.

Google Calendar mapping
// Your app fetches (auth is yours)
const { data: event } = await calendar.events.get({
  calendarId: "primary", eventId: "abc123",
})

// Map to the EventCard schema
const eventData = {
  id: `google:${event.id}`,
  provider: "google",
  title: event.summary,
  startAt: event.start.dateTime ?? event.start.date,
  endAt: event.end.dateTime ?? event.end.date,
  // ... map remaining fields
}
Outlook mapping
// Your app fetches (auth is yours)
const event = await graphClient
  .api("/me/events/AAMk...").get()

// Map to the EventCard schema
const eventData = {
  id: `outlook:${event.id}`,
  provider: "outlook",
  title: event.subject,
  startAt: event.start.dateTime,
  endAt: event.end.dateTime,
  // ... map remaining fields
}

Usage as AI Tool

EventCard also works as a standard taw-ui tool output — let the AI populate the canonical schema directly.

server — define tool
import { tool } from "ai"
import { EventCardSchema } from "@/components/taw/event-card"

export const getEvent = tool({
  description: "Look up a calendar event",
  parameters: z.object({
    query: z.string(),
  }),
  outputSchema: EventCardSchema,
  execute: async ({ query }) => {
    const event = await fetchNextEvent(query)
    return {
      id: \`google:\${event.id}\`,
      provider: "google",
      title: event.summary,
      startAt: event.start.dateTime,
      endAt: event.end.dateTime,
      // ... map remaining fields
    }
  },
})
client — render
import { EventCard } from "@/components/taw/event-card"
import type { ToolPart } from "@/components/taw/lib/types"

function ToolOutput({ part }: { part: ToolPart }) {
  // Handles loading, error, and success states
  return <EventCard part={part} />
}

Providers

Switch between fixtures to see EventCard rendering data from different providers and states.

Google Calendar
MAR10
Work

Q1 Planning — Product & Engineering Sync

Today · 6:00 PM 7:30 PM(1h 30m)

Quarterly planning session to align on product roadmap priorities, engineering capacity, and key deliverables for Q1. Please review the pre-read doc before joining.

Conference Room 4B
SSarah Chen(organizer)
James WilsonPriya PatelAlex KimMaria Garcia
Outlook
MAR11
Calendar

Design Review: New Dashboard Components

Tomorrow · 7:00 PM 8:00 PM(1h)

Review the latest Figma mockups for the analytics dashboard redesign. Focus on the new chart components and data visualization patterns.

DDavid Park(organizer)
Emma ThompsonRaj PatelLisa Wang

Props

FieldTypeDescription
part*ToolPartTool call lifecycle state — handles loading, error, and success
animatebooleanEnable entrance animations (default: true)
classNamestringAdditional CSS classes on the wrapper

Schema

EventCardSchema
FieldTypeDescription
id*stringStable identifier (e.g. "google:abc123")
provider*"google" | "outlook" | "calcom" | "other"Source provider for icon and branding
title*stringEvent title / summary
startAt*stringStart time (ISO 8601) or date (YYYY-MM-DD)
endAt*stringEnd time (ISO 8601) or date (YYYY-MM-DD)
isAllDaybooleanWhether this is an all-day event
descriptionstringEvent description (truncated for display)
locationstringPhysical location or room name
meetingUrlstring (URL)Video meeting link (Zoom, Meet, Teams)
status"confirmed" | "tentative" | "cancelled"Event status — controls accent strip color
organizerOrganizerEvent organizer
attendeesAttendee[]List of attendees with RSVP status
calendarNamestringCalendar name (e.g. "Work", "Personal")
urlstring (URL)Link back to the event in the provider
confidencenumber (0-1)AI confidence in this data
caveatstringUncertainty note
sourceSourceData provenance
Organizer
FieldTypeDescription
name*stringDisplay name
emailstringEmail address (display only)
avatarUrlstring (URL)Avatar image URL
Attendee
FieldTypeDescription
name*stringDisplay name
emailstringEmail address (display only)
avatarUrlstring (URL)Avatar image URL
responseStatus"accepted" | "declined" | "tentative" | "needsAction"RSVP response — shown as colored dot on avatar

Data Mapping

Map your provider's API response to the EventCardSchema inline. No special adapters needed — just a plain object mapping.

Google Calendar → EventCard
// Map Google Calendar API v3 fields
const eventData = {
  id: `google:${event.id}`,
  provider: "google",
  title: event.summary,
  startAt: event.start.dateTime ?? event.start.date,
  endAt: event.end.dateTime ?? event.end.date,
  attendees: (event.attendees ?? []).map(a => ({
    name: a.displayName ?? a.email,
    email: a.email,
  })),
}
Outlook → EventCard
// Map Microsoft Graph API fields
const eventData = {
  id: `outlook:${event.id}`,
  provider: "outlook",
  title: event.subject,
  startAt: event.start.dateTime,
  endAt: event.end.dateTime,
  location: event.location?.displayName,
  organizer: event.organizer
    ? { name: event.organizer.emailAddress.name }
    : undefined,
}

Features

Provider icons

Native icons for Google, Outlook, Cal.com — plus a generic calendar fallback

Status accent strip

Left border colored by event status: green (confirmed), yellow (tentative), red (cancelled)

Smart time formatting

Locale-aware time display with duration badges and all-day event support

Attendee avatars

Stacked avatar display with RSVP response status indicators

Graceful degradation

Renders beautifully from minimal (5 fields) to fully populated data

Inline data mapping

Map any provider's API response to the canonical schema — no adapters needed

Auth Boundary

taw-ui does not handle authentication. OAuth flows, access tokens, refresh tokens, API clients, and data fetching are the responsibility of your application. taw-ui provides schemas, components, and validation — nothing more.

See Domain Surfaces for the full architecture explanation.

Related