source: Klonkt/src/themes/sidebar/layout.css@ 495b019

Last change on this file since 495b019 was 495b019, checked in by Bart <bart@…>, 3 days ago

Lay-outthema's: een pakket, de beheerder kiest, en de zijbalk als eerste

Een lay-out is nu een pakket: een map in src/themes/ met een theme.json (id,
naam, versie, contract, stylesheet) en de stylesheet zelf. De zijbalk is het
eerste ingebouwde thema; een thema van buiten installeren komt later en gaat
door dezelfde lader, zodat er één vorm is.

Dezelfde markup, een ander stelsel: een thema verandert geen template. Het
contract (1) is de afspraak over de ids en klassen waar het op mag bouwen; een
thema op een ander contract valt terug op de gewone kop in plaats van half te
werken. Elke regel staat onder html[data-layout="<id>"], en een toets bewaakt
dat, zodat een thema niets raakt zolang het niet gekozen is.

WIE KIEST: de beheerder, in het sitebeheer (sites.layout). Een bezoeker niet
-- de server zet data-layout zelf, het bezoekersscript met localStorage is
weg, en ?layout= werkt alleen als voorproefje voor wie de site beheert. Het
beheer houdt altijd de gewone kop, ook bij navigeren via htmx (de lay-out reist
mee in pcmsNav): een kapot thema mag je nooit buitensluiten van de instelling
waarmee je het uitzet.

Geserveerd op /themes/<id>/<versie>/<bestand>, met de versie in het pad als
cache-buster; alleen wat het pakket zelf noemt komt eruit. De actor noemt het
gekozen thema als shaer:theme, zodat Shaer het van zijn eigen site kan halen
in plaats van er zelf een te kiezen.

