diff --git a/packages/react/src/presets/video/minimal-skin.css b/packages/react/src/presets/video/minimal-skin.css
index 97d5faf9..1ffe58bd 100644
--- a/packages/react/src/presets/video/minimal-skin.css
+++ b/packages/react/src/presets/video/minimal-skin.css
@@ -101,6 +101,7 @@
.media-minimal-skin .media-overlay {
position: absolute;
inset: 0;
+ z-index: 1;
border-radius: inherit;
background-image: linear-gradient(to top, oklch(0 0 0 / 0.7), oklch(0 0 0 / 0.5) 7.5rem, oklch(0 0 0 / 0));
backdrop-filter: blur(0) saturate(1.2) brightness(0.9);
@@ -451,10 +452,7 @@
overflow: hidden;
background-color: oklch(1 0 0 / 0.2);
border-radius: inherit;
- outline: 2px solid transparent;
- outline-offset: -2px;
box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);
- transition: outline-offset 150ms ease-out;
user-select: none;
}
.media-minimal-skin .media-slider__track[data-orientation="horizontal"] {
@@ -465,13 +463,13 @@
width: 0.1875rem;
height: 100%;
}
-.media-minimal-skin .media-slider:focus-visible .media-slider__track {
- outline-color: oklch(1 0 0);
- outline-offset: 6px;
-}
/* Thumb */
.media-minimal-skin .media-slider__thumb {
+ position: absolute;
+ top: 50%;
+ left: var(--media-slider-fill, 0%);
+ transform: translate(-50%, -50%);
z-index: 10;
width: 0.75rem;
height: 0.75rem;
@@ -484,32 +482,44 @@
opacity: 0;
scale: 0.7;
transform-origin: center;
- transition-property: opacity, scale;
+ transition-property: opacity, scale, outline-offset;
transition-duration: 150ms;
transition-timing-function: ease-out;
user-select: none;
+ outline: 2px solid transparent;
+ outline-offset: -2px;
+}
+.media-minimal-skin .media-slider__thumb:focus-visible {
+ outline-color: oklch(1 0 0);
+ outline-offset: 2px;
}
.media-minimal-skin .media-slider:hover .media-slider__thumb,
.media-minimal-skin .media-slider:focus-within .media-slider__thumb {
opacity: 1;
scale: 1;
}
-.media-minimal-skin .media-slider__track[data-orientation="horizontal"] .media-slider__thumb {
- cursor: ew-resize;
-}
-.media-minimal-skin .media-slider__track[data-orientation="vertical"] .media-slider__thumb {
- cursor: ns-resize;
-}
-/* Pointer (hidden in minimal skin) */
-.media-minimal-skin .media-slider__pointer {
- display: none;
-}
-
-/* Progress fill */
-.media-minimal-skin .media-slider__progress {
- background-color: oklch(1 0 0);
+/* Shared track fills */
+.media-minimal-skin .media-slider__buffer,
+.media-minimal-skin .media-slider__fill {
+ position: absolute;
+ inset-block: 0;
+ left: 0;
border-radius: inherit;
+ pointer-events: none;
+}
+
+/* Buffer */
+.media-minimal-skin .media-slider__buffer {
+ background-color: oklch(1 0 0 / 0.2);
+ width: var(--media-slider-buffer, 0%);
+ transition: width 0.25s ease-out;
+}
+
+/* Fill */
+.media-minimal-skin .media-slider__fill {
+ background-color: oklch(1 0 0);
+ width: var(--media-slider-fill, 0%);
}
/* Time display within slider */
diff --git a/packages/react/src/presets/video/minimal-skin.tailwind.tsx b/packages/react/src/presets/video/minimal-skin.tailwind.tsx
index 9608c618..550cbbf5 100644
--- a/packages/react/src/presets/video/minimal-skin.tailwind.tsx
+++ b/packages/react/src/presets/video/minimal-skin.tailwind.tsx
@@ -28,6 +28,7 @@ import { PlayButton } from '@/ui/play-button';
import { PlaybackRateButton } from '@/ui/playback-rate-button';
import { SeekButton } from '@/ui/seek-button';
import { Time } from '@/ui/time';
+import { TimeSlider } from '@/ui/time-slider';
import type { MinimalVideoSkinProps } from './minimal-skin';
const SEEK_TIME = 10;
@@ -293,8 +294,35 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod
/>
- {/* Temporary spacer */}
-
+
+
+
+
+
+
+
diff --git a/packages/react/src/presets/video/minimal-skin.tsx b/packages/react/src/presets/video/minimal-skin.tsx
index b38a4329..edb9120a 100644
--- a/packages/react/src/presets/video/minimal-skin.tsx
+++ b/packages/react/src/presets/video/minimal-skin.tsx
@@ -28,6 +28,7 @@ import { PlayButton } from '@/ui/play-button';
import { PlaybackRateButton } from '@/ui/playback-rate-button';
import { SeekButton } from '@/ui/seek-button';
import { Time } from '@/ui/time';
+import { TimeSlider } from '@/ui/time-slider';
import type { BaseSkinProps } from '../types';
const SEEK_TIME = 10;
@@ -159,8 +160,13 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode {
- {/* Temporary spacer */}
-
+
+
+
+
+
+
+
diff --git a/packages/react/src/presets/video/skin.css b/packages/react/src/presets/video/skin.css
index ac00e98f..76d86af4 100644
--- a/packages/react/src/presets/video/skin.css
+++ b/packages/react/src/presets/video/skin.css
@@ -104,6 +104,7 @@
.media-default-skin .media-overlay {
position: absolute;
inset: 0;
+ z-index: 1;
border-radius: inherit;
background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3), oklch(0 0 0 / 0));
backdrop-filter: blur(0) saturate(1.2) brightness(0.9);
@@ -465,10 +466,7 @@
overflow: hidden;
background-color: oklch(1 0 0 / 0.2);
border-radius: inherit;
- outline: 2px solid transparent;
- outline-offset: -2px;
box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05);
- transition: outline-offset 150ms ease-out;
user-select: none;
}
.media-default-skin .media-slider__track[data-orientation="horizontal"] {
@@ -479,14 +477,14 @@
width: 0.25rem;
height: 100%;
}
-.media-default-skin .media-slider:focus-visible .media-slider__track {
- outline-color: oklch(62.3% 0.214 259.815);
- outline-offset: 6px;
-}
/* Thumb */
.media-default-skin .media-slider__thumb {
z-index: 10;
+ position: absolute;
+ top: 50%;
+ left: var(--media-slider-fill);
+ transform: translate(-50%, -50%);
width: 0.625rem;
height: 0.625rem;
background-color: oklch(1 0 0);
@@ -496,36 +494,47 @@
0 1px 3px 0 oklch(0 0 0 / 0.15),
0 1px 2px -1px oklch(0 0 0 / 0.15);
opacity: 0;
- transition-property: opacity, height, width;
+ transition-property: opacity, height, width, outline-offset;
transition-duration: 150ms;
transition-timing-function: ease-out;
user-select: none;
+ outline: 2px solid transparent;
+ outline-offset: -2px;
}
-.media-default-skin .media-slider__thumb:active {
+.media-default-skin .media-slider__thumb:focus-visible {
+ outline-color: oklch(62.3% 0.214 259.815);
+ outline-offset: 2px;
+}
+.media-default-skin .media-slider:active .media-slider__thumb {
width: 0.75rem;
height: 0.75rem;
}
.media-default-skin .media-slider:hover .media-slider__thumb,
-.media-default-skin .media-slider:focus-within .media-slider__thumb {
+.media-default-skin .media-slider__thumb:focus-visible {
opacity: 1;
}
-.media-default-skin .media-slider__track[data-orientation="horizontal"] .media-slider__thumb {
- cursor: ew-resize;
-}
-.media-default-skin .media-slider__track[data-orientation="vertical"] .media-slider__thumb {
- cursor: ns-resize;
+
+/* Shared track fills */
+.media-default-skin .media-slider__buffer,
+.media-default-skin .media-slider__fill {
+ position: absolute;
+ inset-block: 0;
+ left: 0;
+ border-radius: inherit;
+ pointer-events: none;
}
-/* Pointer (hover preview) */
-.media-default-skin .media-slider__pointer {
+/* Buffer */
+.media-default-skin .media-slider__buffer {
background-color: oklch(1 0 0 / 0.2);
- border-radius: inherit;
+ width: var(--media-slider-buffer);
+ transition: width 0.25s ease-out;
}
-/* Progress fill */
-.media-default-skin .media-slider__progress {
+/* Fill */
+.media-default-skin .media-slider__fill {
background-color: oklch(1 0 0);
- border-radius: inherit;
+ width: var(--media-slider-fill);
}
/* Time display within slider */
diff --git a/packages/react/src/presets/video/skin.tailwind.tsx b/packages/react/src/presets/video/skin.tailwind.tsx
index 0d3eb12f..776204a6 100644
--- a/packages/react/src/presets/video/skin.tailwind.tsx
+++ b/packages/react/src/presets/video/skin.tailwind.tsx
@@ -28,6 +28,7 @@ import { PlayButton } from '@/ui/play-button';
import { PlaybackRateButton } from '@/ui/playback-rate-button';
import { SeekButton } from '@/ui/seek-button';
import { Time } from '@/ui/time';
+import { TimeSlider } from '@/ui/time-slider';
import type { VideoSkinProps } from './skin';
const SEEK_TIME = 10;
@@ -300,8 +301,35 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode {
type="current"
className="hidden @2xs/media-time:block text-shadow-2xs text-shadow-black/25 tabular-nums"
/>
- {/* Temporary spacer */}
-
+
+
+
+
+
+
+
diff --git a/packages/react/src/presets/video/skin.tsx b/packages/react/src/presets/video/skin.tsx
index 8b286752..c2ddb470 100644
--- a/packages/react/src/presets/video/skin.tsx
+++ b/packages/react/src/presets/video/skin.tsx
@@ -28,6 +28,7 @@ import { PlayButton } from '@/ui/play-button';
import { PlaybackRateButton } from '@/ui/playback-rate-button';
import { SeekButton } from '@/ui/seek-button';
import { Time } from '@/ui/time';
+import { TimeSlider } from '@/ui/time-slider';
import type { BaseSkinProps } from '../types';
const SEEK_TIME = 10;
@@ -154,8 +155,13 @@ export function VideoSkin(props: VideoSkinProps): ReactNode {
- {/* Temporary spacer */}
-
+
+
+
+
+
+
+