feat(web): settings helptext behind a "?" popup instead of inline paragraphs
The Qobuz/Monitor/Discovery help I just added was always-visible and verbose. Replace each with a compact "?" button (new reusable HelpButton) that opens the same content in a popup (reuses the Modal), keeping the settings tabs clean. web tsc + build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { Modal } from "./modal";
|
||||
|
||||
/** A small "?" affordance that opens its help content in a popup, keeping settings pages
|
||||
* uncluttered. */
|
||||
export function HelpButton({ title, children }: { title: string; children: ReactNode }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className="help-btn"
|
||||
aria-label={`Help: ${title}`}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
?
|
||||
</button>
|
||||
<Modal open={open} onClose={() => setOpen(false)} title={title}>
|
||||
<div className="help-body">{children}</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
+11
-1
@@ -259,7 +259,7 @@ nav.contents .sep { flex: 1; }
|
||||
.field.wide { grid-column: 1 / -1; }
|
||||
.subhead {
|
||||
font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
|
||||
color: var(--graphite); margin: 26px 0 2px;
|
||||
color: var(--graphite); margin: 26px 0 2px; display: flex; align-items: center; gap: 10px;
|
||||
}
|
||||
.field .set { color: var(--accent); }
|
||||
.info-panel {
|
||||
@@ -276,6 +276,16 @@ nav.contents .sep { flex: 1; }
|
||||
.help { font-size: 0.8rem; color: var(--graphite); line-height: 1.5; margin: 4px 0 14px; max-width: 62ch; }
|
||||
.help b { color: var(--ink); font-weight: 600; }
|
||||
.help code { font-family: var(--mono); font-size: 0.85em; }
|
||||
/* compact "?" trigger that opens help in a popup */
|
||||
.help-btn {
|
||||
font-family: var(--mono); font-size: 0.72rem; line-height: 1; width: 20px; height: 20px;
|
||||
border: 1.5px solid var(--rule-2); border-radius: 50%; background: transparent; color: var(--graphite);
|
||||
cursor: pointer; display: inline-flex; align-items: center; justify-content: center; padding: 0;
|
||||
}
|
||||
.help-btn:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.help-body { font-size: 0.9rem; color: var(--ink); line-height: 1.6; }
|
||||
.help-body b { font-weight: 600; }
|
||||
.help-body code { font-family: var(--mono); font-size: 0.85em; }
|
||||
.info-panel + .info-panel { margin-top: 14px; }
|
||||
|
||||
/* ── Modal ────────────────────────────────────────────── */
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { PageHead } from "../_ui/page-head";
|
||||
import { HelpButton } from "../_ui/help-button";
|
||||
|
||||
type Loaded = {
|
||||
qobuzEmail: string;
|
||||
@@ -192,12 +193,14 @@ export function SettingsForm() {
|
||||
|
||||
{tab === "Qobuz" ? (
|
||||
<form className="settings-section" onSubmit={saveCredentials}>
|
||||
<p className="help">
|
||||
<div className="subhead">
|
||||
Auth token
|
||||
<HelpButton title="Qobuz authentication">
|
||||
Lyra signs in to Qobuz with a <b>user ID + auth token</b> — the download engine
|
||||
treats these as more reliable than email/password, which Qobuz often rejects. Find
|
||||
them in your logged-in Qobuz web session (bundle/app secret + user auth token).
|
||||
</p>
|
||||
<div className="subhead">Auth token</div>
|
||||
</HelpButton>
|
||||
</div>
|
||||
<div className="field-grid">
|
||||
<label className="field">
|
||||
<span>Qobuz user ID</span>
|
||||
@@ -339,20 +342,22 @@ export function SettingsForm() {
|
||||
/>
|
||||
Automatic monitoring (grab & upgrade)
|
||||
</label>
|
||||
</div>
|
||||
<p className="help">
|
||||
<HelpButton title="Monitoring">
|
||||
When on, the worker periodically checks your followed artists: it <b>grabs new
|
||||
releases</b> as they appear and <b>upgrades</b> owned albums that fall below the
|
||||
quality cutoff.
|
||||
<br />
|
||||
<br />
|
||||
<b>Quality cutoff</b> — the minimum acceptable quality class: <code>1</code> = lossy,{" "}
|
||||
<code>2</code> = CD-lossless (FLAC 16/44.1), <code>3</code> = hi-res. An owned album is
|
||||
kept as-is when it’s ≥ the cutoff; otherwise a better copy is chased. Range 1–3.
|
||||
<br />
|
||||
<br />
|
||||
<b>Poll interval</b> — hours between new-release checks. <b>Retry interval</b> — hours
|
||||
before re-attempting a release that couldn’t be found yet. <b>Upgrade window</b> — how
|
||||
many days after first acquiring an album to keep looking for a better copy.
|
||||
</p>
|
||||
</HelpButton>
|
||||
</div>
|
||||
<div className="field-grid">
|
||||
{MONITOR_FIELDS.map(([key, label]) => (
|
||||
<label key={key} className="field">
|
||||
@@ -379,18 +384,19 @@ export function SettingsForm() {
|
||||
/>
|
||||
Scheduled discovery sweep
|
||||
</label>
|
||||
</div>
|
||||
<p className="help">
|
||||
<HelpButton title="Discovery">
|
||||
When on, the worker periodically sweeps your followed artists for similar artists +
|
||||
their new releases (via ListenBrainz and, if configured, Last.fm) and lists them on{" "}
|
||||
<b>Discover</b>. Nothing is downloaded automatically — you Follow/Want from there.
|
||||
<br />
|
||||
<br />
|
||||
<b>Interval</b> — hours between sweeps. <b>Seeds per chunk</b> — how many followed
|
||||
artists are processed per worker cycle (keeps job-claiming responsive on big rosters).
|
||||
<b> Similar per seed</b> — candidates pulled per artist. <b>Albums per artist</b> —
|
||||
releases surfaced per suggested artist. <b>Min score</b> — drops weak suggestions.{" "}
|
||||
<b>ListenBrainz base URL</b> — leave blank for the default endpoint.
|
||||
</p>
|
||||
</HelpButton>
|
||||
</div>
|
||||
<div className="field-grid">
|
||||
{DISCOVERY_FIELDS.map(([key, label]) => (
|
||||
<label key={key} className="field">
|
||||
|
||||
Reference in New Issue
Block a user