fix(ui): portal tooltips, opaque glass, settings rail+stable height, notif test, channel help
- Tooltip: render in a portal with fixed positioning + edge-flip so hints are never clipped by overflow/stacking ancestors (fixes mispositioned/hidden bubbles app-wide). - Glass: raise opacity so overlay menus/panels stay readable over content. - SettingsPanel: vertical tab rail (no wrapping/jumping), content grid-stacked so the panel sizes to the tallest tab (stable height) and floats to its content height. - Notifications: the test toast is now a normal auto-dismissing toast (with countdown bar) that also plays the sound via a new force-sound flag. - Channel manager: explain priority/tags/hide and what 'Sync subscriptions' does; add a 'Channel priority' feed sort so priority is actually meaningful.
This commit is contained in:
parent
f8d2a11226
commit
91fd008519
7 changed files with 160 additions and 79 deletions
|
|
@ -108,19 +108,34 @@ export default function Channels({
|
|||
className="w-full bg-card border border-border rounded-full pl-9 pr-4 py-2 text-sm outline-none focus:border-accent"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => syncSubs.mutate()}
|
||||
disabled={syncSubs.isPending}
|
||||
className="flex items-center gap-2 px-3 py-2 rounded-lg border border-border text-sm hover:border-accent disabled:opacity-50 transition"
|
||||
<Tooltip
|
||||
side="bottom"
|
||||
hint="Re-import your subscription list from YouTube — adds channels you've newly followed and drops ones you've unfollowed. The videos themselves keep syncing automatically in the background; this does not re-fetch them."
|
||||
>
|
||||
<RefreshCw className={`w-4 h-4 ${syncSubs.isPending ? "animate-spin" : ""}`} />
|
||||
Sync subscriptions
|
||||
</button>
|
||||
<button
|
||||
onClick={() => syncSubs.mutate()}
|
||||
disabled={syncSubs.isPending}
|
||||
className="glass-card glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-sm disabled:opacity-50 transition"
|
||||
>
|
||||
<RefreshCw className={`w-4 h-4 ${syncSubs.isPending ? "animate-spin" : ""}`} />
|
||||
Sync subscriptions
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-muted mb-4 leading-relaxed">
|
||||
Set a channel's <b className="text-fg/80">priority</b> to push its videos up when you sort
|
||||
by “Channel priority”, attach your own <b className="text-fg/80">tags</b> to filter the feed,
|
||||
or <b className="text-fg/80">hide</b> a channel to drop it from the feed without unsubscribing.
|
||||
</p>
|
||||
|
||||
{/* Your tags */}
|
||||
<div className="flex flex-wrap items-center gap-1.5 mb-4">
|
||||
<span className="text-xs uppercase tracking-wide text-muted mr-1">Your tags</span>
|
||||
<Tooltip hint="Your personal labels. Attach them to channels below, then filter the feed by tag from the sidebar. (Separate from the automatic language/topic tags.)">
|
||||
<span className="text-xs uppercase tracking-wide text-muted mr-1 cursor-help underline decoration-dotted decoration-muted/40 underline-offset-4">
|
||||
Your tags
|
||||
</span>
|
||||
</Tooltip>
|
||||
{userTags.map((t) => (
|
||||
<span
|
||||
key={t.id}
|
||||
|
|
@ -232,15 +247,17 @@ function ChannelRow({
|
|||
c.hidden ? "opacity-60" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-col items-center">
|
||||
<button onClick={() => onPriority(1)} className="text-muted hover:text-accent" title="Raise priority">
|
||||
<ArrowUp className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<span className="text-xs text-muted tabular-nums">{c.priority}</span>
|
||||
<button onClick={() => onPriority(-1)} className="text-muted hover:text-accent" title="Lower priority">
|
||||
<ArrowDown className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<Tooltip hint="Your ranking for this channel. Sort the feed by “Channel priority” to bring higher-priority channels to the top.">
|
||||
<div className="flex flex-col items-center cursor-help">
|
||||
<button onClick={() => onPriority(1)} className="text-muted hover:text-accent" aria-label="Raise priority">
|
||||
<ArrowUp className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<span className="text-xs text-muted tabular-nums">{c.priority}</span>
|
||||
<button onClick={() => onPriority(-1)} className="text-muted hover:text-accent" aria-label="Lower priority">
|
||||
<ArrowDown className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
{c.thumbnail_url ? (
|
||||
<img src={c.thumbnail_url} alt="" className="w-10 h-10 rounded-full shrink-0" />
|
||||
|
|
@ -286,9 +303,17 @@ function ChannelRow({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button onClick={onHide} className="text-muted hover:text-fg shrink-0" title={c.hidden ? "Unhide" : "Hide from feed"}>
|
||||
{c.hidden ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
|
||||
</button>
|
||||
<Tooltip
|
||||
hint={
|
||||
c.hidden
|
||||
? "Hidden — this channel's videos are kept out of your feed. Click to show them again."
|
||||
: "Hide this channel's videos from your feed. It stays subscribed; this doesn't unsubscribe on YouTube."
|
||||
}
|
||||
>
|
||||
<button onClick={onHide} className="text-muted hover:text-fg shrink-0" aria-label={c.hidden ? "Unhide" : "Hide from feed"}>
|
||||
{c.hidden ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue