mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 13:16:16 -08:00
fix(sources): keep the page header in view; mark the active source's row
Local Greptile (two P2s) on the PR round, both regressions against master: - The redesigned Sources page scrolled as one, so the title, Clean up and Sort left the view in a long library (master kept a sticky header, and the UI guidelines say headers stay and lists scroll). The header now stays and only the list below it scrolls, which also keeps a row reached by keyboard from scrolling under the header. - Master marked the active playlist on the Sources page; the new row only tinted the current row in the compact (switcher) size. The active source's row is now tinted with the same --app-list-selected-* token on the page too; the switcher keeps its check. The design handoff called the header non-sticky and the current tint switcher-only; both followed master and the guidelines instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
13de38ebe5
commit
e3a4ea7259
5 files changed
+33
-26
No files matched your search
@@ -75,7 +75,7 @@ in `apps/web/src/m3-theme.scss`):
|
||||
- `--app-success-color` — done/watched status (episode watched toggle)
|
||||
- `--app-list-selected-bg` / `--app-list-selected-fg` /
|
||||
`--app-list-selected-outline` — the chosen row of a side list and the
|
||||
switcher's current row (see Selection Pattern)
|
||||
active source's row on Sources and in the switcher (see Selection Pattern)
|
||||
- `--app-line-strong` — popover and menu borders, a step above
|
||||
`--app-widget-header-border`
|
||||
- `--app-danger-text` / `--app-danger-surface` — a failing source's tag and
|
||||
@@ -183,7 +183,8 @@ Use this pattern for:
|
||||
Do not add extra badges, left rails, or second selection systems unless there is a strong reason.
|
||||
|
||||
Side lists styled with `_side-list.scss` (the Sources filters) and the
|
||||
playlist switcher's current row use the Settings navigation's variant
|
||||
active source's row (Sources page and playlist switcher) use the Settings
|
||||
navigation's variant
|
||||
instead, through `--app-list-selected-*`: a soft tint with no lift or glow,
|
||||
outlined in light theme. Its text is the heading colour in light theme (the
|
||||
selection blue on its own tint is 3.3:1) and the selection colour in dark.
|
||||
@@ -1354,8 +1355,9 @@ the source with Enter, and deletes and undoes a source keyboard-only.
|
||||
One `app-source-row` serves both lists: `size="regular"` on the Sources page
|
||||
(56px, 36px tile, hover actions Refresh, Edit and ⋯; a failing row keeps
|
||||
Retry in view; touch screens always show the actions) and `size="compact"`
|
||||
in the switcher (52px, 32px tile, ⋯ only; the current row is tinted with a
|
||||
check). The meta line is always type · channels · added · updated · URL, with
|
||||
in the switcher (52px, 32px tile, ⋯ only). In both the active source's row
|
||||
is tinted with the selected-row token; the switcher adds a check. The page
|
||||
header (title, Clean up, Sort) stays; only the list below it scrolls. The meta line is always type · channels · added · updated · URL, with
|
||||
empty parts left out; only M3U playlists store a channel count. The helpers
|
||||
in `@iptvnator/playlist/shared/util` (`source-display`, `source-format`,
|
||||
`source-list`) own that text, the filters and the counts.
|
||||
|
||||
@@ -65,18 +65,19 @@
|
||||
// option is the focus indicator.
|
||||
@include focus-ring.focus-ring-declarations($offset: -2px);
|
||||
}
|
||||
}
|
||||
|
||||
&.source-row--current {
|
||||
// The same selected-row look as the side lists: a soft tint, and an
|
||||
// outline in light theme. The dot's ring approximates the tint.
|
||||
--source-row-ring: color-mix(
|
||||
in srgb,
|
||||
var(--app-selection-color) 16%,
|
||||
var(--source-row-base)
|
||||
);
|
||||
background: var(--app-list-selected-bg);
|
||||
box-shadow: inset 0 0 0 1px var(--app-list-selected-outline);
|
||||
}
|
||||
// The active source, on the Sources page and in the switcher: the same
|
||||
// selected-row look as the side lists (a soft tint, and an outline in light
|
||||
// theme). The dot's ring approximates the tint.
|
||||
.source-row--current {
|
||||
--source-row-ring: color-mix(
|
||||
in srgb,
|
||||
var(--app-selection-color) 16%,
|
||||
var(--source-row-base)
|
||||
);
|
||||
background: var(--app-list-selected-bg);
|
||||
box-shadow: inset 0 0 0 1px var(--app-list-selected-outline);
|
||||
}
|
||||
|
||||
// ── Tile column ──────────────────────────────────────────────────────────
|
||||
|
||||
+2
-5
@@ -1,7 +1,4 @@
|
||||
<section
|
||||
class="sources-page app-scrollbar"
|
||||
[class.sources-page--empty]="!hasPlaylists()"
|
||||
>
|
||||
<section class="sources-page" [class.sources-page--empty]="!hasPlaylists()">
|
||||
@if (hasPlaylists()) {
|
||||
<header class="sources-header">
|
||||
<div class="sources-header__title">
|
||||
@@ -92,7 +89,7 @@
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
<div class="sources-content">
|
||||
<div class="sources-content app-scrollbar">
|
||||
<app-recent-playlists
|
||||
[searchQueryInput]="searchQuery()"
|
||||
(addPlaylistClicked)="onAddPlaylist($event)"
|
||||
|
||||
+7
-2
@@ -6,16 +6,19 @@
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
// The page scrolls as one: the header is not sticky.
|
||||
// The header stays and the list scrolls, as on every list page: Sort and
|
||||
// Clean up stay in reach in a long library, and a row reached by keyboard
|
||||
// never scrolls under the header.
|
||||
.sources-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sources-header {
|
||||
flex: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -80,6 +83,8 @@
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 0 20px 32px;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -241,10 +241,12 @@ describe('WorkspaceSourcesComponent', () => {
|
||||
expect(
|
||||
element.querySelector('.sources-count')?.textContent?.trim()
|
||||
).toBe('2');
|
||||
// The page scrolls as one; the header is not a separate bar.
|
||||
expect(element.querySelector('.sources-page')?.classList).toContain(
|
||||
'app-scrollbar'
|
||||
);
|
||||
// The header stays; the list below it scrolls.
|
||||
const scroller = element.querySelector('.sources-content');
|
||||
expect(scroller?.classList).toContain('app-scrollbar');
|
||||
expect(
|
||||
scroller?.contains(element.querySelector('.sources-header'))
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('titles the page by the status filter and counts what it shows', async () => {
|
||||
|
||||
Reference in new issue
Block a user