feat(ui): surface live language filters and built-in EPG sources (#23)

Add language filter controls for projected live channels, preserve backend language views in the browser, and separate built-in EPG sources from custom sources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
blomios
2026-10-06 11:42:23 +02:00
parent 2a1c745a26
commit 638a31d9ef
9 changed files with 425 additions and 25 deletions

View File

@ -537,6 +537,82 @@ h4 {
margin-top: var(--space-sm);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.language-filter {
position: relative;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-xs);
margin-top: var(--space-sm);
}
.language-filter-label {
width: 100%;
color: var(--color-text-muted);
font-size: 0.75rem;
}
.language-chip {
min-height: 32px;
padding: 4px 9px;
border: 1px solid var(--color-border);
border-radius: 999px;
background: var(--color-bg-tertiary);
color: var(--color-text-secondary);
cursor: pointer;
}
.language-chip[aria-pressed="true"] {
border-color: var(--color-accent);
background: var(--color-accent-dim);
color: var(--color-text-primary);
}
.language-more-panel {
position: absolute;
z-index: 20;
top: 100%;
left: 0;
right: 0;
padding: var(--space-sm);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
background: var(--color-bg-secondary);
box-shadow: var(--shadow-lg);
}
.language-search {
box-sizing: border-box;
width: 100%;
min-height: 40px;
margin-bottom: var(--space-sm);
padding: var(--space-sm);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-bg-tertiary);
color: var(--color-text-primary);
}
.language-options {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
max-height: 180px;
overflow: auto;
}
.source-select {
flex: 1;
padding: var(--space-xs) var(--space-sm);
@ -647,6 +723,28 @@ h4 {
object-fit: contain;
}
.channel-logo-wrap {
position: relative;
flex: 0 0 40px;
height: 40px;
}
.channel-language-badge {
position: absolute;
top: -4px;
left: -4px;
min-width: 20px;
padding: 1px 4px;
border-radius: 999px;
background: var(--color-accent);
color: #fff;
font-size: 0.625rem;
font-weight: 700;
line-height: 18px;
text-align: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.channel-info {
flex: 1;
min-width: 0;
@ -1520,6 +1618,32 @@ video::cue {
word-break: break-all;
}
.source-meta {
margin-top: 2px;
color: var(--color-text-muted);
font-size: 0.75rem;
}
.source-badge {
display: inline-block;
margin-left: var(--space-xs);
padding: 2px 6px;
border-radius: 999px;
background: var(--color-accent-dim);
color: var(--color-accent);
font-size: 0.6875rem;
font-weight: 600;
}
@media (hover: none) and (pointer: coarse) {
.language-chip,
.variant-toggle,
.source-actions .btn {
min-height: 44px;
min-width: 44px;
}
}
.source-actions {
display: flex;
gap: var(--space-xs);