Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Hour-grid schedule for a single day using calendar-event and hour-view elements with two-layer rendering for multi-hour spanning.
The <day-view> component renders a day schedule as an hour grid. Authors write semantic markup using <ol>, <time>, <hour-view>, and <calendar-event>. The component enhances this with a two-layer rendering system: CSS Grid for the hour layout, and JS absolute positioning for events that span multiple hours.
Each hour is an <li> containing a <time> label and an <hour-view> container. Events go inside <hour-view> as <calendar-event> elements.
<day-view data-date="2026-04-10"> <ol> <li> <time datetime="09:00">9 AM</time> <hour-view> <calendar-event data-category="meeting"> <time datetime="09:00">9:00</time> <icon-wc name="users" size="sm"></icon-wc> Sprint standup </calendar-event> </hour-view> </li> <li> <time datetime="10:00">10 AM</time> <hour-view> <calendar-event data-category="meeting" data-duration="2h"> <time datetime="10:00">10:00</time> Design review </calendar-event> </hour-view> </li> <li> <time datetime="11:00">11 AM</time> <hour-view></hour-view> </li> </ol></day-view>
| Element | Purpose |
|---|---|
<ol> | Ordered list of hour slots |
<li> | One hour: contains <time> + <hour-view> |
<time datetime="HH:00"> | Hour label |
<hour-view> | Subgrid container for events within the hour |
<calendar-event> | Individual event with time, category, duration |
| Attribute | Type | Default | Description |
|---|---|---|---|
data-date |
ISO date | — | The date this view represents. |
data-start-hour |
number | "auto" |
7 |
First visible hour, or "auto" to scan events and compute sparse range. |
data-end-hour |
number | 19 |
Last visible hour. Ignored when data-start-hour="auto". |
data-compact |
boolean | — | Compact presentation for embedding in dialogs or overlays. |
Set data-start-hour="auto" and place <calendar-event> children directly inside <day-view> (no <ol>). The component scans event times, computes a sparse hour range (first event hour − 1 to last event hour + 1), and builds the hour grid automatically. Untimed events are placed in an all-day section.
<day-view data-date="2026-04-10" data-start-hour="auto"> <calendar-event> <time datetime="09:00">9:00 AM</time> Sprint standup </calendar-event> <calendar-event> <time datetime="14:00">2:00 PM</time> Code review </calendar-event> <calendar-event> Team lunch (all day) </calendar-event></day-view>
This is used by <calendar-wc> to render day detail overlays from event data.
Events starting at :30 are placed in the bottom half of their hour row using data-start="30".
<hour-view> <calendar-event data-category="personal" data-start="30"> <time datetime="08:30">8:30</time> <icon-wc name="coffee" size="sm"></icon-wc> Morning coffee </calendar-event></hour-view>
Add data-duration to span across multiple hour rows. The component positions these events absolutely over the grid using measured coordinates.
<calendar-event data-category="meeting" data-duration="2h"> <time datetime="10:00">10:00</time> <icon-wc name="palette" size="sm"></icon-wc> Design review</calendar-event>
Supported durations: 1h, 1h30m, 2h, 3h.
Leave the subsequent hour's <hour-view> empty — the spanning event overlays it visually.
When two events occupy the same time slot, add data-overlap to the <hour-view> to display them side by side.
<hour-view data-overlap> <calendar-event data-category="focus"> <time datetime="14:00">2:00</time> Code review </calendar-event> <calendar-event data-category="meeting"> <time datetime="14:00">2:00</time> 1:1 with Sarah </calendar-event></hour-view>
Place all-day events in a <ul class="all-day-events"> above the hour list.
<day-view> <ul class="all-day-events"> <li> <calendar-event data-category="personal"> <icon-wc name="globe" size="sm"></icon-wc> Earth Day (all day) </calendar-event> </li> </ul> <ol>...</ol></day-view>
| Event | Detail | Description |
|---|---|---|
day-view:event-click |
{ time, text, element, category, duration } |
Fired when a <calendar-event> is clicked. |
The component uses two rendering layers:
| Layer | Mechanism | Handles |
|---|---|---|
| Grid | CSS Grid + subgrid | Hour rows, half-hour positioning, double-booking columns |
| Overlay | JS absolute positioning | Multi-hour spanning events (measured against grid rows) |
Hour dividers use box-shadow instead of border to avoid gaps in the spanning calculations.
| Layer | What renders |
|---|---|
| HTML only | Ordered list of hours with events — readable, semantic |
| + CSS | Grid layout, category colors, half-hour positioning |
| + JS | Multi-hour spanning, click events, keyboard navigation |
| Key | Action |
|---|---|
| Arrow Down | Move focus to next event |
| Arrow Up | Move focus to previous event |
<calendar-event> — Event block element<hour-view> — Hour container element<calendar-wc> — Month calendar with events