Skip to content

Month view

Month viewEach day shows its events from the model and links to the day's agenda.
Thymeleaf source
<sl:month-view day-href="/agenda/{date}">
<sl:slot name="day">
<sl:badge th:each="event : ${events[slDay.date]}" variant="secondary">[[${event}]]</sl:badge>
</sl:slot>
</sl:month-view>
Rendered HTML
<div class="month-view">
<div class="month-view-nav">
<a class="month-view-nav-button month-view-previous" href="/?month=2026-09" aria-label="Go to the previous month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6"></path>
</svg>
</a>
<a class="month-view-nav-button month-view-next" href="/?month=2026-11" aria-label="Go to the next month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6"></path>
</svg>
</a>
</div>
<table class="month-view-grid">
<caption class="month-view-caption">October 2026</caption>
<thead>
<tr class="month-view-weekdays">
<th scope="col" class="month-view-weekday" aria-label="Sunday">Su</th>
<th scope="col" class="month-view-weekday" aria-label="Monday">Mo</th>
<th scope="col" class="month-view-weekday" aria-label="Tuesday">Tu</th>
<th scope="col" class="month-view-weekday" aria-label="Wednesday">We</th>
<th scope="col" class="month-view-weekday" aria-label="Thursday">Th</th>
<th scope="col" class="month-view-weekday" aria-label="Friday">Fr</th>
<th scope="col" class="month-view-weekday" aria-label="Saturday">Sa</th>
</tr>
</thead>
<tbody>
<tr class="month-view-week">
<td class="month-view-day" data-outside="true">
<a class="month-view-day-link" href="/agenda/2026-09-27">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Sunday, September 27, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day" data-outside="true">
<a class="month-view-day-link" href="/agenda/2026-09-28">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Monday, September 28, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day" data-outside="true">
<a class="month-view-day-link" href="/agenda/2026-09-29">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Tuesday, September 29, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day" data-outside="true">
<a class="month-view-day-link" href="/agenda/2026-09-30">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Wednesday, September 30, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-01">
<span class="month-view-day-number" aria-hidden="true">1</span>
<span class="sl-sr-only">Thursday, October 1, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-02">
<span class="month-view-day-number" aria-hidden="true">2</span>
<span class="sl-sr-only">Friday, October 2, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-03">
<span class="month-view-day-number" aria-hidden="true">3</span>
<span class="sl-sr-only">Saturday, October 3, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-04">
<span class="month-view-day-number" aria-hidden="true">4</span>
<span class="sl-sr-only">Sunday, October 4, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-05">
<span class="month-view-day-number" aria-hidden="true">5</span>
<span class="sl-sr-only">Monday, October 5, 2026</span>
<div class="month-view-day-content">
<span class="badge" data-variant="secondary">Standup</span>
</div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-06">
<span class="month-view-day-number" aria-hidden="true">6</span>
<span class="sl-sr-only">Tuesday, October 6, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-07">
<span class="month-view-day-number" aria-hidden="true">7</span>
<span class="sl-sr-only">Wednesday, October 7, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-08">
<span class="month-view-day-number" aria-hidden="true">8</span>
<span class="sl-sr-only">Thursday, October 8, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-09">
<span class="month-view-day-number" aria-hidden="true">9</span>
<span class="sl-sr-only">Friday, October 9, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-10">
<span class="month-view-day-number" aria-hidden="true">10</span>
<span class="sl-sr-only">Saturday, October 10, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-11">
<span class="month-view-day-number" aria-hidden="true">11</span>
<span class="sl-sr-only">Sunday, October 11, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-12">
<span class="month-view-day-number" aria-hidden="true">12</span>
<span class="sl-sr-only">Monday, October 12, 2026</span>
<div class="month-view-day-content">
<span class="badge" data-variant="secondary">Release</span>
<span class="badge" data-variant="secondary">Retro</span>
</div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-13">
<span class="month-view-day-number" aria-hidden="true">13</span>
<span class="sl-sr-only">Tuesday, October 13, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-14">
<span class="month-view-day-number" aria-hidden="true">14</span>
<span class="sl-sr-only">Wednesday, October 14, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-15">
<span class="month-view-day-number" aria-hidden="true">15</span>
<span class="sl-sr-only">Thursday, October 15, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-16">
<span class="month-view-day-number" aria-hidden="true">16</span>
<span class="sl-sr-only">Friday, October 16, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-17">
<span class="month-view-day-number" aria-hidden="true">17</span>
<span class="sl-sr-only">Saturday, October 17, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-18">
<span class="month-view-day-number" aria-hidden="true">18</span>
<span class="sl-sr-only">Sunday, October 18, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-19">
<span class="month-view-day-number" aria-hidden="true">19</span>
<span class="sl-sr-only">Monday, October 19, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-20">
<span class="month-view-day-number" aria-hidden="true">20</span>
<span class="sl-sr-only">Tuesday, October 20, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-21">
<span class="month-view-day-number" aria-hidden="true">21</span>
<span class="sl-sr-only">Wednesday, October 21, 2026</span>
<div class="month-view-day-content">
<span class="badge" data-variant="secondary">Offsite</span>
</div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-22">
<span class="month-view-day-number" aria-hidden="true">22</span>
<span class="sl-sr-only">Thursday, October 22, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day" data-today="true">
<a class="month-view-day-link" href="/agenda/2026-10-23" aria-current="date">
<span class="month-view-day-number" aria-hidden="true">23</span>
<span class="sl-sr-only">Friday, October 23, 2026</span>
<div class="month-view-day-content">
<span class="badge" data-variant="secondary">Demo</span>
</div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-24">
<span class="month-view-day-number" aria-hidden="true">24</span>
<span class="sl-sr-only">Saturday, October 24, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-25">
<span class="month-view-day-number" aria-hidden="true">25</span>
<span class="sl-sr-only">Sunday, October 25, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-26">
<span class="month-view-day-number" aria-hidden="true">26</span>
<span class="sl-sr-only">Monday, October 26, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-27">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Tuesday, October 27, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-28">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Wednesday, October 28, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-29">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Thursday, October 29, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-30">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Friday, October 30, 2026</span>
<div class="month-view-day-content">
<span class="badge" data-variant="secondary">Planning</span>
</div>
</a>
</td>
<td class="month-view-day">
<a class="month-view-day-link" href="/agenda/2026-10-31">
<span class="month-view-day-number" aria-hidden="true">31</span>
<span class="sl-sr-only">Saturday, October 31, 2026</span>
<div class="month-view-day-content"></div>
</a>
</td>
</tr>
</tbody>
</table>
</div>

