Skip to content
Brok UI

Loading…

No results

Calendar Event Card

Open source

A single calendar event card with a tone-coloured accent bar, time chip, location, attendee avatars and an optional join action.

Version
v1.0.4
Stability
stable
License
MIT
Related
Calendar
List Panel
Card

Preview

Product sync

Tue, 16 Jun

10:00 – 10:45

Google Meet

Ada Ada Lin Lin Sam Sam Rae Rae +1
Join

Design critique

Wed, 17 Jun

14:00 – 15:00

Studio B

Mara Mara Ken Ken
Tone
previews.components.calendar-event-card.default.blade.php Blade
<div class="mx-auto w-full max-w-sm space-y-3">
    <x-ui.calendar-event-card
        title="Product sync"
        date="Tue, 16 Jun"
        start="10:00"
        end="10:45"
        location="Google Meet"
        tone="primary"
        href="#"
        :attendees="[['name' => 'Ada'], ['name' => 'Lin'], ['name' => 'Sam'], ['name' => 'Rae'], ['name' => 'Joel']]"
    />
    <x-ui.calendar-event-card
        title="Design critique"
        date="Wed, 17 Jun"
        start="14:00"
        end="15:00"
        location="Studio B"
        tone="warning"
        :attendees="[['name' => 'Mara'], ['name' => 'Ken']]"
    />
</div>
Primary Current
Bar Current
Chip Current
Success Current
Warning Current
Info Current
Destructive Current

Installation

terminal
php artisan ui:add calendar-event-card

Registry contract

php artisan ui:add calendar-event-card writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.

  • blade resources/views/components/ui/calendar-event-card.blade.php
Registry dependencies
avatar button
Packages
composer: jml/brok:^0.2

Use with AI

A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.

calendar-event-card.md
# Brok UI: Calendar Event Card (`calendar-event-card`)

A single calendar event card with a tone-coloured accent bar, time chip, location, attendee avatars and an optional join action.

Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.

## Install

```bash
php artisan ui:add calendar-event-card
```

## Usage

```blade
<div class="mx-auto w-full max-w-sm space-y-3">
    <x-ui.calendar-event-card
        title="Product sync"
        date="Tue, 16 Jun"
        start="10:00"
        end="10:45"
        location="Google Meet"
        tone="primary"
        href="#"
        :attendees="[['name' => 'Ada'], ['name' => 'Lin'], ['name' => 'Sam'], ['name' => 'Rae'], ['name' => 'Joel']]"
    />
    <x-ui.calendar-event-card
        title="Design critique"
        date="Wed, 17 Jun"
        start="14:00"
        end="15:00"
        location="Studio B"
        tone="warning"
        :attendees="[['name' => 'Mara'], ['name' => 'Ken']]"
    />
</div>
```

## Props

- `title` (string, default `Product sync`)
- `date` (string, default `Tue, 16 Jun`)
- `start` (string, default `10:00`)
- `end` (string, default `10:45`)
- `location` (string, default `Google Meet`)
- `tone` (string, default `primary`)
- `attendees` (array, default `[]`)
- `href` (mixed|null, default `null`)
- `joinLabel` (string, default `Join`)

## Use when

- Use when self-contained content objects benefit from a recognizable card-like presentation with local actions or metadata.
- Showing one upcoming event with its time, place and attendees in an agenda or dashboard.
- Offering a join link beside the event details.

## Avoid when

- Do not use card widgets where a simpler list, table, or plain text block would make comparison faster.
- Rendering a whole calendar; calendar and mini-calendar lay out dates.
- Listing many events compactly, where a table or list-panel reads faster.

## Anti-patterns

- Using cards for dense cross-item comparison

## Rules