Co-Authored-By: Claude Opus 5.5 <claude@…>

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Lay-out "zijbalk" -- het eerste ingebouwde thema (experimental/theme, op weg
3 * naar 2.0). Een thema is een pakket: theme.json ernaast, dit bestand erin.
4 *
5 * DEZELFDE MARKUP, EEN ANDER STELSEL. Dit thema verandert geen template; het
6 * ordent wat er al staat. Dat is het contract (`"contract": 1` in theme.json):
7 * de ids en klassen waar de JS en de custom_css van beheerders op leunen,
8 * blijven waar ze zijn, en een thema mag alleen daarop bouwen.
9 *
10 * ELKE REGEL ONDER html[data-layout="sidebar"]. De shell zet dat attribuut
11 * alleen als dit het gekozen thema is, dus zolang hij niet gekozen is raakt
12 * dit bestand niets. Voor ingebouwde thema's staat die afbakening er met de
13 * hand; een thema van buiten krijgt hem straks bij installatie opgelegd.
14 *
15 * WIE KIEST: de beheerder van de site, in het beheer. Een bezoeker niet.
16 *
17 * ALLEEN OP EEN BREED SCHERM. Onder de 1024px blijft alles zoals het was: daar
18 * is de onderste tabbalk de navigatie, en een zijbalk zou de inhoud opeten.
19 */
20@media (min-width: 1024px) {
21
22 html[data-layout="sidebar"] { --sidebar-w: 15rem; }
23
24 /* Alleen ruimte maken als er ook een zijbalk IS. De hub-landing en de
25 in- en uitlogschermen hebben geen kop; die houden de volle breedte. */
26 html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) {
27 padding-left: var(--sidebar-w);
28 }
29
30 /* ── De chrome wordt de zijbalk ─────────────────────────────── */
31 /* Niet de masthead maar het hele #pcms-chrome-slot: daar zitten de
32 masthead, de identiteit van de site (profile-header) en de Lezen/Grid-
33 wissel al samen in, en het slot wordt bij elke htmx-navigatie als
34 geheel ververst. Zo blijft alles bij elkaar dat bij de site hoort, en
35 bepaalt `order` de volgorde -- zonder dat er een regel markup verschuift. */
36 html[data-layout="sidebar"] #pcms-chrome:has(.masthead) {
37 position: fixed;
38 top: 0; bottom: 0; left: 0;
39 width: var(--sidebar-w);
40 display: flex;
41 flex-direction: column;
42 padding-top: var(--ios-safe-top, 0px);
43 border-right: 1px solid var(--rule);
44 background: var(--paper);
45 z-index: 30;
46 /* GEEN overflow hier: de taal- en gebruikersmenu's klappen naar rechts
47 uit de balk, en een scrollende balk zou ze afknippen. */
48 }
49
50 /* ── 1. Bovenaan: wie dit is ─────────────────────────────────── */
51 /* De specificiteit is opzet: de compacte stand op post-, zoek- en
52 archiefpagina's (foto 40px, geen bio) bestaat om ruimte boven de inhoud
53 te sparen. In een kolom is die ruimte er wel, en een identiteit die per
54 pagina van maat verspringt leest als een andere site. */
55 html[data-layout="sidebar"] #pcms-chrome .profile-header {
56 order: -2;
57 padding: 1.75rem 0 1.25rem;
58 border-bottom: 1px solid var(--rule);
59 background: transparent;
60 }
61 html[data-layout="sidebar"] #pcms-chrome .profile-header-inner {
62 max-width: none;
63 margin: 0;
64 padding: 0 1.6rem;
65 flex-direction: column;
66 align-items: flex-start;
67 gap: .85rem;
68 }
69 html[data-layout="sidebar"] #pcms-chrome .profile-photo {
70 width: 72px;
71 height: 72px;
72 border-width: 2px;
73 }
74 html[data-layout="sidebar"] #pcms-chrome .profile-photo-fallback { font-size: 1.75rem; }
75 html[data-layout="sidebar"] #pcms-chrome .profile-name {
76 font-size: 1.4rem;
77 margin: 0 0 .3rem;
78 overflow-wrap: anywhere;
79 }
80 html[data-layout="sidebar"] #pcms-chrome .profile-bio {
81 display: block;
82 font-size: .85rem;
83 }
84 html[data-layout="sidebar"] #pcms-chrome .profile-links { flex-wrap: wrap; }
85
86 /* ── 2. Hoe je de site leest ─────────────────────────────────── */
87 /* De Lezen/Grid-wissel zit in hetzelfde slot, dus hij komt mee: onder de
88 identiteit, als keuze die bij de site hoort in plaats van boven de stroom. */
89 html[data-layout="sidebar"] #pcms-chrome .view-switcher-wrap {
90 order: -1;
91 margin: 0;
92 padding: .9rem 0;
93 border-bottom: 1px solid var(--rule);
94 background: transparent;
95 }
96 html[data-layout="sidebar"] #pcms-chrome .view-switcher-wrap .container {
97 max-width: none;
98 padding-inline: 1.6rem;
99 justify-content: flex-start;
100 }
101
102 /* ── 3. De navigatie vult de rest ────────────────────────────── */
103 html[data-layout="sidebar"] #pcms-chrome .masthead {
104 position: static;
105 flex: 1 1 auto;
106 display: flex;
107 flex-direction: column;
108 padding: 1rem 0 1.25rem;
109 border: 0;
110 background: transparent;
111 }
112
113 html[data-layout="sidebar"] .masthead-inner {
114 flex: 1 1 auto;
115 max-width: none;
116 margin: 0;
117 padding-inline: .75rem;
118 flex-direction: column;
119 align-items: stretch;
120 justify-content: flex-start;
121 gap: 1rem;
122 }
123
124 /* Het merk is overal verborgen (de profielkop draagt het), en dan is het
125 een leeg vak met een gat eronder. Behalve op beheerpagina's: daar staat
126 "terug naar de site", en dat is daar de enige weg terug. */
127 html[data-layout="sidebar"] .masthead-brand:not(:has(.nav-link-admin)) {
128 display: none;
129 }
130 html[data-layout="sidebar"] .masthead-brand {
131 flex: 0 0 auto;
132 overflow: visible;
133 }
134 html[data-layout="sidebar"] .masthead-brand .nav-link-admin {
135 width: 100%;
136 }
137
138 /* ── De navigatie staat onder elkaar ──────────────────────────── */
139 html[data-layout="sidebar"] .top-nav-desktop {
140 flex: 1 1 auto;
141 flex-direction: column;
142 align-items: stretch;
143 gap: .15rem;
144 }
145
146 html[data-layout="sidebar"] .top-nav-desktop > .nav-link,
147 html[data-layout="sidebar"] .top-nav-desktop > .nav-btn,
148 html[data-layout="sidebar"] .top-nav-desktop > details > summary {
149 width: 100%;
150 justify-content: flex-start;
151 padding: .55rem .85rem;
152 }
153 html[data-layout="sidebar"] .top-nav-desktop .nav-label { display: inline; }
154
155 /* Knoppen die in de kop alleen een pictogram zijn, krijgen hier hun naam.
156 De naam stond al in de markup, als title of aria-label; er is niets bij
157 gekomen. In een kolom onder elkaar leest een rij losse pictogrammen als
158 een raadsel. */
159 html[data-layout="sidebar"] .top-nav-desktop > .nav-btn[title]::after,
160 html[data-layout="sidebar"] .top-nav-desktop .lang-toggle[title]::after {
161 content: attr(title);
162 }
163 html[data-layout="sidebar"] .top-nav-desktop .user-toggle[aria-label]::after {
164 content: attr(aria-label);
165 }
166 /* Het pijltje hoort bij een menu dat naar beneden valt; hier klapt hij
167 opzij, en tussen de taalcode en de naam las het als "EN ⌄ Language". */
168 html[data-layout="sidebar"] .top-nav-desktop .lang-caret { display: none; }
169
170 /* Bovenin wat je zoekt (archief, zoeken); onderin wat bij JOU hoort
171 (thema, taal, meldingen, je account). Het thema is de eerste van dat
172 tweede rijtje, dus die duwt de rest naar beneden. */
173 html[data-layout="sidebar"] .top-nav-desktop > #theme-toggle {
174 margin-top: auto;
175 }
176
177 /* ── De uitklapmenu's klappen naar rechts open ───────────────── */
178 /* In de kop vielen ze naar beneden, rechts uitgelijnd. Onderin een smalle
179 balk zou dat buiten beeld vallen, dus: naast de knop, naar boven toe. */
180 html[data-layout="sidebar"] .user-dropdown,
181 html[data-layout="sidebar"] .lang-dropdown {
182 top: auto;
183 right: auto;
184 bottom: 0;
185 left: calc(100% + .6rem);
186 transform-origin: bottom left;
187 }
188 html[data-layout="sidebar"] .user-menu,
189 html[data-layout="sidebar"] .lang-menu {
190 position: relative;
191 }
192
193 /* ── Wat over de volle breedte vastzat, begint nu na de balk ──── */
194 html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) .audio-player,
195 html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) .audio-sheet {
196 left: var(--sidebar-w);
197 }
198}
Note: See TracBrowser for help on using the repository browser.