mirror of
https://github.com/nianzhibai/91.git
synced 2026-06-15 08:45:41 +08:00
style(detail): redesign video detail page to cinema dark ultra-minimalist layout
This commit is contained in:
@@ -13,12 +13,21 @@ export function VideoActions({ video, onHideVideo, hideSaving }: Props) {
|
||||
const [likes, setLikes] = useState(video.likes ?? 0);
|
||||
const [dislikes, setDislikes] = useState(video.dislikes ?? 0);
|
||||
const [bursting, setBursting] = useState(false);
|
||||
const [liked, setLiked] = useState(false);
|
||||
const [disliked, setDisliked] = useState(false);
|
||||
|
||||
async function handleLike() {
|
||||
if (liked) return;
|
||||
setLiked(true);
|
||||
setLikes((n) => n + 1);
|
||||
setBursting(true);
|
||||
window.setTimeout(() => setBursting(false), 240);
|
||||
|
||||
if (disliked) {
|
||||
setDisliked(false);
|
||||
setDislikes((n) => Math.max(0, n - 1));
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/video/${encodeURIComponent(video.id)}/like`,
|
||||
@@ -31,26 +40,38 @@ export function VideoActions({ video, onHideVideo, hideSaving }: Props) {
|
||||
}
|
||||
} catch {
|
||||
setLikes((n) => Math.max(0, n - 1));
|
||||
setLiked(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDislike() {
|
||||
if (disliked) return;
|
||||
setDisliked(true);
|
||||
setDislikes((n) => n + 1);
|
||||
|
||||
if (liked) {
|
||||
setLiked(false);
|
||||
setLikes((n) => Math.max(0, n - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="video-actions">
|
||||
<button
|
||||
className={`video-actions__btn video-actions__like ${bursting ? "is-bursting" : ""}`}
|
||||
className={`video-actions__btn video-actions__like ${liked ? "is-active" : ""} ${bursting ? "is-bursting" : ""}`}
|
||||
onClick={handleLike}
|
||||
aria-label="点赞"
|
||||
>
|
||||
<ThumbsUp size={14} />
|
||||
点赞 · {formatCount(likes)}
|
||||
<ThumbsUp size={14} fill={liked ? "currentColor" : "none"} />
|
||||
{liked ? "已赞" : "点赞"} · {formatCount(likes)}
|
||||
</button>
|
||||
<button
|
||||
className="video-actions__btn is-danger"
|
||||
onClick={() => setDislikes((n) => n + 1)}
|
||||
className={`video-actions__btn is-danger ${disliked ? "is-active" : ""}`}
|
||||
onClick={handleDislike}
|
||||
aria-label="点踩"
|
||||
>
|
||||
<ThumbsDown size={14} />
|
||||
点踩 · {formatCount(dislikes)}
|
||||
<ThumbsDown size={14} fill={disliked ? "currentColor" : "none"} />
|
||||
{disliked ? "已踩" : "点踩"} · {formatCount(dislikes)}
|
||||
</button>
|
||||
<button
|
||||
className="video-actions__btn is-danger"
|
||||
@@ -58,7 +79,7 @@ export function VideoActions({ video, onHideVideo, hideSaving }: Props) {
|
||||
disabled={hideSaving}
|
||||
>
|
||||
<EyeOff size={14} />
|
||||
{hideSaving ? "隐藏中" : "不再展示"}
|
||||
{hideSaving ? "隐藏中" : "不再显示"}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import type { TagItem, VideoDetail } from "@/types";
|
||||
import { formatCount } from "@/lib/format";
|
||||
|
||||
type Props = {
|
||||
video: VideoDetail;
|
||||
@@ -17,6 +18,7 @@ export function VideoInfoPanel({
|
||||
const [editingTags, setEditingTags] = useState(false);
|
||||
const [draftTags, setDraftTags] = useState<string[]>(video.tags ?? []);
|
||||
const [tagError, setTagError] = useState("");
|
||||
const [descCollapsed, setDescCollapsed] = useState(true);
|
||||
|
||||
function openTagEditor() {
|
||||
setDraftTags(video.tags ?? []);
|
||||
@@ -37,13 +39,28 @@ export function VideoInfoPanel({
|
||||
|
||||
return (
|
||||
<section className="info-panel" aria-label="视频信息">
|
||||
<header className="info-panel__header">视频信息</header>
|
||||
<header className="info-panel__header">视频详细参数</header>
|
||||
<div className="info-panel__body">
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">发布时间</span>
|
||||
<span className="info-row__value">{video.publishedAt}</span>
|
||||
</div>
|
||||
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">发布作者</span>
|
||||
<span className="info-row__value">{video.author || video.category || "影视合集"}</span>
|
||||
</div>
|
||||
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">播放次数</span>
|
||||
<span className="info-row__value">{formatCount(video.views)} 次观看</span>
|
||||
</div>
|
||||
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">画面品质</span>
|
||||
<span className="info-row__value">{video.quality || "HD 1080P"}</span>
|
||||
</div>
|
||||
|
||||
{video.sourceLabel && (
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">来源网盘</span>
|
||||
@@ -52,14 +69,13 @@ export function VideoInfoPanel({
|
||||
)}
|
||||
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">来源/合集</span>
|
||||
<div className="info-row__value">
|
||||
{video.category || video.author || "未设置"}
|
||||
</div>
|
||||
<span className="info-row__label">视频时长</span>
|
||||
<span className="info-row__value">{video.duration || "未知"}</span>
|
||||
</div>
|
||||
|
||||
<div className="info-row">
|
||||
<span className="info-row__label">标签</span>
|
||||
{/* 标签行 - 满宽 */}
|
||||
<div className="info-row is-tags-row">
|
||||
<span className="info-row__label">视频标签</span>
|
||||
<div className="info-row__value">
|
||||
<div className="detail-tags">
|
||||
{(video.tags ?? []).map((t) => (
|
||||
@@ -69,7 +85,7 @@ export function VideoInfoPanel({
|
||||
))}
|
||||
{onTagsChange && (
|
||||
<button className="detail-tags__edit" onClick={openTagEditor}>
|
||||
选择标签
|
||||
修改标签
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -84,7 +100,7 @@ export function VideoInfoPanel({
|
||||
onChange={() => setDraftTags(toggleTag(draftTags, tag.label))}
|
||||
/>
|
||||
<span>{tag.label}</span>
|
||||
{typeof tag.count === "number" && <em>{tag.count}</em>}
|
||||
{typeof tag.count === "number" && <em>({tag.count})</em>}
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
@@ -92,13 +108,41 @@ export function VideoInfoPanel({
|
||||
<div className="detail-tag-editor__actions">
|
||||
<button onClick={() => setEditingTags(false)}>取消</button>
|
||||
<button onClick={saveTags} disabled={tagSaving}>
|
||||
{tagSaving ? "保存中..." : "保存"}
|
||||
{tagSaving ? "保存中..." : "保存修改"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 描述行 - Collapsible */}
|
||||
{video.description && (
|
||||
<div
|
||||
className="info-row"
|
||||
style={{
|
||||
gridColumn: "1 / -1",
|
||||
borderTop: "1px dashed rgba(255, 255, 255, 0.06)",
|
||||
paddingTop: "var(--space-4)"
|
||||
}}
|
||||
>
|
||||
<span className="info-row__label">视频简介</span>
|
||||
<div className="info-row__value" style={{ position: "relative" }}>
|
||||
<p className={`description ${descCollapsed ? "is-collapsed" : ""}`} style={{ margin: 0 }}>
|
||||
{video.description}
|
||||
</p>
|
||||
{video.description.length > 120 && (
|
||||
<button
|
||||
className="description-toggle"
|
||||
onClick={() => setDescCollapsed(!descCollapsed)}
|
||||
style={{ border: 0, padding: 0, marginTop: "6px" }}
|
||||
>
|
||||
{descCollapsed ? "展开全部介绍 ↓" : "收起介绍 ↑"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -112,20 +112,26 @@ export default function VideoDetailPage() {
|
||||
<div className="container page-section">
|
||||
<div className="detail-layout">
|
||||
<div className="detail-main" ref={detailTopRef}>
|
||||
{/* 顶置影院式悬浮播放器 */}
|
||||
<div className="detail-player-card">
|
||||
<div className="detail-title-bar">{detail.title}</div>
|
||||
<VideoPlayer
|
||||
src={detail.videoSrc}
|
||||
poster={detail.poster}
|
||||
title={detail.title}
|
||||
onFirstPlay={handleFirstPlay}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 动作区 */}
|
||||
<div className="detail-actions-row">
|
||||
<VideoActions
|
||||
video={detail}
|
||||
onHideVideo={handleHideVideo}
|
||||
hideSaving={hideSaving}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 磨砂元数据展板 */}
|
||||
<VideoInfoPanel
|
||||
video={detail}
|
||||
availableTags={tags}
|
||||
|
||||
+309
-211
@@ -1,49 +1,53 @@
|
||||
/* =========================================================
|
||||
* Video detail page
|
||||
* Premium Video Detail Page Styles
|
||||
* Cinema dark-slate concept with borderless player floating,
|
||||
* below-player bold headers, glass uploader profiles, and
|
||||
* high-density horizontal recommendation items.
|
||||
* ========================================================= */
|
||||
|
||||
.detail-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 340px;
|
||||
grid-template-columns: minmax(0, 1fr) 360px;
|
||||
gap: var(--space-6);
|
||||
margin-top: var(--space-4);
|
||||
margin-top: var(--space-5);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-4);
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Player card(标题 + 视频 + 操作 一体卡片)
|
||||
* Movie-Theater Floating Player Container
|
||||
* ========================================================= */
|
||||
.detail-player-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: #000;
|
||||
border: 1px solid rgba(255, 255, 255, 0.04);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-md);
|
||||
box-shadow: var(--shadow-xl);
|
||||
transition: box-shadow var(--transition-normal), border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.detail-title-bar {
|
||||
padding: var(--space-4) var(--space-5);
|
||||
font-size: var(--font-xl);
|
||||
font-weight: var(--weight-bold);
|
||||
letter-spacing: -0.005em;
|
||||
color: var(--text-strong);
|
||||
background: var(--bg-elevated);
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
.detail-player-card:hover {
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow:
|
||||
0 12px 30px rgba(0, 0, 0, 0.4),
|
||||
0 30px 80px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* ----- Player ----- */
|
||||
/* Video Player controls custom style */
|
||||
.video-player {
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 9;
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.video-player video {
|
||||
@@ -59,96 +63,91 @@
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: var(--space-4);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: #fff;
|
||||
font-size: var(--font-md);
|
||||
text-align: center;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
/* ----- Stats ----- */
|
||||
.video-stats {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-5);
|
||||
padding: var(--space-3) var(--space-5);
|
||||
background: var(--bg-surface);
|
||||
color: var(--text-default);
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.video-stats__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.video-stats__label {
|
||||
color: var(--text-faint);
|
||||
}
|
||||
|
||||
.video-stats__value {
|
||||
background: rgba(8, 9, 13, 0.85);
|
||||
color: var(--text-strong);
|
||||
font-weight: var(--weight-semibold);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-size: var(--font-md);
|
||||
font-weight: var(--weight-medium);
|
||||
text-align: center;
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* ----- Action bar ----- */
|
||||
|
||||
|
||||
/* =========================================================
|
||||
* Video Action Controls Row
|
||||
* ========================================================= */
|
||||
.detail-actions-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-4);
|
||||
padding-bottom: var(--space-4);
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Translucent Action Buttons (Likes / Dislikes / Hide)
|
||||
* ========================================================= */
|
||||
.video-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
padding: var(--space-4) var(--space-5);
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.video-actions__btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 9px 16px;
|
||||
height: 38px;
|
||||
padding: 0 var(--space-4);
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-elevated);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
color: var(--text-default);
|
||||
font-size: var(--font-sm);
|
||||
font-weight: var(--weight-medium);
|
||||
border: 1px solid var(--border-subtle);
|
||||
font-weight: var(--weight-semibold);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.video-actions__btn:hover:not(:disabled) {
|
||||
background: var(--bg-sunken);
|
||||
border-color: var(--border-default);
|
||||
background: rgba(255, 255, 255, 0.09);
|
||||
border-color: rgba(255, 255, 255, 0.16);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
.video-actions__btn:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.video-actions__btn.is-active {
|
||||
background: var(--accent);
|
||||
color: var(--text-on-accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
/* Point Actions Specific Hovers */
|
||||
.video-actions__like:hover:not(:disabled) {
|
||||
background: var(--accent-soft);
|
||||
border-color: var(--border-accent);
|
||||
color: var(--accent);
|
||||
box-shadow: 0 4px 12px rgba(255, 138, 60, 0.12);
|
||||
}
|
||||
|
||||
.video-actions__btn.is-danger {
|
||||
color: var(--text-default);
|
||||
.video-actions__btn.is-active {
|
||||
background: var(--accent-gradient);
|
||||
color: var(--text-on-accent);
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 4px 14px var(--accent-glow);
|
||||
}
|
||||
|
||||
.video-actions__btn.is-danger:hover {
|
||||
.video-actions__btn.is-danger:hover:not(:disabled) {
|
||||
background: var(--danger-soft);
|
||||
border-color: rgba(241, 85, 108, 0.4);
|
||||
border-color: rgba(241, 85, 108, 0.3);
|
||||
color: var(--danger);
|
||||
box-shadow: 0 4px 12px rgba(241, 85, 108, 0.12);
|
||||
}
|
||||
|
||||
/* like burst */
|
||||
/* Burst dynamic animation for Point Up */
|
||||
.video-actions__like.is-bursting {
|
||||
animation: like-burst 280ms var(--ease-out);
|
||||
}
|
||||
@@ -156,70 +155,91 @@
|
||||
@keyframes like-burst {
|
||||
0% { transform: scale(1); }
|
||||
35% {
|
||||
transform: scale(1.1);
|
||||
background: var(--accent);
|
||||
transform: scale(1.12);
|
||||
background: var(--accent-gradient);
|
||||
color: var(--text-on-accent);
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 6px var(--accent-soft);
|
||||
box-shadow: 0 0 0 8px var(--accent-soft);
|
||||
}
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Info panel
|
||||
* Glassmorphic Info Panel Box
|
||||
* ========================================================= */
|
||||
.info-panel {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: var(--glass-card);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-md), var(--shadow-inset);
|
||||
transition: border-color var(--transition-normal);
|
||||
}
|
||||
|
||||
.info-panel:focus-within {
|
||||
border-color: rgba(255, 255, 255, 0.14);
|
||||
}
|
||||
|
||||
.info-panel__header {
|
||||
padding: var(--space-3) var(--space-5);
|
||||
font-size: var(--font-md);
|
||||
font-weight: var(--weight-semibold);
|
||||
font-weight: var(--weight-bold);
|
||||
color: var(--text-strong);
|
||||
background: var(--bg-elevated);
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.info-panel__header::before {
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: var(--accent);
|
||||
border-radius: var(--radius-xs);
|
||||
background: var(--accent-gradient);
|
||||
}
|
||||
|
||||
.info-panel__body {
|
||||
padding: var(--space-5);
|
||||
display: grid;
|
||||
gap: var(--space-4);
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: var(--space-4) var(--space-5);
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: grid;
|
||||
grid-template-columns: 96px minmax(0, 1fr);
|
||||
gap: var(--space-3);
|
||||
font-size: var(--font-sm);
|
||||
align-items: start;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Span Tags row full-width */
|
||||
.info-row.is-tags-row {
|
||||
grid-column: 1 / -1;
|
||||
margin-top: 4px;
|
||||
border-top: 1px dashed rgba(255, 255, 255, 0.06);
|
||||
padding-top: var(--space-4);
|
||||
}
|
||||
|
||||
.info-row__label {
|
||||
color: var(--text-faint);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: var(--weight-medium);
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.info-row__value {
|
||||
color: var(--text-default);
|
||||
font-size: var(--font-sm);
|
||||
font-weight: var(--weight-medium);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ----- Detail tag chips ----- */
|
||||
/* ----- Capsule Tag Chips ----- */
|
||||
.detail-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -229,72 +249,95 @@
|
||||
|
||||
.detail-tags .tag-chip {
|
||||
height: 26px;
|
||||
padding: 0 12px;
|
||||
padding: 0 11px;
|
||||
font-size: var(--font-xs);
|
||||
border-radius: var(--radius-pill);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.07);
|
||||
color: var(--text-muted);
|
||||
cursor: default;
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.detail-tags .tag-chip:hover {
|
||||
background: var(--bg-surface);
|
||||
color: var(--text-default);
|
||||
border-color: var(--border-subtle);
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
border-color: var(--border-accent);
|
||||
}
|
||||
|
||||
.detail-tags__edit {
|
||||
height: 26px;
|
||||
padding: 0 12px;
|
||||
border: 1px dashed var(--border-default);
|
||||
border: 1px dashed rgba(255, 255, 255, 0.15);
|
||||
border-radius: var(--radius-pill);
|
||||
background: transparent;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: var(--weight-medium);
|
||||
font-weight: var(--weight-semibold);
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.detail-tags__edit:hover {
|
||||
border-color: var(--border-accent);
|
||||
color: var(--accent);
|
||||
border-style: solid;
|
||||
background: var(--accent-softer);
|
||||
}
|
||||
|
||||
/* Elegant Tag Drawer */
|
||||
.detail-tag-editor {
|
||||
margin-top: var(--space-3);
|
||||
padding: var(--space-3);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: var(--space-4);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--bg-sunken);
|
||||
box-shadow: var(--shadow-inset);
|
||||
}
|
||||
|
||||
.detail-tag-editor__grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
max-height: 180px;
|
||||
overflow-y: auto;
|
||||
padding-right: var(--space-2);
|
||||
}
|
||||
|
||||
.detail-tag-editor__grid::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
.detail-tag-editor__grid::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.detail-tag-editor__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 5px 10px;
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 6px 12px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--bg-surface);
|
||||
color: var(--text-default);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: var(--weight-medium);
|
||||
cursor: pointer;
|
||||
transition: border-color var(--transition-fast);
|
||||
transition: all var(--transition-fast);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.detail-tag-editor__item:hover {
|
||||
border-color: var(--border-default);
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
background: var(--bg-elevated);
|
||||
}
|
||||
|
||||
.detail-tag-editor__item input {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin: 0;
|
||||
accent-color: var(--accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.detail-tag-editor__item em {
|
||||
@@ -307,36 +350,40 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--space-2);
|
||||
margin-top: var(--space-3);
|
||||
margin-top: var(--space-4);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
padding-top: var(--space-3);
|
||||
}
|
||||
|
||||
.detail-tag-editor__actions button {
|
||||
padding: 7px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-elevated);
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
border-radius: 6px;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
color: var(--text-default);
|
||||
font-size: var(--font-sm);
|
||||
font-weight: var(--weight-medium);
|
||||
border: 1px solid var(--border-subtle);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: var(--weight-semibold);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.detail-tag-editor__actions button:hover {
|
||||
background: var(--bg-sunken);
|
||||
border-color: var(--border-default);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
.detail-tag-editor__actions button:last-child {
|
||||
background: var(--accent);
|
||||
background: var(--accent-gradient);
|
||||
border-color: var(--accent);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
.detail-tag-editor__actions button:last-child:hover {
|
||||
filter: brightness(1.05);
|
||||
filter: brightness(1.06);
|
||||
}
|
||||
|
||||
.detail-tag-editor__actions button:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -344,78 +391,49 @@
|
||||
margin-top: var(--space-2);
|
||||
color: var(--danger);
|
||||
font-size: var(--font-xs);
|
||||
}
|
||||
|
||||
/* ----- Description ----- */
|
||||
.description {
|
||||
font-size: var(--font-sm);
|
||||
line-height: var(--line-relaxed);
|
||||
color: var(--text-default);
|
||||
white-space: pre-wrap;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.description.is-collapsed {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.description-toggle {
|
||||
display: inline-block;
|
||||
margin-top: 6px;
|
||||
color: var(--accent);
|
||||
font-size: var(--font-xs);
|
||||
font-weight: var(--weight-medium);
|
||||
}
|
||||
|
||||
.description-toggle:hover {
|
||||
text-decoration: underline;
|
||||
font-weight: var(--weight-semibold);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Comments
|
||||
* Unified Comments Panel (Glass style)
|
||||
* ========================================================= */
|
||||
.comment-panel {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: var(--glass-card);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-md), var(--shadow-inset);
|
||||
}
|
||||
|
||||
.comment-panel__header {
|
||||
padding: var(--space-3) var(--space-5);
|
||||
font-size: var(--font-md);
|
||||
font-weight: var(--weight-semibold);
|
||||
font-weight: var(--weight-bold);
|
||||
color: var(--text-strong);
|
||||
background: var(--bg-elevated);
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.comment-panel__header::before {
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: var(--accent);
|
||||
border-radius: var(--radius-xs);
|
||||
background: var(--accent-gradient);
|
||||
}
|
||||
|
||||
.comment-panel__body {
|
||||
padding: var(--space-3) var(--space-5) var(--space-4);
|
||||
}
|
||||
|
||||
.comment-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.comment-item {
|
||||
padding: var(--space-3) 0;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.comment-item:last-child {
|
||||
@@ -428,38 +446,38 @@
|
||||
gap: var(--space-2);
|
||||
font-size: var(--font-xs);
|
||||
color: var(--text-faint);
|
||||
margin-bottom: 6px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.comment-item__author {
|
||||
color: var(--text-strong);
|
||||
font-weight: var(--weight-semibold);
|
||||
font-weight: var(--weight-bold);
|
||||
}
|
||||
|
||||
.comment-empty {
|
||||
padding: var(--space-7) 0;
|
||||
padding: var(--space-6) 0;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Recommended sidebar
|
||||
* Ultimate Compact Sidebar Recommendations Overrides
|
||||
* ========================================================= */
|
||||
.detail-side {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3);
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.detail-side__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 0 var(--space-2);
|
||||
gap: 10px;
|
||||
padding: 0 var(--space-1);
|
||||
font-size: var(--font-md);
|
||||
font-weight: var(--weight-semibold);
|
||||
font-weight: var(--weight-bold);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
@@ -467,35 +485,112 @@
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: var(--accent);
|
||||
border-radius: var(--radius-xs);
|
||||
background: var(--accent-gradient);
|
||||
}
|
||||
|
||||
/* Convert all standard VideoCards inside detail sidebar to elegant compact items */
|
||||
.detail-side__list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
/* 推荐卡每张占独立一行,但不要无限拉宽:
|
||||
* - 桌面侧栏 340px 时本身就在限内
|
||||
* - 1024px 以下变单列布局后限制到 360px 居中,避免变成超大卡 */
|
||||
.detail-side__list .video-card {
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
margin: 0 auto;
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
border-radius: 0 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* Sidebar cards hover background overlay */
|
||||
.detail-side__list .video-card:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.detail-side__list .video-card__link {
|
||||
display: grid !important;
|
||||
grid-template-columns: 140px minmax(0, 1fr) !important;
|
||||
grid-template-rows: auto auto !important;
|
||||
gap: 4px 12px !important;
|
||||
align-items: start !important;
|
||||
padding: 6px !important;
|
||||
border-radius: var(--radius-md) !important;
|
||||
background: transparent;
|
||||
transition: background var(--transition-fast);
|
||||
}
|
||||
|
||||
.detail-side__list .video-card__link:hover {
|
||||
background: rgba(255, 255, 255, 0.03) !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.detail-side__list .thumb-frame {
|
||||
grid-column: 1 !important;
|
||||
grid-row: 1 / span 2 !important;
|
||||
width: 140px !important;
|
||||
border-radius: var(--radius-sm) !important;
|
||||
box-shadow: var(--shadow-sm);
|
||||
aspect-ratio: 16 / 9 !important;
|
||||
}
|
||||
|
||||
.detail-side__list .video-title {
|
||||
grid-column: 2 !important;
|
||||
grid-row: 1 !important;
|
||||
font-size: 12px !important;
|
||||
line-height: 1.35 !important;
|
||||
font-weight: var(--weight-bold) !important;
|
||||
color: var(--text-strong) !important;
|
||||
margin: 0 !important;
|
||||
display: -webkit-box !important;
|
||||
-webkit-line-clamp: 2 !important;
|
||||
-webkit-box-orient: vertical !important;
|
||||
overflow: hidden !important;
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.detail-side__list .video-card__link:hover .video-title {
|
||||
color: var(--accent) !important;
|
||||
}
|
||||
|
||||
.detail-side__list .video-meta {
|
||||
grid-column: 2 !important;
|
||||
grid-row: 2 !important;
|
||||
font-size: 11px !important;
|
||||
color: var(--text-muted) !important;
|
||||
display: flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
align-items: center !important;
|
||||
gap: 2px 6px !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Responsive
|
||||
* Responsive Breakpoints
|
||||
* ========================================================= */
|
||||
@media (max-width: 1024px) {
|
||||
.detail-layout {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
.detail-side {
|
||||
margin-top: var(--space-3);
|
||||
margin-top: var(--space-4);
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
padding-top: var(--space-5);
|
||||
}
|
||||
|
||||
.detail-side__list .video-card__link {
|
||||
grid-template-columns: 160px minmax(0, 1fr) !important;
|
||||
}
|
||||
|
||||
.detail-side__list .thumb-frame {
|
||||
width: 160px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,60 +600,63 @@
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.detail-title-bar {
|
||||
padding: var(--space-3) var(--space-4);
|
||||
font-size: var(--font-md);
|
||||
.detail-title {
|
||||
font-size: var(--font-lg);
|
||||
line-height: 1.35;
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.video-stats {
|
||||
padding: var(--space-3) var(--space-4);
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.video-stats__item {
|
||||
.detail-publisher-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 2px;
|
||||
gap: var(--space-3);
|
||||
padding-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.video-actions {
|
||||
padding: var(--space-3) var(--space-4);
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
flex-wrap: nowrap;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 4px;
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.video-actions::-webkit-scrollbar {
|
||||
display: none; /* Chrome/Safari */
|
||||
}
|
||||
|
||||
.video-actions::-webkit-scrollbar { display: none; }
|
||||
|
||||
.video-actions__btn {
|
||||
flex-shrink: 0;
|
||||
padding: 7px 12px;
|
||||
height: 34px;
|
||||
padding: 0 var(--space-3);
|
||||
font-size: var(--font-xs);
|
||||
}
|
||||
|
||||
.info-panel__header,
|
||||
.comment-panel__header {
|
||||
padding: 10px var(--space-4);
|
||||
padding: 12px var(--space-4);
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.info-panel__body {
|
||||
padding: var(--space-4);
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.info-row {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.info-row__label {
|
||||
font-size: var(--font-xs);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
.info-row.is-tags-row {
|
||||
padding-top: var(--space-3);
|
||||
}
|
||||
|
||||
.comment-panel__body {
|
||||
padding: 0 var(--space-4) var(--space-3);
|
||||
}
|
||||
|
||||
.detail-side__list .video-card__link {
|
||||
grid-template-columns: 120px minmax(0, 1fr) !important;
|
||||
}
|
||||
|
||||
.detail-side__list .thumb-frame {
|
||||
width: 120px !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user