<sl:month-view> shows a month to look at, not to pick from: an agenda, a booking overview, orders per day. The server renders it whole, so it needs no JavaScript. For a date in a form, use the calendar or the date picker.

The day slot is rendered once for every day, and sees that day as ${slDay}:

Property
date The day as a LocalDate, to look it up in your model: ${events[slDay.date]}
iso The same as an ISO string: 2026-10-23
number The day of the month, which the cell shows
label The whole date in the page’s locale (Friday, October 23, 2026), which screen readers get
outside Whether the day belongs to the previous or next month
today Whether it is today

Put the data in the model as a map from LocalDate to what a day shows, and look the day up in the slot:

@GetMapping("/agenda")
String agenda(Model model) {
model.addAttribute("events", agenda.eventsByDay()); // Map<LocalDate, List<String>>
return "agenda";
}
<sl:month-view day-href="/agenda/{date}">
<sl:slot name="day">
<sl:badge th:each="event : ${events[slDay.date]}" variant="secondary">[[${event}]]</sl:badge>
</sl:slot>
</sl:month-view>

The seven days share the width. Content wider than its day is cut off, so keep it short: a badge, a count, a word.

day-href makes every day a link. {date} in it is replaced by the day’s ISO date: /agenda/{date} links to /agenda/2026-10-23, ?date={date} to the same page with a parameter. The result is a Thymeleaf link, so a path that starts with / gets the context path.

The link holds the day’s number, its whole date for screen readers, and the slot’s content. So a screen reader reads “Friday, October 23, 2026, Demo”. Put nothing interactive in the slot then: a link cannot hold a button or another link. Today’s day is marked aria-current="date".

Without day-href, the days are no links.

