完善观众端交互视觉体系
This commit is contained in:
1 parent
a8067db922
commit
e83b56b22f
3 files changed
+71
-20
No files matched your search
@@ -38,7 +38,7 @@ export default function HomePage() {
|
|||||||
<header className="viewer-hero">
|
<header className="viewer-hero">
|
||||||
<nav className="viewer-nav" aria-label="主导航">
|
<nav className="viewer-nav" aria-label="主导航">
|
||||||
<span>{brand.brand_name}</span>
|
<span>{brand.brand_name}</span>
|
||||||
<button type="button" onClick={() => document.getElementById('programmes')?.scrollIntoView()}>
|
<button className="viewer-button viewer-button--ghost" type="button" onClick={() => document.getElementById('programmes')?.scrollIntoView()}>
|
||||||
节目目录
|
节目目录
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -77,7 +77,7 @@ export default function HomePage() {
|
|||||||
aria-label="搜索节目"
|
aria-label="搜索节目"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div className="viewer-filters" aria-label="按节目状态筛选">
|
<div className="viewer-filters" aria-label="按节目状态筛选" role="group">
|
||||||
{[
|
{[
|
||||||
['all', '全部'],
|
['all', '全部'],
|
||||||
['live', '直播中'],
|
['live', '直播中'],
|
||||||
@@ -87,7 +87,8 @@ export default function HomePage() {
|
|||||||
<button
|
<button
|
||||||
key={value}
|
key={value}
|
||||||
type="button"
|
type="button"
|
||||||
className={filter === value ? 'is-active' : ''}
|
className={`viewer-button viewer-filter${filter === value ? ' is-active' : ''}`}
|
||||||
|
aria-pressed={filter === value}
|
||||||
onClick={() => setFilter(value)}
|
onClick={() => setFilter(value)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
@@ -108,13 +109,10 @@ export default function HomePage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : visibleStreams.length === 0 ? (
|
) : visibleStreams.length === 0 ? (
|
||||||
<div style={{
|
<div className="viewer-empty">
|
||||||
textAlign: 'center', padding: '80px 0',
|
<span className="viewer-empty-icon"><VideoCameraOutlined /></span>
|
||||||
background: '#fff', borderRadius: 14,
|
<h3>暂无直播</h3>
|
||||||
}}>
|
<p>当前没有正在播出或排期的直播节目</p>
|
||||||
<VideoCameraOutlined style={{ fontSize: 40, color: '#C4BCB0', marginBottom: 16 }} />
|
|
||||||
<h3 style={{ fontSize: 18, fontWeight: 500, color: '#5E5A52' }}>暂无直播</h3>
|
|
||||||
<p style={{ color: '#949088', fontSize: 14, marginTop: 4 }}>当前没有正在播出或排期的直播节目</p>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="stream-grid">
|
<div className="stream-grid">
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export default function WatchPage() {
|
|||||||
<h2>节目章节</h2>
|
<h2>节目章节</h2>
|
||||||
<div className="chapter-list">
|
<div className="chapter-list">
|
||||||
{info.chapters.map((chapter, index) => (
|
{info.chapters.map((chapter, index) => (
|
||||||
<button key={`${chapter.time}-${index}`} type="button" onClick={() => jumpToChapter(chapter.time)}>
|
<button className="viewer-button chapter-button" key={`${chapter.time}-${index}`} type="button" onClick={() => jumpToChapter(chapter.time)}>
|
||||||
<span>{chapter.title}</span>
|
<span>{chapter.title}</span>
|
||||||
<time>{Math.floor(chapter.time / 60)}:{String(chapter.time % 60).padStart(2, '0')}</time>
|
<time>{Math.floor(chapter.time / 60)}:{String(chapter.time % 60).padStart(2, '0')}</time>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,10 +1,29 @@
|
|||||||
.viewer-shell {
|
.viewer-shell {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
overflow-x: hidden;
|
||||||
background: #f4f0e8;
|
background: #f4f0e8;
|
||||||
color: #211d18;
|
color: #211d18;
|
||||||
font-family: "Noto Serif SC", "Songti SC", SimSun, Georgia, serif;
|
font-family: "Noto Serif SC", "Songti SC", SimSun, Georgia, serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewer-button {
|
||||||
|
appearance: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
font: 600 13px/1 Inter, "Noto Sans SC", sans-serif;
|
||||||
|
transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease, color 160ms ease, transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer-button:hover { transform: translateY(-1px); }
|
||||||
|
.viewer-button:active { transform: translateY(0); }
|
||||||
|
.viewer-button:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(118, 95, 69, 0.2); }
|
||||||
|
.viewer-button:disabled { cursor: not-allowed; opacity: 0.48; transform: none; }
|
||||||
|
.viewer-button--ghost { padding: 9px 14px; border-color: #d2cabf; background: rgba(255, 255, 255, 0.48); color: #403a33; }
|
||||||
|
.viewer-button--ghost:hover { border-color: #aa9f91; background: #fffdf9; color: #211d18; }
|
||||||
|
|
||||||
.viewer-nav {
|
.viewer-nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -37,24 +56,26 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: rgba(255, 255, 255, 0.58);
|
background: rgba(255, 255, 255, 0.58);
|
||||||
color: #767066;
|
color: #767066;
|
||||||
|
box-shadow: 0 1px 2px rgba(33, 29, 24, 0.04), 0 8px 24px rgba(33, 29, 24, 0.04);
|
||||||
|
transition: border-color 160ms ease, box-shadow 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewer-search:focus-within { border-color: #aaa296; box-shadow: 0 0 0 3px rgba(117, 108, 94, 0.08); }
|
.viewer-search:focus-within { border-color: #aaa296; box-shadow: 0 0 0 3px rgba(117, 108, 94, 0.08); }
|
||||||
.viewer-search input { width: 100%; border: 0; outline: 0; background: transparent; color: #292720; font: 14px/1.4 Inter, "Noto Sans SC", sans-serif; }
|
.viewer-search input { appearance: none; width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: #292720; font: 14px/1.4 Inter, "Noto Sans SC", sans-serif; }
|
||||||
.viewer-search input::placeholder { color: #9d978d; }
|
.viewer-search input::placeholder { color: #9d978d; }
|
||||||
|
|
||||||
.viewer-filters { display: flex; flex-wrap: wrap; gap: 6px; }
|
.viewer-filters { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||||
.viewer-filters button {
|
.viewer-filter {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 7px;
|
border-radius: 999px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #777168;
|
color: #777168;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font: 13px/1 Inter, "Noto Sans SC", sans-serif;
|
font: 13px/1 Inter, "Noto Sans SC", sans-serif;
|
||||||
}
|
}
|
||||||
.viewer-filters button:hover { border-color: #d8d2c8; color: #292720; background: rgba(255, 255, 255, 0.45); }
|
.viewer-filter:hover { border-color: #d8d2c8; color: #292720; background: rgba(255, 255, 255, 0.72); }
|
||||||
.viewer-filters button.is-active { border-color: #cbc4b9; background: #eae5dc; color: #292720; }
|
.viewer-filter.is-active { border-color: #292720; background: #292720; color: #fffdf9; box-shadow: 0 5px 14px rgba(33, 29, 24, 0.16); }
|
||||||
|
|
||||||
.stream-card { border-color: #d9d3c9; box-shadow: none; transition: transform 160ms ease, border-color 160ms ease, background 160ms ease; }
|
.stream-card { border-color: #d9d3c9; box-shadow: none; transition: transform 160ms ease, border-color 160ms ease, background 160ms ease; }
|
||||||
.stream-card:hover { transform: translateY(-2px); border-color: #bcb4a8; }
|
.stream-card:hover { transform: translateY(-2px); border-color: #bcb4a8; }
|
||||||
@@ -135,11 +156,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.stream-card {
|
.stream-card {
|
||||||
|
appearance: none;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid #dcd3c7;
|
border: 1px solid #dcd3c7;
|
||||||
border-radius: 8px;
|
border-radius: 14px;
|
||||||
background: #fffdf9;
|
background: #fffdf9;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
@@ -155,6 +177,7 @@ button.stream-card {
|
|||||||
button.stream-card:hover {
|
button.stream-card:hover {
|
||||||
border-color: #a99882;
|
border-color: #a99882;
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 14px 32px rgba(40, 34, 27, 0.09);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.stream-card:active {
|
button.stream-card:active {
|
||||||
@@ -185,13 +208,31 @@ button.stream-card:focus-visible {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 26px;
|
min-height: 26px;
|
||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
border-radius: 3px;
|
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||||
|
border-radius: 999px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||||||
font-family: system-ui, sans-serif;
|
font-family: system-ui, sans-serif;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 650;
|
font-weight: 650;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewer-empty {
|
||||||
|
display: grid;
|
||||||
|
min-height: 300px;
|
||||||
|
place-items: center;
|
||||||
|
align-content: center;
|
||||||
|
padding: 56px 24px;
|
||||||
|
border: 1px dashed #cec5b8;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba(255, 253, 249, 0.72);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer-empty-icon { display: grid; width: 58px; height: 58px; margin-bottom: 18px; place-items: center; border-radius: 18px; background: #ebe4da; color: #766d62; font-size: 25px; }
|
||||||
|
.viewer-empty h3 { color: #3f3932; font-size: 19px; font-weight: 650; }
|
||||||
|
.viewer-empty p { margin-top: 6px; color: #84796c; font: 14px/1.6 Inter, "Noto Sans SC", sans-serif; }
|
||||||
|
|
||||||
.stream-status.live {
|
.stream-status.live {
|
||||||
background: #8f302b;
|
background: #8f302b;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -261,6 +302,7 @@ button.stream-card:focus-visible {
|
|||||||
background: #171512;
|
background: #171512;
|
||||||
color: #eee7dc;
|
color: #eee7dc;
|
||||||
font-family: "Noto Serif SC", "Songti SC", SimSun, Georgia, serif;
|
font-family: "Noto Serif SC", "Songti SC", SimSun, Georgia, serif;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.watch-header {
|
.watch-header {
|
||||||
@@ -364,7 +406,9 @@ button.stream-card:focus-visible {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.chapter-list button:hover { border-color: #806d56; background: #2b261f; }
|
.chapter-button { width: 100%; border-radius: 8px; }
|
||||||
|
.chapter-list button:hover { border-color: #9d8263; background: #302920; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.16); }
|
||||||
|
.chapter-list button:focus-visible { border-color: #b99a76; box-shadow: 0 0 0 3px rgba(185, 154, 118, 0.22); }
|
||||||
.chapter-list time { color: #949088; font-variant-numeric: tabular-nums; }
|
.chapter-list time { color: #949088; font-variant-numeric: tabular-nums; }
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
@@ -423,7 +467,8 @@ button.stream-card:focus-visible {
|
|||||||
|
|
||||||
.viewer-directory-tools { align-items: stretch; flex-direction: column; }
|
.viewer-directory-tools { align-items: stretch; flex-direction: column; }
|
||||||
.viewer-search { width: auto; }
|
.viewer-search { width: auto; }
|
||||||
.viewer-filters { overflow-x: auto; flex-wrap: nowrap; padding-bottom: 3px; }
|
.viewer-filters { max-width: 100%; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 6px; scrollbar-width: none; }
|
||||||
|
.viewer-filters::-webkit-scrollbar { display: none; }
|
||||||
.viewer-filters button { flex: none; }
|
.viewer-filters button { flex: none; }
|
||||||
|
|
||||||
.viewer-hero {
|
.viewer-hero {
|
||||||
@@ -452,6 +497,14 @@ button.stream-card:focus-visible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
.viewer-hero, .viewer-main { padding-inline: 16px; }
|
||||||
|
.viewer-nav { gap: 12px; }
|
||||||
|
.viewer-nav span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.watch-header { padding-inline: 12px; }
|
||||||
|
.watch-quality, .watch-line { min-width: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.viewer-shell *,
|
.viewer-shell *,
|
||||||
.viewer-shell *::before,
|
.viewer-shell *::before,
|
||||||
|
|||||||
Reference in new issue
Block a user