WIP: February 2026 event improvements and calendar refactor #1

Draft
andrew wants to merge 10 commits from feb-2026-event-improvements into master
5 changed files with 68 additions and 24 deletions
Showing only changes of commit 7a2b0e44ad - Show all commits

View File

@ -47,6 +47,7 @@ return [
'title' => 'Calendar settings', 'title' => 'Calendar settings',
], ],
'timezone_help' => 'You can override your default time zone here.', 'timezone_help' => 'You can override your default time zone here.',
'toggle_sidebar' => 'Toggle calendar sidebar',
'event' => [ 'event' => [
'when' => 'When', 'when' => 'When',
'all_day' => 'All day', 'all_day' => 'All day',

View File

@ -47,6 +47,7 @@ return [
'title' => 'Impostazioni calendario', 'title' => 'Impostazioni calendario',
], ],
'timezone_help' => 'Puoi sovrascrivere il tuo fuso orario predefinito qui.', 'timezone_help' => 'Puoi sovrascrivere il tuo fuso orario predefinito qui.',
'toggle_sidebar' => 'Mostra o nascondi la barra laterale del calendario',
'event' => [ 'event' => [
'when' => 'Quando', 'when' => 'Quando',
'all_day' => 'Tutto il giorno', 'all_day' => 'Tutto il giorno',

View File

@ -245,7 +245,18 @@ main {
/* section specific */ /* section specific */
&#calendar { &#calendar {
/* */ header {
h2 {
.calendar-expand-toggle {
@apply ml-1 opacity-0 pointer-events-none transition-opacity duration-150;
}
&:hover .calendar-expand-toggle,
&:focus-within .calendar-expand-toggle {
@apply opacity-100 pointer-events-auto;
}
}
}
} }
&#settings { &#settings {
/* */ /* */

View File

@ -1,6 +1,16 @@
import './bootstrap'; import './bootstrap';
import htmx from 'htmx.org'; import htmx from 'htmx.org';
const SELECTORS = {
calendarToggle: '.calendar-toggle',
calendarViewForm: '#calendar-view',
calendarExpandToggle: '[data-calendar-expand]',
colorPicker: '[data-colorpicker]',
colorPickerColor: '[data-colorpicker-color]',
colorPickerHex: '[data-colorpicker-hex]',
colorPickerRandom: '[data-colorpicker-random]',
};
/** /**
* htmx/global * htmx/global
*/ */
@ -19,34 +29,43 @@ document.addEventListener('htmx:configRequest', (evt) => {
}) })
/** /**
* calendar toggle * calendar ui
* progressive enhancement on html form with no js * progressive enhancement on html form with no js
*/ */
document.addEventListener('change', event => { document.addEventListener('change', (event) => {
const checkbox = event.target; const target = event.target;
// ignore anything that isnt one of our checkboxes if (target?.matches(SELECTORS.calendarToggle)) {
if (!checkbox.matches('.calendar-toggle')) return; const slug = target.value;
const show = target.checked;
const slug = checkbox.value; document
const show = checkbox.checked; .querySelectorAll(`[data-calendar="${slug}"]`)
.forEach(el => el.classList.toggle('hidden', !show));
return;
}
// toggle .hidden on every matching event element const form = target?.form;
document if (!form || form.id !== 'calendar-view') return;
.querySelectorAll(`[data-calendar="${slug}"]`) if (target.name !== 'view') return;
.forEach(el => el.classList.toggle('hidden', !show));
form.requestSubmit();
}); });
/** /**
* calendar view picker * calendar sidebar expand toggle
* progressive enhancement on html form with no js
*/ */
document.addEventListener('change', (e) => { document.addEventListener('click', (event) => {
const form = e.target?.form; const toggle = event.target.closest(SELECTORS.calendarExpandToggle);
if (!form || form.id !== 'calendar-view') return; if (!toggle) return;
if (e.target.name !== 'view') return;
form.requestSubmit(); event.preventDefault();
const main = toggle.closest('main');
if (!main) return;
const isExpanded = main.classList.toggle('expanded');
toggle.setAttribute('aria-pressed', isExpanded ? 'true' : 'false');
}); });
/** /**
@ -71,9 +90,9 @@ function initColorPickers(root = document) {
if (el.__colorpickerWired) return; if (el.__colorpickerWired) return;
el.__colorpickerWired = true; el.__colorpickerWired = true;
const color = el.querySelector('[data-colorpicker-color]'); const color = el.querySelector(SELECTORS.colorPickerColor);
const hex = el.querySelector('[data-colorpicker-hex]'); const hex = el.querySelector(SELECTORS.colorPickerHex);
const btn = el.querySelector('[data-colorpicker-random]'); const btn = el.querySelector(SELECTORS.colorPickerRandom);
if (!color || !hex) return; if (!color || !hex) return;
@ -137,11 +156,15 @@ function initColorPickers(root = document) {
} }
}; };
root.querySelectorAll('[data-colorpicker]').forEach(wire); root.querySelectorAll(SELECTORS.colorPicker).forEach(wire);
}
function initUI() {
initColorPickers();
} }
// initial bind // initial bind
document.addEventListener('DOMContentLoaded', () => initColorPickers()); document.addEventListener('DOMContentLoaded', initUI);
// rebind in htmx for swapped content // rebind in htmx for swapped content
document.addEventListener('htmx:afterSwap', (e) => { document.addEventListener('htmx:afterSwap', (e) => {

View File

@ -85,6 +85,14 @@
@if(!empty($header['span'])) @if(!empty($header['span']))
<span>{{ $header['span'] }}</span> <span>{{ $header['span'] }}</span>
@endif @endif
<button
type="button"
class="button button--icon button--sm calendar-expand-toggle"
data-calendar-expand
aria-label="{{ __('calendar.toggle_sidebar') }}"
>
<x-icon-chevron-left />
</button>
</h2> </h2>
<menu> <menu>
<li> <li>