The previous and next buttons are links to the same page with ?month=2026-09; every other parameter of the request is kept, so a filter (?team=ops) stays. Without a month attribute, <sl:month-view> reads that parameter itself, so the controller needs nothing for it. A value that is no month falls back to the current month.

To read it in the controller, take a YearMonth (Spring converts 2026-10) and pass it on:

@GetMapping("/agenda")
String agenda(@RequestParam(required = false) YearMonth month, Model model) {
YearMonth shown = month != null ? month : YearMonth.now();
model.addAttribute("month", shown);
model.addAttribute("events", agenda.eventsByDay(shown));
return "agenda";
}
<sl:month-view th:month="${month}">...</sl:month-view>

month takes a YearMonth, a LocalDate in the month, or the text 2026-10. month-param renames the parameter, for a second month view on the page.

Today is marked; by default that is the server’s date. If your users are in another time zone, put their date in the model (LocalDate.now(zone)) and pass it: th:today="${today}".

nav-size sets the size of the previous and next links, with the sizes of an icon <sl:button> (icon-xs, icon-sm, icon, icon-lg), so they can match the buttons elsewhere on the page. Without it they have the size of the skin’s calendar. On a touch screen the links have a hit area of at least 44 by 44 pixels whatever their size, as the icon buttons.

Size of the navigationThe previous and next links take the size of an icon button, here icon-lg, to match the buttons around the month. On a touch screen their hit area is at least 44 by 44 pixels whatever they look like.
Thymeleaf source
<sl:month-view nav-size="icon-lg"/>
Rendered HTML
<div class="month-view" data-nav-size="icon-lg">
<div class="month-view-nav">
<a class="month-view-nav-button month-view-previous" href="/?month=2026-09" aria-label="Go to the previous month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6"></path>
</svg>
</a>
<a class="month-view-nav-button month-view-next" href="/?month=2026-11" aria-label="Go to the next month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6"></path>
</svg>
</a>
</div>
<table class="month-view-grid">
<caption class="month-view-caption">October 2026</caption>
<thead>
<tr class="month-view-weekdays">
<th scope="col" class="month-view-weekday" aria-label="Sunday">Su</th>
<th scope="col" class="month-view-weekday" aria-label="Monday">Mo</th>
<th scope="col" class="month-view-weekday" aria-label="Tuesday">Tu</th>
<th scope="col" class="month-view-weekday" aria-label="Wednesday">We</th>
<th scope="col" class="month-view-weekday" aria-label="Thursday">Th</th>
<th scope="col" class="month-view-weekday" aria-label="Friday">Fr</th>
<th scope="col" class="month-view-weekday" aria-label="Saturday">Sa</th>
</tr>
</thead>
<tbody>
<tr class="month-view-week">
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Sunday, September 27, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Monday, September 28, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Tuesday, September 29, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Wednesday, September 30, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">1</span>
<span class="sl-sr-only">Thursday, October 1, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">2</span>
<span class="sl-sr-only">Friday, October 2, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">3</span>
<span class="sl-sr-only">Saturday, October 3, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">4</span>
<span class="sl-sr-only">Sunday, October 4, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">5</span>
<span class="sl-sr-only">Monday, October 5, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">6</span>
<span class="sl-sr-only">Tuesday, October 6, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">7</span>
<span class="sl-sr-only">Wednesday, October 7, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">8</span>
<span class="sl-sr-only">Thursday, October 8, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">9</span>
<span class="sl-sr-only">Friday, October 9, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">10</span>
<span class="sl-sr-only">Saturday, October 10, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">11</span>
<span class="sl-sr-only">Sunday, October 11, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">12</span>
<span class="sl-sr-only">Monday, October 12, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">13</span>
<span class="sl-sr-only">Tuesday, October 13, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">14</span>
<span class="sl-sr-only">Wednesday, October 14, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">15</span>
<span class="sl-sr-only">Thursday, October 15, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">16</span>
<span class="sl-sr-only">Friday, October 16, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">17</span>
<span class="sl-sr-only">Saturday, October 17, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">18</span>
<span class="sl-sr-only">Sunday, October 18, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">19</span>
<span class="sl-sr-only">Monday, October 19, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">20</span>
<span class="sl-sr-only">Tuesday, October 20, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">21</span>
<span class="sl-sr-only">Wednesday, October 21, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">22</span>
<span class="sl-sr-only">Thursday, October 22, 2026</span>
</div>
</td>
<td class="month-view-day" data-today="true">
<div class="month-view-day-body" aria-current="date">
<span class="month-view-day-number" aria-hidden="true">23</span>
<span class="sl-sr-only">Friday, October 23, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">24</span>
<span class="sl-sr-only">Saturday, October 24, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">25</span>
<span class="sl-sr-only">Sunday, October 25, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">26</span>
<span class="sl-sr-only">Monday, October 26, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Tuesday, October 27, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Wednesday, October 28, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Thursday, October 29, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Friday, October 30, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">31</span>
<span class="sl-sr-only">Saturday, October 31, 2026</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>

