mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(skin): add error handling for audio players (#1048)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
559d5169b5
commit
df927f67fc
@@ -1,5 +1,3 @@
|
||||
@import "../../shared/css/audio/icon-state.css";
|
||||
@import "../../shared/css/audio/tooltip-state.css";
|
||||
@import "./components/reset.css";
|
||||
@import "./components/root.css";
|
||||
@import "./components/surface.css";
|
||||
@@ -11,6 +9,8 @@
|
||||
@import "./components/icons.css";
|
||||
@import "./components/slider.css";
|
||||
@import "./components/popup.css";
|
||||
@import "../../shared/css/audio/icon-state.css";
|
||||
@import "../../shared/css/audio/tooltip-state.css";
|
||||
|
||||
/* ==========================================================================
|
||||
Root
|
||||
@@ -23,26 +23,68 @@
|
||||
--media-surface-outer-border-color: oklch(0 0 0 / 0.05);
|
||||
--media-surface-shadow-color: oklch(0 0 0 / 0.15);
|
||||
--media-surface-backdrop-filter: blur(16px) saturate(1.5);
|
||||
--media-controls-text-color: var(--media-color-primary, oklch(0 0 0));
|
||||
--media-text-color: var(--media-color-primary, oklch(0 0 0));
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--media-border-color: oklch(1 0 0 / 0.1);
|
||||
--media-surface-background-color: oklch(0 0 0 / 0.4);
|
||||
--media-controls-text-color: var(--media-color-primary, oklch(1 0 0));
|
||||
--media-text-color: var(--media-color-primary, oklch(1 0 0));
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Error Dialog
|
||||
========================================================================== */
|
||||
|
||||
.media-default-skin--audio .media-error__dialog {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding-inline: 1.25rem 0.125rem;
|
||||
transition-property: opacity, filter;
|
||||
transition-duration: 300ms;
|
||||
transition-delay: 100ms;
|
||||
transition-timing-function: ease-out;
|
||||
border-radius: calc(infinity * 1px);
|
||||
background-color: var(--media-surface-background-color);
|
||||
backdrop-filter: var(--media-surface-backdrop-filter);
|
||||
color: var(--media-text-color);
|
||||
|
||||
/* Simple, fast transition for reduced motion users */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition-duration: 100ms;
|
||||
transition-delay: 0ms;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-error[data-starting-style] .media-error__dialog,
|
||||
.media-default-skin .media-error[data-ending-style] .media-error__dialog {
|
||||
opacity: 0;
|
||||
filter: blur(4px);
|
||||
}
|
||||
|
||||
.media-default-skin--audio .media-error__content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Controls
|
||||
========================================================================== */
|
||||
|
||||
.media-default-skin--audio .media-controls {
|
||||
color: var(--media-controls-text-color);
|
||||
color: var(--media-text-color);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Sliders
|
||||
========================================================================== */
|
||||
|
||||
.media-default-skin--audio .media-slider__track {
|
||||
background-color: oklch(0 0 0 / 0.1);
|
||||
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0.5rem 1rem;
|
||||
background: oklch(1 0 0);
|
||||
border: none;
|
||||
border-radius: calc(infinity * 1px);
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: -2px;
|
||||
color: oklch(0 0 0);
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
transition-property: background-color, color, outline-offset, scale;
|
||||
transition-property: background-color, outline-offset, scale;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease-out;
|
||||
cursor: pointer;
|
||||
@@ -25,10 +21,14 @@
|
||||
touch-action: manipulation;
|
||||
|
||||
&:focus-visible {
|
||||
outline-color: oklch(62.3% 0.214 259.815);
|
||||
outline-color: currentColor;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&:active {
|
||||
scale: 0.98;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.5;
|
||||
filter: grayscale(1);
|
||||
@@ -40,12 +40,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Icon button variant */
|
||||
.media-default-skin .media-button--icon {
|
||||
display: grid;
|
||||
width: 2.125rem;
|
||||
padding: 0;
|
||||
aspect-ratio: 1;
|
||||
/* Primary button variant */
|
||||
.media-default-skin .media-button--primary {
|
||||
background: oklch(1 0 0);
|
||||
color: oklch(0 0 0);
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Subtle button variant */
|
||||
.media-default-skin .media-button--subtle {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
text-shadow: inherit;
|
||||
@@ -56,6 +60,14 @@
|
||||
background-color: oklch(from currentColor l c h / 0.1);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Icon button variant */
|
||||
.media-default-skin .media-button--icon {
|
||||
display: grid;
|
||||
width: 2.125rem;
|
||||
padding: 0;
|
||||
aspect-ratio: 1;
|
||||
|
||||
&:active {
|
||||
scale: 0.9;
|
||||
@@ -72,7 +84,7 @@
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
bottom: -3px;
|
||||
font-size: 0.75em;
|
||||
font-size: 10px;
|
||||
font-weight: 480;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
@@ -3,57 +3,7 @@
|
||||
========================================================================== */
|
||||
|
||||
.media-default-skin .media-error {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.media-default-skin .media-error__dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
max-width: 18rem;
|
||||
padding: 0.75rem;
|
||||
border-radius: 1.75rem;
|
||||
color: oklch(1 0 0);
|
||||
font-size: 0.875rem;
|
||||
transition-property: opacity, scale;
|
||||
transition-duration: 500ms;
|
||||
transition-delay: 100ms;
|
||||
transition-timing-function: linear(
|
||||
0,
|
||||
0.034 1.5%,
|
||||
0.763 9.7%,
|
||||
1.066 13.9%,
|
||||
1.198 19.9%,
|
||||
1.184 21.8%,
|
||||
0.963 37.5%,
|
||||
0.997 50.9%,
|
||||
1
|
||||
);
|
||||
|
||||
/* Simple, fast transition for reduced motion users */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition-duration: 100ms;
|
||||
transition-delay: 0ms;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-error[data-starting-style] .media-error__dialog,
|
||||
.media-default-skin .media-error[data-ending-style] .media-error__dialog {
|
||||
opacity: 0;
|
||||
scale: 0.5;
|
||||
}
|
||||
|
||||
.media-default-skin .media-error__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0.5rem 0.375rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.media-default-skin .media-error__title {
|
||||
@@ -74,3 +24,7 @@
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-error[data-open] ~ .media-controls * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,22 @@
|
||||
outline-color: oklch(from currentColor l c h / 0.25);
|
||||
outline-offset: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -4px;
|
||||
border-radius: inherit;
|
||||
box-shadow: 0 0 0 2px oklch(1 0 0);
|
||||
transition-property: opacity, scale;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
&:not(:focus-visible)::after {
|
||||
scale: 0.5;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-slider:active .media-slider__thumb,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@import "../../shared/css/video/icon-state.css";
|
||||
@import "../../shared/css/video/tooltip-state.css";
|
||||
@import "./components/reset.css";
|
||||
@import "./components/root.css";
|
||||
@import "./components/surface.css";
|
||||
@@ -16,6 +14,8 @@
|
||||
@import "./components/slider.css";
|
||||
@import "./components/popup.css";
|
||||
@import "./components/captions.css";
|
||||
@import "../../shared/css/video/icon-state.css";
|
||||
@import "../../shared/css/video/tooltip-state.css";
|
||||
|
||||
/* ==========================================================================
|
||||
Root
|
||||
@@ -67,6 +67,69 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Error Dialog
|
||||
========================================================================== */
|
||||
|
||||
.media-default-skin--video .media-error {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.media-default-skin--video .media-error__dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
max-width: 18rem;
|
||||
padding: 0.75rem;
|
||||
border-radius: 1.75rem;
|
||||
color: oklch(1 0 0);
|
||||
text-shadow: 0 1px 0 oklch(0 0 0 / 0.25);
|
||||
transition-property: opacity, scale;
|
||||
transition-duration: 500ms;
|
||||
transition-delay: 100ms;
|
||||
transition-timing-function: linear(
|
||||
0,
|
||||
0.034 1.5%,
|
||||
0.763 9.7%,
|
||||
1.066 13.9%,
|
||||
1.198 19.9%,
|
||||
1.184 21.8%,
|
||||
0.963 37.5%,
|
||||
0.997 50.9%,
|
||||
1
|
||||
);
|
||||
|
||||
/* Simple, fast transition for reduced motion users */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition-duration: 100ms;
|
||||
transition-delay: 0ms;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin .media-error[data-starting-style] .media-error__dialog,
|
||||
.media-default-skin .media-error[data-ending-style] .media-error__dialog {
|
||||
opacity: 0;
|
||||
scale: 0.5;
|
||||
}
|
||||
|
||||
.media-default-skin--video .media-error__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0.5rem 0.375rem;
|
||||
text-shadow: inherit;
|
||||
}
|
||||
|
||||
.media-default-skin--video .media-error__title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Controls (hide/show behavior)
|
||||
========================================================================== */
|
||||
@@ -111,6 +174,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.media-default-skin--video .media-error[data-open] ~ .media-controls {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide cursor when controls are hidden in fullscreen */
|
||||
@media (pointer: fine) {
|
||||
.media-default-skin--video:fullscreen:has(.media-controls:not([data-visible])) {
|
||||
|
||||
@@ -13,8 +13,8 @@ import { surface as baseSurface } from './components/surface';
|
||||
|
||||
export const root = cn(
|
||||
baseRoot,
|
||||
'[--media-controls-text-color:var(--media-color-primary,oklch(0_0_0))]',
|
||||
'dark:[--media-controls-text-color:var(--media-color-primary,oklch(1_0_0))]'
|
||||
'[--media-text-color:var(--media-color-primary,oklch(0_0_0))]',
|
||||
'dark:[--media-text-color:var(--media-color-primary,oklch(1_0_0))]'
|
||||
);
|
||||
|
||||
/* ==========================================================================
|
||||
@@ -39,7 +39,7 @@ export const surface = cn(
|
||||
Controls
|
||||
========================================================================== */
|
||||
|
||||
export const controls = cn(baseControls, surface, 'text-(--media-controls-text-color)');
|
||||
export const controls = cn(baseControls, surface, 'text-(--media-text-color)', 'peer-data-open/error:[&_*]:invisible');
|
||||
|
||||
/* ==========================================================================
|
||||
Sliders
|
||||
@@ -75,7 +75,16 @@ export const bufferingIndicator = {
|
||||
|
||||
export const error = {
|
||||
...baseError,
|
||||
dialog: cn(baseError.dialog, surface),
|
||||
dialog: cn(
|
||||
'absolute inset-0 z-20 flex items-center gap-3 rounded-full px-5 pr-0.5',
|
||||
'bg-(--media-surface-background-color) text-(--media-text-color)',
|
||||
'backdrop-blur-lg backdrop-saturate-150',
|
||||
'transition-[opacity,filter] duration-300 delay-100 ease-out',
|
||||
'group-data-starting-style/error:opacity-0 group-data-starting-style/error:blur-[4px]',
|
||||
'group-data-ending-style/error:opacity-0 group-data-ending-style/error:blur-[4px]',
|
||||
'motion-reduce:duration-100 motion-reduce:delay-0'
|
||||
),
|
||||
content: 'flex flex-1 items-center gap-2',
|
||||
};
|
||||
|
||||
/* ==========================================================================
|
||||
|
||||
@@ -2,21 +2,21 @@ import { cn } from '@videojs/utils/style';
|
||||
|
||||
export const button = {
|
||||
base: cn(
|
||||
'items-center justify-center shrink-0 border-none cursor-pointer select-none text-center touch-manipulation',
|
||||
'font-medium',
|
||||
'flex items-center justify-center shrink-0 border-none cursor-pointer select-none text-center touch-manipulation',
|
||||
'py-2 px-4 rounded-full',
|
||||
'outline-2 outline-transparent -outline-offset-2',
|
||||
'transition-[background-color,color,outline-offset,scale] duration-150 ease-out',
|
||||
'transition-[background-color,outline-offset,scale] duration-150 ease-out',
|
||||
'active:scale-[0.98]',
|
||||
'disabled:cursor-not-allowed disabled:opacity-50 disabled:grayscale',
|
||||
'focus-visible:outline-blue-500 focus-visible:outline-offset-2',
|
||||
'focus-visible:outline-current focus-visible:outline-offset-2',
|
||||
'data-[availability=unavailable]:hidden'
|
||||
),
|
||||
icon: cn(
|
||||
'grid w-[2.125rem] aspect-square bg-transparent rounded-full',
|
||||
'text-inherit text-shadow-inherit',
|
||||
primary: 'bg-white text-black font-medium text-center',
|
||||
subtle: cn(
|
||||
'bg-transparent text-inherit text-shadow-inherit',
|
||||
'hover:bg-current/10 hover:no-underline',
|
||||
'focus-visible:bg-current/10',
|
||||
'aria-expanded:bg-current/10',
|
||||
'active:scale-90'
|
||||
'aria-expanded:bg-current/10'
|
||||
),
|
||||
default: cn('flex py-2 px-4 bg-white rounded-full', 'text-black'),
|
||||
icon: cn('grid w-[2.125rem] aspect-square p-0', 'active:scale-90'),
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { cn } from '@videojs/utils/style';
|
||||
|
||||
export const error = {
|
||||
root: 'peer/error group/error flex absolute inset-0 z-20 items-center justify-center',
|
||||
root: 'peer/error group/error flex absolute inset-0 z-20 items-center justify-center outline-none',
|
||||
dialog: cn(
|
||||
'flex flex-col gap-3 max-w-72 p-3 rounded-[1.75rem] text-white text-sm',
|
||||
'flex flex-col gap-3 max-w-72 p-3 rounded-[1.75rem] text-white',
|
||||
// Animation
|
||||
'transition-[opacity,scale,transform] duration-500 delay-100',
|
||||
'ease-[linear(0,0.034_1.5%,0.763_9.7%,1.066_13.9%,1.198_19.9%,1.184_21.8%,0.963_37.5%,0.997_50.9%,1)]',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const seek = {
|
||||
button: '@max-md/media-controls:hidden',
|
||||
label: 'text-[0.75em] font-[480] tabular-nums',
|
||||
label: 'text-[10px] font-[480] tabular-nums',
|
||||
labelForward: 'absolute -right-px -bottom-0.75',
|
||||
labelBackward: 'absolute -left-px -bottom-0.75',
|
||||
};
|
||||
|
||||
@@ -87,6 +87,7 @@ export const controls = cn(
|
||||
// Position
|
||||
'absolute bottom-3 inset-x-3',
|
||||
'[color:var(--media-color-primary,oklch(1_0_0))] z-10',
|
||||
'peer-data-open/error:hidden',
|
||||
'ease-out origin-bottom',
|
||||
'duration-(--media-controls-transition-duration)',
|
||||
'delay-(--media-controls-transition-delay)',
|
||||
@@ -153,7 +154,9 @@ export const bufferingIndicator = {
|
||||
|
||||
export const error = {
|
||||
...baseError,
|
||||
dialog: cn(baseError.dialog, surface),
|
||||
dialog: cn(baseError.dialog, surface, 'text-shadow-[0_1px_0_oklch(0_0_0/0.25)]'),
|
||||
content: cn(baseError.content, 'text-shadow-inherit'),
|
||||
title: cn(baseError.title, 'text-base'),
|
||||
};
|
||||
|
||||
/* ==========================================================================
|
||||
|
||||
Reference in New Issue
Block a user