-
+
+
-
+
-
`;
diff --git a/packages/html/package.json b/packages/html/package.json
index e241579d..8708239f 100644
--- a/packages/html/package.json
+++ b/packages/html/package.json
@@ -25,9 +25,13 @@
"types": "./dist/icons.d.ts",
"default": "./dist/icons.js"
},
- "./skins/default": {
- "types": "./dist/skins/default.d.ts",
- "default": "./dist/skins/default.js"
+ "./skins/frosted": {
+ "types": "./dist/skins/frosted.d.ts",
+ "default": "./dist/skins/frosted.js"
+ },
+ "./skins/minimal": {
+ "types": "./dist/skins/minimal.d.ts",
+ "default": "./dist/skins/minimal.js"
}
},
"main": "dist/index.js",
diff --git a/packages/html/src/components/media-popover.ts b/packages/html/src/components/media-popover.ts
index 56b2c355..6a5f5156 100644
--- a/packages/html/src/components/media-popover.ts
+++ b/packages/html/src/components/media-popover.ts
@@ -288,7 +288,7 @@ export class MediaPopoverPortal extends HTMLElement {
if (!portalId) return;
/* @TODO We need to make sure portal logic is non-brittle longer term (CJP) */
- // NOTE: Hacky solution in part to ensure styling propogates from skin to container's baked in portal (TL;DR - Shadow DOM vs. Light DOM CSS) (CJP)
+ // NOTE: Hacky solution in part to ensure styling propagates from skin to container's baked in portal (TL;DR - Shadow DOM vs. Light DOM CSS) (CJP)
const portalContainer
= ((this.getRootNode() as ShadowRoot | Document).getElementById(portalId)
?? (this.getRootNode() as ShadowRoot | Document)
diff --git a/packages/html/src/skins/default/index.ts b/packages/html/src/skins/default/index.ts
deleted file mode 100644
index dea96aaa..00000000
--- a/packages/html/src/skins/default/index.ts
+++ /dev/null
@@ -1,390 +0,0 @@
-import { MediaSkin } from '@/media/media-skin';
-import '@/media/media-container';
-import '@/media/media-provider';
-import '@/components/media-play-button';
-import '@/components/media-mute-button';
-import '@/components/media-volume-slider';
-import '@/components/media-time-slider';
-import '@/components/media-fullscreen-button';
-import '@/components/media-duration-display';
-import '@/components/media-current-time-display';
-import '@/components/media-preview-time-display';
-import '@/components/media-popover';
-import '@/components/media-tooltip';
-import '@/icons';
-
-export function getTemplateHTML() {
- return /* html */`
- ${MediaSkin.getTemplateHTML()}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Play
- Pause
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Enter Fullscreen
- Exit Fullscreen
-
-
-
-
-
-
- `;
-}
-
-export class MediaSkinDefault extends MediaSkin {
- static getTemplateHTML: () => string = getTemplateHTML;
-}
-
-customElements.define('media-skin-default', MediaSkinDefault);
diff --git a/packages/html/src/skins/frosted/index.ts b/packages/html/src/skins/frosted/index.ts
new file mode 100644
index 00000000..7529c3f6
--- /dev/null
+++ b/packages/html/src/skins/frosted/index.ts
@@ -0,0 +1,119 @@
+import { MediaSkin } from '@/media/media-skin';
+import styles from './styles.css';
+import '@/media/media-container';
+import '@/media/media-provider';
+import '@/components/media-play-button';
+import '@/components/media-mute-button';
+import '@/components/media-volume-slider';
+import '@/components/media-time-slider';
+import '@/components/media-fullscreen-button';
+import '@/components/media-duration-display';
+import '@/components/media-current-time-display';
+import '@/components/media-preview-time-display';
+import '@/components/media-popover';
+import '@/components/media-tooltip';
+
+import '@/icons';
+
+export function getTemplateHTML() {
+ return /* html */`
+ ${MediaSkin.getTemplateHTML()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+}
+
+export class MediaSkinFrosted extends MediaSkin {
+ static getTemplateHTML: () => string = getTemplateHTML;
+}
+
+customElements.define('media-skin-frosted', MediaSkinFrosted);
diff --git a/packages/html/src/skins/frosted/styles.css b/packages/html/src/skins/frosted/styles.css
new file mode 100644
index 00000000..c79b5651
--- /dev/null
+++ b/packages/html/src/skins/frosted/styles.css
@@ -0,0 +1,351 @@
+media-container * {
+ box-sizing: border-box;
+}
+
+media-container {
+ position: relative;
+ isolation: isolate;
+ container: root / inline-size;
+ overflow: clip;
+ font-size: 0.8125rem;
+ line-height: 1.5;
+ border-radius: inherit;
+}
+media-container::before,
+media-container::after {
+ content: '';
+ position: absolute;
+ pointer-events: none;
+ border-radius: inherit;
+ z-index: 10;
+}
+media-container::before {
+ inset: 1px;
+ box-shadow: inset 0 0 0 1px oklab(1 0 0 / 0.15);
+}
+media-container::after {
+ inset: 0;
+ box-shadow: inset 0 0 0 1px oklab(0 0 0 / 0.1);
+}
+
+/* Fullscreen */
+media-container:fullscreen {
+ border-radius: 0;
+}
+media-container:fullscreen video {
+ height: 100%;
+ width: 100%;
+}
+
+media-container > ::slotted([slot='media']) {
+ display: block;
+ width: 100%;
+ height: 100%;
+}
+
+/* Media Container UI Overlay Styling */
+media-container > .overlay {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: start;
+ pointer-events: none;
+ background-image: linear-gradient(to top, oklab(0 0 0 / 0.5), oklab(0 0 0 / 0.3), rgba(0, 0, 0, 0));
+ backdrop-filter: saturate(1.5) brightness(0.9);
+ transition: opacity 0.15s ease-out;
+ transition-delay: 500ms;
+ opacity: 0;
+}
+media-container:hover > .overlay,
+media-container:has([data-paused]) > .overlay,
+media-container:has([aria-expanded='true']) > .overlay {
+ opacity: 1;
+ transition-delay: 0ms;
+}
+
+/* Common Surface Styles - e.g. tooltips, popovers, controls */
+.surface {
+ background-color: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(64px) brightness(0.9) saturate(1.5);
+ box-shadow:
+ inset 0 0 0 1px oklab(1 0 0 / 0.15),
+ 0 0 0 1px oklab(0 0 0 / 0.15),
+ oklab(0 0 0 / 0.15) 0px 1px 3px 0px,
+ oklab(0 0 0 / 0.15) 0px 1px 2px -1px;
+}
+@media (prefers-reduced-transparency: reduce) {
+ .surface {
+ background-color: oklab(0 0 0 / 0.7);
+ box-shadow:
+ inset 0 0 0 1px oklab(0 0 0),
+ 0 0 0 1px oklab(1 0 0 / 0.2);
+ }
+}
+@media (prefers-contrast: more) {
+ .surface {
+ background-color: oklab(0 0 0 / 0.9);
+ box-shadow:
+ inset 0 0 0 1px oklab(0 0 0),
+ 0 0 0 1px oklab(1 0 0 / 0.2);
+ }
+}
+
+/* Media Control Bar UI/Styles */
+.control-bar {
+ position: absolute;
+ bottom: 0.75rem;
+ inset-inline: 0.75rem;
+ padding: 0.25rem;
+ display: flex;
+ align-items: center;
+ gap: 0.125rem;
+ border-radius: calc(infinity * 1px);
+ will-change: scale, transform, filter, opacity;
+ scale: 0.9;
+ opacity: 0;
+ filter: blur(8px);
+ transition-property: scale, transform, filter, opacity;
+ transition-delay: 500ms;
+ transition-duration: 300ms;
+ transition-timing-function: ease-out;
+ transform-origin: bottom;
+ color: oklab(1 0 0);
+}
+media-container:hover > .control-bar,
+media-container:has([data-paused]) > .control-bar,
+media-container:has([aria-expanded='true']) > .control-bar {
+ opacity: 1;
+ scale: 1;
+ filter: blur(0px);
+ transition-delay: 0ms;
+ transition-duration: 100ms;
+}
+
+/* Time Display Styling */
+.time-controls {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ gap: 0.75rem;
+ padding-inline: 0.375rem;
+}
+media-current-time-display,
+media-duration-display {
+ text-shadow: 0 1px 0 oklab(0 0 0 / 0.25);
+ font-variant-numeric: tabular-nums;
+}
+
+/* Generic Media Button Styling */
+.button {
+ display: grid;
+ flex-shrink: 0;
+ padding: 0.5rem;
+ cursor: pointer;
+ background: transparent;
+ border: none;
+ border-radius: calc(infinity * 1px);
+ color: oklab(1 0 0 / 0.9);
+ user-select: none;
+ outline: 2px solid transparent;
+ outline-offset: -2px;
+ transition-property: background-color, color, outline-offset;
+ transition-duration: 150ms;
+ transition-timing-function: ease-out;
+}
+.button:hover,
+.button:focus-visible,
+.button[aria-expanded='true'] {
+ background-color: oklab(1 0 0 / 0.1);
+ color: oklab(1 0 0);
+ text-decoration: none;
+}
+.button:focus-visible {
+ outline-color: oklch(62.3% 0.214 259.815);
+ outline-offset: 2px;
+}
+.button[disabled] {
+ cursor: not-allowed;
+ opacity: 0.5;
+ filter: grayscale(1);
+}
+
+.button .icon {
+ grid-area: 1 / 1;
+ width: 18px;
+ height: 18px;
+ filter: drop-shadow(0 1px 0 oklab(0 0 0 / 0.25));
+}
+
+/* Media Play Button UI/Styles */
+media-play-button .icon {
+ opacity: 0;
+ transition: opacity 150ms linear;
+}
+
+media-play-button:not([data-paused]) .pause-icon,
+media-play-button[data-paused] .play-icon {
+ opacity: 1;
+}
+
+/* Media Fullscreen Button UI/Styles */
+media-fullscreen-button .icon {
+ display: none;
+}
+media-fullscreen-button:not([data-fullscreen]) .fullscreen-enter-icon,
+media-fullscreen-button[data-fullscreen] .fullscreen-exit-icon {
+ display: inline;
+}
+
+/* One way to define the "default visible" icon (CJP) */
+media-mute-button .icon {
+ display: none;
+}
+media-mute-button:not([data-volume-level]) .volume-low-icon,
+media-mute-button[data-volume-level='high'] .volume-high-icon,
+media-mute-button[data-volume-level='low'] .volume-low-icon,
+media-mute-button[data-volume-level='medium'] .volume-low-icon,
+media-mute-button[data-volume-level='off'] .volume-off-icon {
+ display: inline;
+}
+
+/* TimeSlider Component Styles */
+.slider-root {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ border-radius: calc(infinity * 1px);
+ outline: none;
+}
+
+/* Horizontal orientation styles */
+.slider-root[data-orientation='horizontal'] {
+ min-width: 80px;
+ width: 100%;
+ height: 20px;
+}
+
+/* Vertical orientation styles */
+.slider-root[data-orientation='vertical'] {
+ height: 80px;
+ width: 20px;
+}
+
+.slider-track {
+ position: relative;
+ isolation: isolate;
+ background-color: oklab(1 0 0 / 0.2);
+ border-radius: inherit;
+ overflow: hidden;
+ user-select: none;
+ outline: 2px solid transparent;
+ outline-offset: -2px;
+ transition: outline-offset 150ms ease-out;
+ box-shadow: 0 0 0 1px oklab(0 0 0 / 0.05);
+}
+
+/* Horizontal track styles */
+.slider-track[data-orientation='horizontal'] {
+ width: 100%;
+ height: 0.25rem;
+}
+
+/* Vertical track styles */
+.slider-track[data-orientation='vertical'] {
+ width: 0.25rem;
+ height: 100%;
+}
+
+.slider-root:focus-visible .slider-track {
+ outline-color: oklch(62.3% 0.214 259.815);
+ outline-offset: 6px;
+}
+
+.slider-thumb {
+ width: 0.625rem;
+ height: 0.625rem;
+ background-color: oklab(1 0 0);
+ border-radius: calc(infinity * 1px);
+ user-select: none;
+ z-index: 10;
+ box-shadow:
+ 0 0 0 1px oklab(0 0 0 / 0.1),
+ 0 1px 3px 0 oklab(0 0 0 / 0.15),
+ 0 1px 2px -1px oklab(0 0 0 / 0.15);
+ opacity: 0;
+ transition-property: opacity, height, width;
+ transition-duration: 150ms;
+ transition-timing-function: ease-in-out;
+}
+.slider-thumb:active {
+ width: 0.75rem;
+ height: 0.75rem;
+}
+.slider-root:hover .slider-thumb,
+.slider-root:focus-within .slider-thumb {
+ opacity: 1;
+}
+.slider-track[data-orientation='horizontal'] .slider-thumb {
+ cursor: ew-resize;
+}
+.slider-track[data-orientation='vertical'] .slider-thumb {
+ cursor: ns-resize;
+}
+
+.slider-pointer {
+ background-color: oklab(1 0 0 / 0.2);
+ border-radius: inherit;
+}
+
+.slider-progress {
+ background-color: oklab(1 0 0);
+ border-radius: inherit;
+}
+
+.popup-animation {
+ transition-property: transform, scale, opacity, filter;
+ transition-duration: 200ms;
+ transform: scale(1);
+ transform-origin: bottom;
+ opacity: 1;
+ filter: blur(0px);
+}
+.popup-animation[data-starting-style],
+.popup-animation[data-ending-style] {
+ transform: scale(0);
+ opacity: 0;
+ filter: blur(8px);
+}
+.popup-animation[data-instant] {
+ transition-duration: 0ms;
+}
+
+media-popover-popup {
+ padding: 0.75rem 0.25rem;
+ border-radius: calc(infinity * 1px);
+}
+
+/* Tooltip Component Styles */
+media-tooltip-popup {
+ color: oklab(1 0 0);
+ padding: 0.25rem 0.625rem;
+ border-radius: calc(infinity * 1px);
+ font-size: 0.75rem;
+}
+
+.tooltip {
+ display: none;
+ white-space: nowrap;
+}
+
+media-tooltip-popup[data-paused] .play-tooltip,
+media-tooltip-popup:not([data-paused]) .pause-tooltip {
+ display: block;
+}
+
+media-tooltip-popup[data-fullscreen] .fullscreen-exit-tooltip,
+media-tooltip-popup:not([data-fullscreen]) .fullscreen-enter-tooltip {
+ display: block;
+}
diff --git a/packages/html/src/skins/minimal/index.ts b/packages/html/src/skins/minimal/index.ts
new file mode 100644
index 00000000..e06afd25
--- /dev/null
+++ b/packages/html/src/skins/minimal/index.ts
@@ -0,0 +1,26 @@
+import { MediaSkin } from '@/media/media-skin';
+import '@/media/media-container';
+import '@/media/media-provider';
+import '@/components/media-play-button';
+import '@/components/media-mute-button';
+import '@/components/media-volume-slider';
+import '@/components/media-time-slider';
+import '@/components/media-fullscreen-button';
+import '@/components/media-duration-display';
+import '@/components/media-current-time-display';
+import '@/components/media-preview-time-display';
+import '@/components/media-popover';
+import '@/components/media-tooltip';
+import '@/icons';
+
+export function getTemplateHTML() {
+ return /* html */`
+ ${MediaSkin.getTemplateHTML()}
+ `;
+}
+
+export class MediaSkinMinimal extends MediaSkin {
+ static getTemplateHTML: () => string = getTemplateHTML;
+}
+
+customElements.define('media-skin-minimal', MediaSkinMinimal);
diff --git a/packages/html/src/skins/minimal/styles.css b/packages/html/src/skins/minimal/styles.css
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/html/src/types.d.ts b/packages/html/src/types.d.ts
new file mode 100644
index 00000000..31f07ea5
--- /dev/null
+++ b/packages/html/src/types.d.ts
@@ -0,0 +1,4 @@
+declare module '*.css' {
+ const content: string;
+ export default content;
+}
diff --git a/packages/html/tsdown.config.ts b/packages/html/tsdown.config.ts
index 207ddca0..b0b53557 100644
--- a/packages/html/tsdown.config.ts
+++ b/packages/html/tsdown.config.ts
@@ -5,7 +5,8 @@ export default defineConfig({
index: './src/index.ts',
store: './src/store/index.ts',
icons: './src/icons/index.ts',
- 'skins/default': './src/skins/default/index.ts',
+ 'skins/frosted': './src/skins/frosted/index.ts',
+ 'skins/minimal': './src/skins/minimal/index.ts',
},
platform: 'browser',
format: 'es',
@@ -19,5 +20,6 @@ export default defineConfig({
},
loader: {
'.svg': 'text',
+ '.css': 'text',
},
});
diff --git a/packages/react/src/skins/frosted/styles.ts b/packages/react/src/skins/frosted/styles.ts
index 66a5ba29..49f36e32 100644
--- a/packages/react/src/skins/frosted/styles.ts
+++ b/packages/react/src/skins/frosted/styles.ts
@@ -46,18 +46,18 @@ const styles: FrostedSkinStyles = {
Controls: cn(
'vjs:@container/controls vjs:absolute vjs:inset-x-3 vjs:bottom-3 vjs:rounded-full vjs:flex vjs:items-center vjs:p-1 vjs:gap-0.5 vjs:text-white',
// Animation
- 'vjs:transition vjs:will-change-transform vjs:origin-bottom vjs:ease-out',
+ 'vjs:transition vjs:will-change-[transform,scale,filter,opacity] vjs:origin-bottom vjs:ease-out',
// FIXME: Temporary className hook for above logic in the overlay. Can be removed once have a proper way to handle controls visibility.
'controls',
// FIXME: Temporary hide/show logic
- 'vjs:scale-90 vjs:opacity-0 vjs:delay-500 vjs:duration-300',
- 'vjs:has-[[data-paused]]:scale-100 vjs:has-[[data-paused]]:opacity-100 vjs:has-[[data-paused]]:delay-0',
- 'vjs:has-[[aria-expanded="true"]]:scale-100 vjs:has-[[aria-expanded="true"]]:opacity-100 vjs:has-[[aria-expanded="true"]]:delay-0',
- 'vjs:group-hover/root:scale-100 vjs:group-hover/root:opacity-100 vjs:group-hover/root:delay-0',
+ 'vjs:scale-90 vjs:opacity-0 vjs:blur-sm vjs:delay-500 vjs:duration-300',
+ 'vjs:has-[[data-paused]]:scale-100 vjs:has-[[data-paused]]:opacity-100 vjs:has-[[data-paused]]:blur-none vjs:has-[[data-paused]]:delay-0 vjs:has-[[data-paused]]:duration-100',
+ 'vjs:has-[[aria-expanded="true"]]:scale-100 vjs:has-[[aria-expanded="true"]]:opacity-100 vjs:has-[[aria-expanded="true"]]:blur-none vjs:has-[[aria-expanded="true"]]:delay-0 vjs:has-[[aria-expanded="true"]]:duration-100',
+ 'vjs:group-hover/root:scale-100 vjs:group-hover/root:opacity-100 vjs:group-hover/root:blur-none vjs:group-hover/root:delay-0 vjs:group-hover/root:duration-100',
),
Icon: cn('icon'),
Button: cn(
- 'vjs:group/button vjs:cursor-pointer vjs:relative vjs:shrink-0 vjs:transition vjs:select-none vjs:p-2 vjs:rounded-full',
+ 'vjs:group/button vjs:cursor-pointer vjs:relative vjs:shrink-0 vjs:transition-[color,background,outline-offset] vjs:select-none vjs:p-2 vjs:rounded-full',
// Background/foreground
'vjs:bg-transparent vjs:text-white/90',
// Hover and focus states
@@ -65,21 +65,19 @@ const styles: FrostedSkinStyles = {
// Focus state
'vjs:-outline-offset-2 vjs:focus-visible:outline-2 vjs:focus-visible:outline-offset-2 vjs:focus-visible:outline-blue-500',
// Disabled state
- 'vjs:aria-disabled:grayscale vjs:aria-disabled:opacity-50 vjs:aria-disabled:cursor-not-allowed',
+ 'vjs:disabled:grayscale vjs:disabled:opacity-50 vjs:disabled:cursor-not-allowed',
// Loading state
'vjs:aria-busy:pointer-events-none vjs:aria-busy:cursor-not-allowed',
// Expanded state
'vjs:aria-expanded:bg-white/10 vjs:aria-expanded:text-white',
- // Pressed state
- 'vjs:active:scale-95',
),
IconButton: cn(
'vjs:grid vjs:[&_.icon]:[grid-area:1/1]',
- 'vjs:[&_.icon]:shrink-0 vjs:[&_.icon]:transition-[opacity,filter] vjs:[&_.icon]:duration-500 vjs:[&_.icon]:linear vjs:[&_.icon]:drop-shadow-[0_1px_0_var(--tw-shadow-color)] vjs:[&_.icon]:shadow-black/25',
+ 'vjs:[&_.icon]:shrink-0 vjs:[&_.icon]:transition-opacity vjs:[&_.icon]:duration-150 vjs:[&_.icon]:ease-linear vjs:[&_.icon]:drop-shadow-[0_1px_0_var(--tw-shadow-color)] vjs:[&_.icon]:shadow-black/25',
),
PlayButton: cn(
- 'vjs:[&_.pause-icon]:opacity-100 vjs:[&[data-paused]_.pause-icon]:opacity-0 vjs:[&[data-paused]_.pause-icon]:blur-sm',
- 'vjs:[&_.play-icon]:opacity-0 vjs:[&_.play-icon]:blur-sm vjs:[&[data-paused]_.play-icon]:opacity-100 vjs:[&[data-paused]_.play-icon]:blur-none',
+ 'vjs:[&_.pause-icon]:opacity-100 vjs:[&[data-paused]_.pause-icon]:opacity-0',
+ 'vjs:[&_.play-icon]:opacity-0 vjs:[&[data-paused]_.play-icon]:opacity-100',
),
PlayIcon: cn('play-icon'),
PauseIcon: cn('pause-icon'),
@@ -132,10 +130,10 @@ const styles: FrostedSkinStyles = {
'vjs:[&[data-orientation="vertical"]]:w-5 vjs:[&[data-orientation="vertical"]]:h-20',
),
SliderTrack: cn(
- 'vjs:-outline-offset-2 vjs:group-focus-visible/slider-root:outline-2 vjs:group-focus-visible/slider-root:outline-offset-2 vjs:group-focus-visible/slider-root:outline-blue-500',
- 'vjs:w-full vjs:relative vjs:select-none vjs:rounded-full vjs:bg-white/20 vjs:ring-1 vjs:ring-black/5',
- 'vjs:[&[data-orientation="horizontal"]]:h-1',
+ 'vjs:relative vjs:select-none vjs:transition-[outline-offset] vjs:rounded-[inherit] vjs:bg-white/20 vjs:ring-1 vjs:ring-black/5',
+ 'vjs:[&[data-orientation="horizontal"]]:w-full vjs:[&[data-orientation="horizontal"]]:h-1',
'vjs:[&[data-orientation="vertical"]]:w-1',
+ 'vjs:-outline-offset-2 vjs:group-focus-visible/slider-root:outline-2 vjs:group-focus-visible/slider-root:outline-offset-6 vjs:group-focus-visible/slider-root:outline-blue-500',
),
SliderProgress: cn('vjs:bg-white vjs:rounded-[inherit]'),
// TODO: Work out what we want to do here.
@@ -143,7 +141,6 @@ const styles: FrostedSkinStyles = {
SliderThumb: cn(
'vjs:bg-white vjs:z-10 vjs:select-none vjs:ring vjs:ring-black/10 vjs:rounded-full vjs:shadow-sm vjs:shadow-black/15',
'vjs:opacity-0 vjs:transition-[opacity,height,width] vjs:ease-in-out',
- 'vjs:-outline-offset-2 vjs:focus-visible:outline-2 vjs:focus-visible:outline-offset-2 vjs:focus-visible:outline-blue-500',
'vjs:group-hover/slider:opacity-100 vjs:group-focus-within/slider:opacity-100',
'vjs:size-2.5 vjs:active:size-3 vjs:group-active/slider:size-3',
'vjs:[&[data-orientation="horizontal"]]:hover:cursor-ew-resize',
@@ -160,7 +157,7 @@ const styles: FrostedSkinStyles = {
'vjs:relative vjs:px-1 vjs:py-3 vjs:rounded-full',
),
TooltipPopup: cn(
- 'vjs:whitespace-nowrap vjs:flex vjs:flex-col vjs:rounded-full vjs:text-white vjs:text-xs vjs:@7xl/root:text-sm vjs:px-2.5 vjs:py-1',
+ 'vjs:whitespace-nowrap vjs:rounded-full vjs:text-white vjs:text-xs vjs:@7xl/root:text-sm vjs:px-2.5 vjs:py-1',
),
};
diff --git a/packages/react/src/skins/minimal/styles.ts b/packages/react/src/skins/minimal/styles.ts
index 1fc91285..fa165051 100644
--- a/packages/react/src/skins/minimal/styles.ts
+++ b/packages/react/src/skins/minimal/styles.ts
@@ -46,7 +46,7 @@ const styles: MinimalSkinStyles = {
),
Icon: cn('icon'),
Button: cn(
- 'vjs:group/button vjs:cursor-pointer vjs:relative vjs:shrink-0 vjs:transition vjs:select-none vjs:p-2.5 vjs:rounded-md',
+ 'vjs:group/button vjs:cursor-pointer vjs:relative vjs:shrink-0 vjs:transition-[color,background,outline-offset] vjs:select-none vjs:p-2.5 vjs:rounded-md',
// Background/foreground
'vjs:bg-transparent vjs:text-white',
// Hover and focus states
@@ -54,7 +54,7 @@ const styles: MinimalSkinStyles = {
// Focus state
'vjs:-outline-offset-2 vjs:focus-visible:outline-2 vjs:focus-visible:outline-offset-2 vjs:focus-visible:outline-white',
// Disabled state
- 'vjs:aria-disabled:grayscale vjs:aria-disabled:opacity-50 vjs:aria-disabled:cursor-not-allowed',
+ 'vjs:disabled:grayscale vjs:disabled:opacity-50 vjs:disabled:cursor-not-allowed',
// Loading state
'vjs:aria-busy:pointer-events-none vjs:aria-busy:cursor-not-allowed',
// Expanded state
@@ -63,11 +63,11 @@ const styles: MinimalSkinStyles = {
ButtonGroup: cn('vjs:flex vjs:items-center vjs:gap-1.5'),
IconButton: cn(
'vjs:grid vjs:[&_.icon]:[grid-area:1/1]',
- 'vjs:[&_.icon]:shrink-0 vjs:[&_.icon]:transition-[opacity,filter] vjs:[&_.icon]:duration-300 vjs:[&_.icon]:linear vjs:[&_.icon]:drop-shadow-[0_1px_0_var(--tw-shadow-color)] vjs:[&_.icon]:shadow-black/40',
+ 'vjs:[&_.icon]:shrink-0 vjs:[&_.icon]:transition-opacity vjs:[&_.icon]:duration-150 vjs:[&_.icon]:ease-linear vjs:[&_.icon]:drop-shadow-[0_1px_0_var(--tw-shadow-color)] vjs:[&_.icon]:shadow-black/40',
),
PlayButton: cn(
- 'vjs:[&_.pause-icon]:opacity-100 vjs:[&_.pause-icon]:blur-none vjs:[&[data-paused]_.pause-icon]:opacity-0 vjs:[&[data-paused]_.pause-icon]:blur-xs',
- 'vjs:[&_.play-icon]:opacity-0 vjs:[&_.play-icon]:blur-xs vjs:[&[data-paused]_.play-icon]:opacity-100 vjs:[&[data-paused]_.play-icon]:blur-none',
+ 'vjs:[&_.pause-icon]:opacity-100 vjs:[&[data-paused]_.pause-icon]:opacity-0',
+ 'vjs:[&_.play-icon]:opacity-0 vjs:[&[data-paused]_.play-icon]:opacity-100',
),
PlayIcon: cn('play-icon'),
PauseIcon: cn('pause-icon'),
@@ -114,23 +114,21 @@ const styles: MinimalSkinStyles = {
TimeDisplay: cn('vjs:tabular-nums vjs:text-shadow-2xs/20'),
DurationDisplay: cn('vjs:text-white/50 vjs:contents'),
SliderRoot: cn(
- 'vjs:flex vjs:items-center vjs:justify-center vjs:flex-1 vjs:group/slider vjs:relative vjs:rounded-sm',
+ 'vjs:flex vjs:items-center vjs:justify-center vjs:flex-1 vjs:group/slider vjs:relative vjs:rounded-full',
'vjs:[&[data-orientation="horizontal"]]:h-5 vjs:[&[data-orientation="horizontal"]]:min-w-20',
'vjs:[&[data-orientation="vertical"]]:w-5 vjs:[&[data-orientation="vertical"]]:h-18',
- // Focus state
- 'vjs:-outline-offset-8 vjs:focus-visible:outline-2 vjs:focus-visible:outline-offset-8 vjs:focus-visible:outline-white',
),
SliderTrack: cn(
- 'vjs:relative vjs:select-none vjs:rounded-full vjs:bg-white/10 vjs:transition-[height,width] vjs:ease-in-out',
+ 'vjs:relative vjs:select-none vjs:rounded-[inherit] vjs:bg-white/10',
'vjs:[&[data-orientation="horizontal"]]:w-full vjs:[&[data-orientation="horizontal"]]:h-[0.1875rem]',
'vjs:[&[data-orientation="vertical"]]:w-[0.1875rem]',
+ 'vjs:-outline-offset-2 vjs:group-focus-visible/slider-root:outline-2 vjs:group-focus-visible/slider-root:outline-offset-2 vjs:group-focus-visible/slider-root:outline-white',
),
SliderProgress: cn('vjs:bg-white vjs:rounded-[inherit]'),
SliderPointer: cn('vjs:hidden'),
SliderThumb: cn(
'vjs:opacity-0 vjs:scale-70 vjs:group-hover/slider:opacity-100 vjs:group-hover/slider:scale-100 vjs:focus-visible:opacity-100 vjs:focus-visible:scale-100',
'vjs:bg-white vjs:z-10 vjs:size-3 vjs:select-none vjs:ring vjs:ring-black/10 vjs:rounded-full vjs:shadow-sm vjs:shadow-black/15 vjs:transition-[opacity,scale] vjs:ease-out',
- 'vjs:-outline-offset-2 vjs:focus-visible:outline-2 vjs:focus-visible:outline-offset-2 vjs:focus-visible:outline-amber-500',
'vjs:[&[data-orientation="horizontal"]]:hover:cursor-ew-resize',
'vjs:[&[data-orientation="vertical"]]:hover:cursor-ns-resize',
),