Week numbers and the first day of the week

Section titled “Week numbers and the first day of the week”

As for the calendar, the page’s locale decides the first day of the week and how weeks are numbered, and the names of the month and the days. week-starts-on overrides the first day: 0 is Sunday, 1 Monday, up to 6. show-week-number adds a column with the week numbers. show-outside-days="false" leaves the days of the previous and next month empty.

Counts and week numbersA count per day, no links. Monday first, with the week numbers; the days of the other months left out.
Thymeleaf source
<sl:month-view show-outside-days="false" show-week-number week-starts-on="1">
<sl:slot name="day">
<span th:if="${orders[slDay.date]}">[[${orders[slDay.date]}]] orders</span>
</sl:slot>
</sl:month-view>
Rendered HTML
<div class="month-view">
<div class="month-view-nav">
<a class="month-view-nav-button month-view-previous" href="/?month=2026-09" aria-label="Go to the previous month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6"></path>
</svg>
</a>
<a class="month-view-nav-button month-view-next" href="/?month=2026-11" aria-label="Go to the next month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6"></path>
</svg>
</a>
</div>
<table class="month-view-grid">
<caption class="month-view-caption">October 2026</caption>
<thead>
<tr class="month-view-weekdays">
<th scope="col" class="month-view-week-number-header">
<span class="sl-sr-only">Week</span>
</th>
<th scope="col" class="month-view-weekday" aria-label="Monday">Mo</th>
<th scope="col" class="month-view-weekday" aria-label="Tuesday">Tu</th>
<th scope="col" class="month-view-weekday" aria-label="Wednesday">We</th>
<th scope="col" class="month-view-weekday" aria-label="Thursday">Th</th>
<th scope="col" class="month-view-weekday" aria-label="Friday">Fr</th>
<th scope="col" class="month-view-weekday" aria-label="Saturday">Sa</th>
<th scope="col" class="month-view-weekday" aria-label="Sunday">Su</th>
</tr>
</thead>
<tbody>
<tr class="month-view-week">
<th scope="row" class="month-view-week-number" aria-label="Week 40">40</th>
<td class="month-view-day" data-outside="true" data-hidden="true"></td>
<td class="month-view-day" data-outside="true" data-hidden="true"></td>
<td class="month-view-day" data-outside="true" data-hidden="true"></td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">1</span>
<span class="sl-sr-only">Thursday, October 1, 2026</span>
<div class="month-view-day-content">
<span>4 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">2</span>
<span class="sl-sr-only">Friday, October 2, 2026</span>
<div class="month-view-day-content">
<span>7 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">3</span>
<span class="sl-sr-only">Saturday, October 3, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">4</span>
<span class="sl-sr-only">Sunday, October 4, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
</tr>
<tr class="month-view-week">
<th scope="row" class="month-view-week-number" aria-label="Week 41">41</th>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">5</span>
<span class="sl-sr-only">Monday, October 5, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">6</span>
<span class="sl-sr-only">Tuesday, October 6, 2026</span>
<div class="month-view-day-content">
<span>3 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">7</span>
<span class="sl-sr-only">Wednesday, October 7, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">8</span>
<span class="sl-sr-only">Thursday, October 8, 2026</span>
<div class="month-view-day-content">
<span>12 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">9</span>
<span class="sl-sr-only">Friday, October 9, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">10</span>
<span class="sl-sr-only">Saturday, October 10, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">11</span>
<span class="sl-sr-only">Sunday, October 11, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
</tr>
<tr class="month-view-week">
<th scope="row" class="month-view-week-number" aria-label="Week 42">42</th>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">12</span>
<span class="sl-sr-only">Monday, October 12, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">13</span>
<span class="sl-sr-only">Tuesday, October 13, 2026</span>
<div class="month-view-day-content">
<span>5 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">14</span>
<span class="sl-sr-only">Wednesday, October 14, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">15</span>
<span class="sl-sr-only">Thursday, October 15, 2026</span>
<div class="month-view-day-content">
<span>9 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">16</span>
<span class="sl-sr-only">Friday, October 16, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">17</span>
<span class="sl-sr-only">Saturday, October 17, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">18</span>
<span class="sl-sr-only">Sunday, October 18, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
</tr>
<tr class="month-view-week">
<th scope="row" class="month-view-week-number" aria-label="Week 43">43</th>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">19</span>
<span class="sl-sr-only">Monday, October 19, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">20</span>
<span class="sl-sr-only">Tuesday, October 20, 2026</span>
<div class="month-view-day-content">
<span>2 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">21</span>
<span class="sl-sr-only">Wednesday, October 21, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">22</span>
<span class="sl-sr-only">Thursday, October 22, 2026</span>
<div class="month-view-day-content">
<span>8 orders</span>
</div>
</div>
</td>
<td class="month-view-day" data-today="true">
<div class="month-view-day-body" aria-current="date">
<span class="month-view-day-number" aria-hidden="true">23</span>
<span class="sl-sr-only">Friday, October 23, 2026</span>
<div class="month-view-day-content">
<span>6 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">24</span>
<span class="sl-sr-only">Saturday, October 24, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">25</span>
<span class="sl-sr-only">Sunday, October 25, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
</tr>
<tr class="month-view-week">
<th scope="row" class="month-view-week-number" aria-label="Week 44">44</th>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">26</span>
<span class="sl-sr-only">Monday, October 26, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Tuesday, October 27, 2026</span>
<div class="month-view-day-content">
<span>11 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Wednesday, October 28, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Thursday, October 29, 2026</span>
<div class="month-view-day-content">
<span>1 orders</span>
</div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Friday, October 30, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">31</span>
<span class="sl-sr-only">Saturday, October 31, 2026</span>
<div class="month-view-day-content"></div>
</div>
</td>
<td class="month-view-day" data-outside="true" data-hidden="true"></td>
</tr>
</tbody>
</table>
</div>
Without contentWithout a day slot or day-href, the month only shows its dates.
Thymeleaf source
<sl:month-view/>
Rendered HTML
<div class="month-view">
<div class="month-view-nav">
<a class="month-view-nav-button month-view-previous" href="/?month=2026-09" aria-label="Go to the previous month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m15 18-6-6 6-6"></path>
</svg>
</a>
<a class="month-view-nav-button month-view-next" href="/?month=2026-11" aria-label="Go to the next month">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="m9 18 6-6-6-6"></path>
</svg>
</a>
</div>
<table class="month-view-grid">
<caption class="month-view-caption">October 2026</caption>
<thead>
<tr class="month-view-weekdays">
<th scope="col" class="month-view-weekday" aria-label="Sunday">Su</th>
<th scope="col" class="month-view-weekday" aria-label="Monday">Mo</th>
<th scope="col" class="month-view-weekday" aria-label="Tuesday">Tu</th>
<th scope="col" class="month-view-weekday" aria-label="Wednesday">We</th>
<th scope="col" class="month-view-weekday" aria-label="Thursday">Th</th>
<th scope="col" class="month-view-weekday" aria-label="Friday">Fr</th>
<th scope="col" class="month-view-weekday" aria-label="Saturday">Sa</th>
</tr>
</thead>
<tbody>
<tr class="month-view-week">
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Sunday, September 27, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Monday, September 28, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Tuesday, September 29, 2026</span>
</div>
</td>
<td class="month-view-day" data-outside="true">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Wednesday, September 30, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">1</span>
<span class="sl-sr-only">Thursday, October 1, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">2</span>
<span class="sl-sr-only">Friday, October 2, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">3</span>
<span class="sl-sr-only">Saturday, October 3, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">4</span>
<span class="sl-sr-only">Sunday, October 4, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">5</span>
<span class="sl-sr-only">Monday, October 5, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">6</span>
<span class="sl-sr-only">Tuesday, October 6, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">7</span>
<span class="sl-sr-only">Wednesday, October 7, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">8</span>
<span class="sl-sr-only">Thursday, October 8, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">9</span>
<span class="sl-sr-only">Friday, October 9, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">10</span>
<span class="sl-sr-only">Saturday, October 10, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">11</span>
<span class="sl-sr-only">Sunday, October 11, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">12</span>
<span class="sl-sr-only">Monday, October 12, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">13</span>
<span class="sl-sr-only">Tuesday, October 13, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">14</span>
<span class="sl-sr-only">Wednesday, October 14, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">15</span>
<span class="sl-sr-only">Thursday, October 15, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">16</span>
<span class="sl-sr-only">Friday, October 16, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">17</span>
<span class="sl-sr-only">Saturday, October 17, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">18</span>
<span class="sl-sr-only">Sunday, October 18, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">19</span>
<span class="sl-sr-only">Monday, October 19, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">20</span>
<span class="sl-sr-only">Tuesday, October 20, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">21</span>
<span class="sl-sr-only">Wednesday, October 21, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">22</span>
<span class="sl-sr-only">Thursday, October 22, 2026</span>
</div>
</td>
<td class="month-view-day" data-today="true">
<div class="month-view-day-body" aria-current="date">
<span class="month-view-day-number" aria-hidden="true">23</span>
<span class="sl-sr-only">Friday, October 23, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">24</span>
<span class="sl-sr-only">Saturday, October 24, 2026</span>
</div>
</td>
</tr>
<tr class="month-view-week">
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">25</span>
<span class="sl-sr-only">Sunday, October 25, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">26</span>
<span class="sl-sr-only">Monday, October 26, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">27</span>
<span class="sl-sr-only">Tuesday, October 27, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">28</span>
<span class="sl-sr-only">Wednesday, October 28, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">29</span>
<span class="sl-sr-only">Thursday, October 29, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">30</span>
<span class="sl-sr-only">Friday, October 30, 2026</span>
</div>
</td>
<td class="month-view-day">
<div class="month-view-day-body">
<span class="month-view-day-number" aria-hidden="true">31</span>
<span class="sl-sr-only">Saturday, October 31, 2026</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>