- Use the `<brok:calendar-event-card>` tag (or `<x-ui.calendar-event-card>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.

## Links

- Docs: https://brokui.dev/docs/components/calendar-event-card
- Registry JSON (files, props, contract): https://brokui.dev/r/open/calendar-event-card.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

API

manifest knowledge + registry-derived coverage

Props

Props accepted by this component: name, type, default value and description.
Prop Type Default Description
title string Product sync
date string Tue, 16 Jun
start string 10:00
end string 10:45
location string Google Meet
tone string primary
attendees array []
href mixed | null null
joinLabel string Join

Slots

  • default —

Data slots

Stable hooks for CSS overrides and browser tests.

calendar-event-card

Behavior

  • tone colours the accent bar and time chip; date, start and end render as given, with no parsing.
  • attendees renders as an avatar-group; href adds the join action labelled by joinLabel.
  • Declares registry capability flags: a11y, responsive, rtl, darkMode, localized.

Guidance

Card and content widget

Present a self-contained content object with local context.

Use when

  • Use when self-contained content objects benefit from a recognizable card-like presentation with local actions or metadata.
  • Showing one upcoming event with its time, place and attendees in an agenda or dashboard.
  • Offering a join link beside the event details.

Avoid when

  • Do not use card widgets where a simpler list, table, or plain text block would make comparison faster.
  • Rendering a whole calendar; calendar and mini-calendar lay out dates.
  • Listing many events compactly, where a table or list-panel reads faster.

Use instead

  • List for compact scanning
  • Table for exact comparison

Anti-patterns

  • Using cards for dense cross-item comparison
Anatomy
root
Theming hooks
calendar-event-card

Accessibility

WCAG 2.2 AA Keyboard focus-visible RTL-ready Localized labels Dark mode
Keyboard
No component-owned keyboard interaction; native element behavior applies.
Focus
none
  • The attendee group is labelled, so avatars are announced as attendees rather than as unnamed images.
  • The tone accent is decorative; the time and location are text.
  • Semantic HTML and a stable data-slot attribute for styling and scripting hooks.
  • Focus-visible rings use the ring token, so keyboard focus is always visible.
  • Disabled and invalid states are conveyed to assistive tech, not by color alone.
  • Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
  • Labels go through __() and layout uses logical properties (ms-*, text-start), so it mirrors under dir="rtl" — flip the preview to RTL to confirm.
  • Dark mode uses the same semantic tokens under the dark class; high contrast follows forced-color system tokens.

Livewire

Safe

Livewire can update this component through forwarded wire:* attributes.

Source

The exact, editable file ui:add writes into your app. Previews render this same code; there are no preview-only components.

resources/views/components/ui/calendar-event-card.blade.php Blade
@props([
    'title' => 'Product sync',
    'date' => 'Tue, 16 Jun',
    'start' => '10:00',
    'end' => '10:45',
    'location' => 'Google Meet',
    'tone' => 'primary',
    'attendees' => [],
    'href' => null,
    'joinLabel' => 'Join',
])

@php
    $attendees = is_array($attendees) ? $attendees : [];

    // Tone → accent bar + soft time chip. Full static class strings so the JIT
    // sees every utility; falls back to primary for unknown tones.
    $tones = [
        'primary' => ['bar' => 'bg-primary', 'chip' => 'bg-primary/10 text-primary'],
        'success' => ['bar' => 'bg-success', 'chip' => 'bg-success/10 text-success'],
        'warning' => ['bar' => 'bg-warning', 'chip' => 'bg-warning/10 text-warning'],
        'info' => ['bar' => 'bg-info', 'chip' => 'bg-info/10 text-info'],
        'destructive' => ['bar' => 'bg-destructive', 'chip' => 'bg-destructive/10 text-destructive'],
    ];
    $t = $tones[$tone] ?? $tones['primary'];

    $time = trim(($start ?? '').($end ? ' – '.$end : ''));
@endphp

{{--
    Calendar event card — a single scheduled event. A tone-coloured accent bar
    runs down the start edge (logical inset, so it mirrors under RTL); the title,
    time chip, date and location stack alongside, with an optional attendee
    avatar stack and a join action. All text is auto-escaped.
--}}
<div
    data-slot="calendar-event-card"
    data-tone="{{ $tone }}"
    {{ $attributes->merge(['class' => 'relative overflow-hidden rounded-lg border border-border bg-card p-6 ps-6 text-foreground shadow-sm']) }}
>
    <span class="absolute inset-y-0 start-0 w-2 {{ $t['bar'] }}" aria-hidden="true"></span>

    <div class="flex items-start justify-between gap-3">
        <div class="min-w-0">
            <h3 class="truncate text-sm font-semibold">{{ $title }}</h3>
            @if ($date)
                <p class="mt-0.5 text-xs text-muted-foreground">{{ $date }}</p>
            @endif
        </div>
        @if ($time)
            <span class="inline-flex shrink-0 items-center rounded-md px-2 py-0.5 text-xs font-medium {{ $t['chip'] }}">{{ $time }}</span>
        @endif
    </div>

    @if ($location)
        <p class="mt-3 inline-flex items-center gap-2 text-xs text-muted-foreground">
            <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" class="size-4 shrink-0">
                <path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
                <circle cx="12" cy="10" r="3" />
            </svg>
            <span class="truncate">{{ $location }}</span>
        </p>
    @endif

    @if (count($attendees) || $href)
        <div class="mt-4 flex items-center justify-between gap-3">
            @if (count($attendees))
                <div class="flex -space-x-2" aria-label="{{ __('Attendees') }}">
                    @foreach (array_slice($attendees, 0, 4) as $person)
                        <x-ui.avatar
                            size="sm"
                            :src="$person['src'] ?? null"
                            :alt="$person['name'] ?? ''"
                            :fallback="$person['name'] ?? null"
                            class="ring-2 ring-card"
                        />
                    @endforeach
                    @if (count($attendees) > 4)
                        <span class="z-10 inline-flex size-8 items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground ring-2 ring-card">+{{ count($attendees) - 4 }}</span>
                    @endif
                </div>
            @else
                <span></span>
            @endif

            @if ($href)
                <x-ui.button :href="$href" size="sm" variant="outline" class="shrink-0">{{ __($joinLabel) }}</x-ui.button>
            @endif
        </div>
    @endif
</div>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.0.4
Status
Stable
License
open
Accessibility reviewed
No review date recorded
Last breaking change
No date recorded
Deprecation
Not deprecated
Contract
v6
Foundation
≥ 1.0.0