@use 'sprucecss/scss/spruce' as *;
.calendar {
--calendar-event-color: #{color('primary')};
background-color: color('surface');
border: config('border-width-base', $display) solid color('border');
border-radius: radius('lg');
overflow: hidden;
&__header {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: spacer('s');
padding: spacer('s') spacer('m');
}
&__title {
font-size: font-size('h4');
margin: 0 auto 0 0;
}
&__navigation {
display: flex;
gap: spacer('xxs');
}
&__weekdays,
&__days {
display: grid;
grid-template-columns: repeat(7, minmax(0, 1fr));
> li {
margin-block: 0;
}
}
&__weekdays {
border-block-start: config('border-width-base', $display) solid color('border');
color: color('muted');
font-size: 0.75rem;
font-weight: 700;
padding-block: spacer('xs');
text-align: center;
text-transform: uppercase;
}
&__days {
@include clear-list;
background-color: color('border');
border-block-start: config('border-width-base', $display) solid color('border');
gap: config('border-width-base', $display);
}
&__day {
background-color: color('surface');
display: flex;
flex-direction: column;
gap: spacer('xxs');
min-block-size: 6.5rem;
min-inline-size: 0;
padding: spacer('xxs');
&--outside {
background-color: color('surface-muted');
.calendar__date {
color: color('muted');
}
}
}
&__date {
align-items: center;
aspect-ratio: 1;
border-radius: radius('pill');
color: color('heading');
display: inline-flex;
font-size: config('font-size-sm', $typography);
font-weight: 600;
inline-size: 1.75rem;
justify-content: center;
&[aria-current='date'] {
background-color: color('primary');
color: color('primary-foreground', 'btn');
}
}
&__events {
@include clear-list;
display: grid;
gap: 2px;
li {
margin: 0;
min-inline-size: 0;
}
> li {
margin-block: 0;
padding-block: 0;
}
}
&__event {
background-color: color-alpha('primary', 0.1);
border-inline-start: 3px solid var(--calendar-event-color);
border-radius: radius('sm');
color: color('heading');
display: block;
font-size: 0.75rem;
line-height: 1.4;
overflow: hidden;
padding: 0.15rem 0.35rem;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
@include transition;
time {
color: color('muted');
}
&:hover {
background-color: color-alpha('primary', 0.18);
}
&:focus-visible {
outline: 2px solid color('focus-ring');
outline-offset: 1px;
}
&--all-day {
background-color: var(--calendar-event-color);
border-inline-start: 0;
color: hsl(0deg 0% 100%);
font-weight: 600;
&:hover {
background-color: var(--calendar-event-color);
opacity: 0.85;
}
}
&--success {
--calendar-event-color: #{color('success', 'alert')};
}
&--warning {
--calendar-event-color: #{color('warning', 'alert')};
color: hsl(0deg 0% 0%);
}
&--info {
--calendar-event-color: #{color('info', 'alert')};
}
}
@include breakpoint-down('sm') {
&__weekdays {
display: none;
}
&__days {
grid-template-columns: 1fr;
}
&__day {
align-items: flex-start;
flex-direction: row;
gap: spacer('s');
min-block-size: 0;
padding: spacer('xs') spacer('m');
&:not([data-has-events], .calendar__day--today) {
display: none;
}
}
&__events {
flex-grow: 1;
gap: spacer('xxs');
}
&__event {
font-size: config('font-size-sm', $typography);
padding: spacer('xxs') spacer('xs');
white-space: normal;
}
}
}
[dir='rtl'] {
.calendar__title {
margin: 0 0 0 auto;
}
.calendar__chevron {
scale: -1 1;
}
}
<section class="calendar" aria-labelledby="calendar-title">
<header class="calendar__header">
<h3 class="calendar__title" id="calendar-title"><time datetime="2026-10">October 2026</time></h3>
<nav class="calendar__navigation" aria-label="Months">
<a class="btn btn--outline-secondary btn--sm btn--icon" href="?month=2026-09">
<svg class="btn__icon calendar__chevron" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 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"/></svg>
<span class="sr-only">Previous month</span>
</a>
<a class="btn btn--outline-secondary btn--sm" href="?month=2026-10">Today</a>
<a class="btn btn--outline-secondary btn--sm btn--icon" href="?month=2026-11">
<svg class="btn__icon calendar__chevron" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 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"/></svg>
<span class="sr-only">Next month</span>
</a>
</nav>
<a class="btn btn--primary btn--sm" href="#">New event</a>
</header>
<div class="calendar__weekdays" aria-hidden="true">
<span>Mon</span><span>Tue</span><span>Wed</span><span>Thu</span><span>Fri</span><span>Sat</span><span>Sun</span>
</div>
<ol class="calendar__days" role="list">
<li class="calendar__day calendar__day--outside">
<time class="calendar__date" datetime="2026-09-28"><span class="sr-only">Monday, September </span>28</time>
</li>
<li class="calendar__day calendar__day--outside">
<time class="calendar__date" datetime="2026-09-29"><span class="sr-only">Tuesday, September </span>29</time>
</li>
<li class="calendar__day calendar__day--outside">
<time class="calendar__date" datetime="2026-09-30"><span class="sr-only">Wednesday, September </span>30</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-01"><span class="sr-only">Thursday, October </span>1</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-01T14:00">2 PM</time> Q4 planning</a></li>
</ul>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-02"><span class="sr-only">Friday, October </span>2</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--success calendar__event--all-day" href="#"><span class="sr-only">All day: </span>Payroll</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-03"><span class="sr-only">Saturday, October </span>3</time>
</li>
<li class="calendar__day calendar__day--today" data-has-events>
<time class="calendar__date" datetime="2026-10-04" aria-current="date"><span class="sr-only">Sunday, October </span>4<span class="sr-only">, today</span></time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-04T10:00">10 AM</time> Product photo shoot</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-05"><span class="sr-only">Monday, October </span>5</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-06"><span class="sr-only">Tuesday, October </span>6</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-06T09:30">9:30 AM</time> Sprint review</a></li>
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-06T15:00">3 PM</time> 1:1 with Ben</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-07"><span class="sr-only">Wednesday, October </span>7</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-08"><span class="sr-only">Thursday, October </span>8</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-09"><span class="sr-only">Friday, October </span>9</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--warning calendar__event--all-day" href="#"><span class="sr-only">All day: </span>Black Friday prep</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-10"><span class="sr-only">Saturday, October </span>10</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-11"><span class="sr-only">Sunday, October </span>11</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-12"><span class="sr-only">Monday, October </span>12</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-13"><span class="sr-only">Tuesday, October </span>13</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-13T11:00">11 AM</time> Supplier call</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-14"><span class="sr-only">Wednesday, October </span>14</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-15"><span class="sr-only">Thursday, October </span>15</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--info calendar__event--all-day" href="#"><span class="sr-only">All day: </span>Newsletter goes out</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-16"><span class="sr-only">Friday, October </span>16</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-17"><span class="sr-only">Saturday, October </span>17</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-18"><span class="sr-only">Sunday, October </span>18</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-19"><span class="sr-only">Monday, October </span>19</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-20"><span class="sr-only">Tuesday, October </span>20</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-20T10:00">10 AM</time> Sprint review</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-21"><span class="sr-only">Wednesday, October </span>21</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-22"><span class="sr-only">Thursday, October </span>22</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--warning calendar__event--all-day" href="#"><span class="sr-only">All day: </span>Inventory count</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-23"><span class="sr-only">Friday, October </span>23</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-24"><span class="sr-only">Saturday, October </span>24</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-25"><span class="sr-only">Sunday, October </span>25</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-26"><span class="sr-only">Monday, October </span>26</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-27"><span class="sr-only">Tuesday, October </span>27</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-27T13:00">1 PM</time> Marketing sync</a></li>
<li><a class="calendar__event calendar__event--primary" href="#"><time datetime="2026-10-27T16:00">4 PM</time> Interview: designer</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-28"><span class="sr-only">Wednesday, October </span>28</time>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-29"><span class="sr-only">Thursday, October </span>29</time>
</li>
<li class="calendar__day" data-has-events>
<time class="calendar__date" datetime="2026-10-30"><span class="sr-only">Friday, October </span>30</time>
<ul class="calendar__events" role="list">
<li><a class="calendar__event calendar__event--success calendar__event--all-day" href="#"><span class="sr-only">All day: </span>Month-end close</a></li>
</ul>
</li>
<li class="calendar__day">
<time class="calendar__date" datetime="2026-10-31"><span class="sr-only">Saturday, October </span>31</time>
</li>
<li class="calendar__day calendar__day--outside">
<time class="calendar__date" datetime="2026-11-01"><span class="sr-only">Sunday, November </span>1</time>
</li>
</ol>
</section>