The month links are plain links, so hx-boost on the page, or hx-get with hx-target and hx-select on a container around the month view, swaps the next month in. The controller renders the same page; nothing in the month view needs JavaScript.

  • The month is a <table>, named by its caption (October 2026). The column headers carry the whole name of the day (Monday), the week numbers are row headers.
  • Each day says its whole date, then its content.
  • It is no ARIA grid: the arrow keys do not move between days. Tab goes through the previous and next links, then through the days that are links.
AttributeValuesDefaultDescription
monthstring—The month shown, as 2026-10 (a YearMonth) or a date in it. By default the month the request asks for in month-param, or else the current month.
month-paramstringmonthThe request parameter the links to the previous and next month set, and that gives the month when month is not set.
day-hrefstring—Makes every day a link: {date} is replaced by the day's ISO date (/agenda/{date}, ?date={date}), and the result is a Thymeleaf link, so a path starting with / gets the context path. The day slot is then inside the link: put nothing interactive in it.
todaystring—Today, as 2026-10-23 (a LocalDate), marked as the current date. By default the server's date; pass it in the user's time zone when that differs.
show-outside-daysbooleantrueShow the days of the previous and next month that fill the first and last week.
show-week-numberboolean—Show the week numbers, counted as the page's locale counts them (ISO weeks in most of Europe).
nav-sizedefault icon-xs icon-sm icon icon-lgdefaultSize of the previous and next month links, the sizes of an icon sl:button, to match the buttons elsewhere on the page. By default the skin's calendar size. On a touch screen the link is always at least 44 by 44 pixels to hit, whatever it looks like.
week-starts-onnumber—The first day of the week: 0 is Sunday, 1 Monday, up to 6. By default the page's locale decides.

Every prop can also be set from an expression: th:month="${...}". Any other attribute passes through to the rendered element, and class is appended.