Skip to main content

max / goingson

Fold backup frequency and retention behind a Customize disclosure Automatic backups now read as one on/off choice. The two selects stay in the DOM (saveBackupSettings reads them by id), and the disclosure starts open when either value is already off-default so a customized setting is never hidden.
Author: Max Johnson <me@maxj.phd> · 2026-07-26 20:50 UTC
Signed with PGP, not checked
Commit: 840f2b302f0d1dee7043db9cef77f1a971526724
Parent: e3f53de
2 files changed, +71 insertions, -25 deletions
@@ -2288,6 +2288,37 @@
2288 2288 padding-top: var(--space-4);
2289 2289 border-top: var(--border-width-sm) solid var(--border);
2290 2290 }
2291 + /* Secondary settings folded behind a link-style summary, so a section reads as
2292 + one choice until someone asks for the rest. */
2293 + .settings-disclosure {
2294 + margin-bottom: var(--space-4);
2295 + }
2296 + .settings-disclosure-toggle {
2297 + display: inline-flex;
2298 + align-items: center;
2299 + gap: var(--space-2);
2300 + cursor: pointer;
2301 + font-size: var(--font-size-sm);
2302 + color: var(--content-secondary);
2303 + list-style: none;
2304 + }
2305 + .settings-disclosure-toggle::-webkit-details-marker {
2306 + display: none;
2307 + }
2308 + .settings-disclosure-toggle::before {
2309 + content: '▶';
2310 + font-size: 0.7rem;
2311 + transition: transform 0.15s ease;
2312 + }
2313 + .settings-disclosure[open] > .settings-disclosure-toggle::before {
2314 + transform: rotate(90deg);
2315 + }
2316 + .settings-disclosure-toggle:hover {
2317 + color: var(--content);
2318 + }
2319 + .settings-disclosure[open] > .settings-disclosure-toggle {
2320 + margin-bottom: var(--space-3);
2321 + }
2291 2322 .form-hint--spaced {
2292 2323 margin-top: var(--space-2);
2293 2324 }
@@ -10,6 +10,11 @@
10 10
11 11 let currentSection = 'appearance';
12 12
13 + // Mirror of NewBackupSettings in src-tauri/src/backup_scheduler.rs; used only
14 + // to decide whether the backup "Customize" disclosure starts open.
15 + const DEFAULT_BACKUP_FREQUENCY_MINUTES = 15;
16 + const DEFAULT_BACKUPS_TO_KEEP = 10;
17 +
13 18 // Settings Page
14 19
15 20 /**
@@ -221,6 +226,13 @@
221 226 ];
222 227
223 228 const renderFormField = GoingsOn.ui.renderFormField;
229 + // Frequency and retention sit behind a disclosure: the defaults are
230 + // right for almost everyone, so the section reads as one on/off
231 + // choice until someone asks for more. Open it when the settings are
232 + // already customized, so a non-default value is never hidden.
233 + const customized =
234 + settings.backupFrequencyMinutes !== DEFAULT_BACKUP_FREQUENCY_MINUTES
235 + || settings.maxBackupsToKeep !== DEFAULT_BACKUPS_TO_KEEP;
224 236 backupHtml = `
225 237 <div class="settings-section-block">
226 238 <h4 class="settings-subheading">Backups</h4>
@@ -240,31 +252,34 @@
240 252 <span>Enable automatic backups</span>
241 253 </label>
242 254 </div>
243 - ${renderFormField({
244 - kind: 'select',
245 - name: 'backup-frequency',
246 - id: 'backup-frequency',
247 - label: 'Backup Frequency',
248 - value: settings.backupFrequencyMinutes,
249 - options: frequencyOptions.map(o => ({
250 - value: String(o.value),
251 - label: o.label,
252 - selected: settings.backupFrequencyMinutes === o.value,
253 - })),
254 - })}
255 - ${renderFormField({
256 - kind: 'select',
257 - name: 'backup-retention',
258 - id: 'backup-retention',
259 - label: 'Retention Policy',
260 - value: settings.maxBackupsToKeep,
261 - options: retentionOptions.map(o => ({
262 - value: String(o.value),
263 - label: o.label,
264 - selected: settings.maxBackupsToKeep === o.value,
265 - })),
266 - hint: 'Older backups are automatically deleted to save space.',
267 - })}
255 + <details class="settings-disclosure"${customized ? ' open' : ''}>
256 + <summary class="settings-disclosure-toggle">Customize</summary>
257 + ${renderFormField({
258 + kind: 'select',
259 + name: 'backup-frequency',
260 + id: 'backup-frequency',
261 + label: 'Backup Frequency',
262 + value: settings.backupFrequencyMinutes,
263 + options: frequencyOptions.map(o => ({
264 + value: String(o.value),
265 + label: o.label,
266 + selected: settings.backupFrequencyMinutes === o.value,
267 + })),
268 + })}
269 + ${renderFormField({
270 + kind: 'select',
271 + name: 'backup-retention',
272 + id: 'backup-retention',
273 + label: 'Retention Policy',
274 + value: settings.maxBackupsToKeep,
275 + options: retentionOptions.map(o => ({
276 + value: String(o.value),
277 + label: o.label,
278 + selected: settings.maxBackupsToKeep === o.value,
279 + })),
280 + hint: 'Older backups are automatically deleted to save space.',
281 + })}
282 + </details>
268 283 <div class="settings-actions-row settings-actions-row--center">
269 284 <button class="btn btn-primary" data-act="export.saveBackupSettings">Save Backup Settings</button>
270 285 <span class="settings-status-text">${esc(lastBackupText)}</span>