Calendars
A month of days with what happens on each, and a strip of days across the things that can be busy on them - equipment, rooms, boats.
A package of the release
Calendars are linked apart, on the screens that show them, beside the two files; they need no script.
<link rel="stylesheet" href="redz-ui/css/redz-ui-calendar.min.css">
A month
table class="calendar": a weekday header, the week starting on the day the page chooses, then six weeks of days. A day holds its time class="calendar-day", its events - calendar-event, a dot of a tone and the words, cut to the width, the whole in its title - and calendar-more for the rest. data-outside quiets a day of another month, data-weekend tints a weekend, aria-current="date" marks today. In a region narrower than 576 px the events fold to their dots. The heading, the previous and next months and the switch of views are the page's links.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
Excavator | Excavator | Excavator Scaffold set Concrete mixer +2 more | Generator | |||
<div class="hstack flex-wrap gap-8">
<div class="btn-group" role="group" aria-label="View">
<a class="btn btn-sm" href="#calendar-strip">Days</a>
<a class="btn btn-sm" href="#calendar-equipment" aria-current="page">Month</a>
</div>
<a class="btn btn-sm btn-icon" href="#calendar-equipment" aria-label="October"><i class="bi bi-chevron-left flip-rtl" aria-hidden="true"></i></a>
<h3 class="fs-14">November 2026</h3>
<a class="btn btn-sm btn-icon" href="#calendar-equipment" aria-label="December"><i class="bi bi-chevron-right flip-rtl" aria-hidden="true"></i></a>
<a class="btn btn-sm btn-text" href="#calendar-equipment">Today</a>
</div>
<table class="calendar">
<caption class="visually-hidden">Equipment booked in November 2026</caption>
<thead><tr><th scope="col"><abbr title="Monday">Mon</abbr></th><th scope="col"><abbr title="Tuesday">Tue</abbr></th><th scope="col"><abbr title="Wednesday">Wed</abbr></th><th scope="col"><abbr title="Thursday">Thu</abbr></th><th scope="col"><abbr title="Friday">Fri</abbr></th><th scope="col"><abbr title="Saturday">Sat</abbr></th><th scope="col"><abbr title="Sunday">Sun</abbr></th></tr></thead>
<tbody>
<tr><td data-outside><time class="calendar-day" datetime="2026-10-26">26</time></td><td data-outside><time class="calendar-day" datetime="2026-10-27">27</time></td><td data-outside><time class="calendar-day" datetime="2026-10-28">28</time></td><td data-outside><time class="calendar-day" datetime="2026-10-29">29</time></td><td data-outside><time class="calendar-day" datetime="2026-10-30">30</time></td><td data-outside data-weekend><time class="calendar-day" datetime="2026-10-31">31</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-01">1</time></td></tr>
<tr><td><time class="calendar-day" datetime="2026-11-02">2</time><div class="calendar-event" title="Excavator · Riverside tower"><span class="dot dot-primary"></span><span>Excavator</span></div></td><td><time class="calendar-day" datetime="2026-11-03">3</time><div class="calendar-event" title="Excavator · Riverside tower"><span class="dot dot-primary"></span><span>Excavator</span></div></td><td aria-current="date"><time class="calendar-day" datetime="2026-11-04">4</time><div class="calendar-event" title="Excavator · Riverside tower"><span class="dot dot-primary"></span><span>Excavator</span></div><div class="calendar-event" title="Scaffold set · Sid Sample"><span class="dot dot-info"></span><span>Scaffold set</span></div><div class="calendar-event" title="Concrete mixer · Harbor view"><span class="dot dot-primary"></span><span>Concrete mixer</span></div><span class="calendar-more">+2<span class="visually-hidden"> more</span></span></td><td><time class="calendar-day" datetime="2026-11-05">5</time></td><td><time class="calendar-day" datetime="2026-11-06">6</time><div class="calendar-event" title="Generator · Harbor view"><span class="dot dot-info"></span><span>Generator</span></div></td><td data-weekend><time class="calendar-day" datetime="2026-11-07">7</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-08">8</time></td></tr>
<tr><td><time class="calendar-day" datetime="2026-11-09">9</time></td><td><time class="calendar-day" datetime="2026-11-10">10</time></td><td><time class="calendar-day" datetime="2026-11-11">11</time></td><td><time class="calendar-day" datetime="2026-11-12">12</time></td><td><time class="calendar-day" datetime="2026-11-13">13</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-14">14</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-15">15</time></td></tr>
<tr><td><time class="calendar-day" datetime="2026-11-16">16</time></td><td><time class="calendar-day" datetime="2026-11-17">17</time></td><td><time class="calendar-day" datetime="2026-11-18">18</time></td><td><time class="calendar-day" datetime="2026-11-19">19</time></td><td><time class="calendar-day" datetime="2026-11-20">20</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-21">21</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-22">22</time></td></tr>
<tr><td><time class="calendar-day" datetime="2026-11-23">23</time></td><td><time class="calendar-day" datetime="2026-11-24">24</time></td><td><time class="calendar-day" datetime="2026-11-25">25</time></td><td><time class="calendar-day" datetime="2026-11-26">26</time></td><td><time class="calendar-day" datetime="2026-11-27">27</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-28">28</time></td><td data-weekend><time class="calendar-day" datetime="2026-11-29">29</time></td></tr>
<tr><td><time class="calendar-day" datetime="2026-11-30">30</time></td><td data-outside><time class="calendar-day" datetime="2026-12-01">1</time></td><td data-outside><time class="calendar-day" datetime="2026-12-02">2</time></td><td data-outside><time class="calendar-day" datetime="2026-12-03">3</time></td><td data-outside><time class="calendar-day" datetime="2026-12-04">4</time></td><td data-outside data-weekend><time class="calendar-day" datetime="2026-12-05">5</time></td><td data-outside data-weekend><time class="calendar-day" datetime="2026-12-06">6</time></td></tr>
</tbody>
</table>Days in a state
A day's data-state tints it: worked, open, pending, absent and off - a time sheet, the days a person can still book. calendar-legend, a list of items with the same data-state, says what each tint means, and every day says its state in words too - in its button's name, or in a visually-hidden word when it is no button; in forced colors the states draw as a line, a dashed and a dotted one. button.calendar-day makes the day's number a button the page opens or picks the day with - its aria-label the whole date and the state, aria-pressed on the day picked.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
- Worked
- Waiting for approval
- Absent
- Open
- Day off
<table class="calendar">
<caption>Alex Sample, November 2026</caption>
<thead><tr><th scope="col"><abbr title="Monday">Mon</abbr></th><th scope="col"><abbr title="Tuesday">Tue</abbr></th><th scope="col"><abbr title="Wednesday">Wed</abbr></th><th scope="col"><abbr title="Thursday">Thu</abbr></th><th scope="col"><abbr title="Friday">Fri</abbr></th><th scope="col"><abbr title="Saturday">Sat</abbr></th><th scope="col"><abbr title="Sunday">Sun</abbr></th></tr></thead>
<tbody>
<tr><td data-state="worked"><button class="calendar-day" type="button" aria-label="November 2, worked" aria-pressed="false">2</button></td><td data-state="worked"><button class="calendar-day" type="button" aria-label="November 3, worked" aria-pressed="false">3</button></td><td data-state="pending" aria-current="date"><button class="calendar-day" type="button" aria-label="November 4, waiting for approval" aria-pressed="true">4</button></td><td data-state="absent"><button class="calendar-day" type="button" aria-label="November 5, absent" aria-pressed="false">5</button></td><td data-state="open"><button class="calendar-day" type="button" aria-label="November 6, open" aria-pressed="false">6</button></td><td data-state="off" data-weekend><button class="calendar-day" type="button" aria-label="November 7, day off" aria-pressed="false">7</button></td><td data-state="off" data-weekend><button class="calendar-day" type="button" aria-label="November 8, day off" aria-pressed="false">8</button></td></tr>
</tbody>
</table>
<ul class="calendar-legend" aria-label="Day states">
<li data-state="worked">Worked</li>
<li data-state="pending">Waiting for approval</li>
<li data-state="absent">Absent</li>
<li data-state="open">Open</li>
<li data-state="off">Day off</li>
</ul>Days across things
table class="schedule": a column of names, kept in view while the days scroll by, then a column per day with its number and weekday. A cell holds how many are out; data-state="busy" tints it, "over" - more out than there are - marks it, and data-weekend tints a weekend's column. Put it in a scroller: overflow-x-auto.
| Equipment | 2Mon | 3Tue | 4Wed | 5Thu | 6Fri | 7Sat | 8Sun |
|---|---|---|---|---|---|---|---|
| Excavator (1) | 1 | 1 | 1 | ||||
| Scaffold set (3) | 2 | 4 | 3 | ||||
| Generator (2) | 1 | 1 |
<div class="overflow-x-auto" tabindex="0" role="region" aria-labelledby="calendar-days-title">
<table class="schedule">
<caption class="visually-hidden" id="calendar-days-title">Equipment out, November 2 to 8</caption>
<thead><tr><th scope="col">Equipment</th><th scope="col">2<abbr title="Monday">Mon</abbr></th><th scope="col">3<abbr title="Tuesday">Tue</abbr></th><th scope="col">4<abbr title="Wednesday">Wed</abbr></th><th scope="col">5<abbr title="Thursday">Thu</abbr></th><th scope="col">6<abbr title="Friday">Fri</abbr></th><th scope="col" data-weekend>7<abbr title="Saturday">Sat</abbr></th><th scope="col" data-weekend>8<abbr title="Sunday">Sun</abbr></th></tr></thead>
<tbody>
<tr><th scope="row">Excavator <span class="text-muted">(1)</span></th><td data-state="busy">1</td><td data-state="busy">1</td><td data-state="busy">1</td><td></td><td></td><td data-weekend></td><td data-weekend></td></tr>
<tr><th scope="row">Scaffold set <span class="text-muted">(3)</span></th><td></td><td data-state="busy">2</td><td data-state="over">4</td><td data-state="busy">3</td><td></td><td data-weekend></td><td data-weekend></td></tr>
<tr><th scope="row">Generator <span class="text-muted">(2)</span></th><td></td><td></td><td></td><td></td><td data-state="busy">1</td><td data-weekend data-state="busy">1</td><td data-weekend></td></tr>
</tbody>
</table>
</div>Accessibility
- Both are tables: a screen reader reads a day with its weekday's header, a cell with its thing and its day. Weekdays are
abbrwith the full name. - A day's number is a
timewith its date; "+2" says "+2 more" with a hidden word. - A busy or over cell says its number; the tint repeats it, and an over cell is also outlined in forced colors.
- A day's state is in words, never in its tint alone; a day that is a button is named by its whole date and its state, "November 4, waiting for approval", and the picked one says
aria-pressed="true".