mirror of
https://github.com/sussy-code/smov.git
synced 2025-01-01 16:37:39 +01:00
Add popup close keyboard shortcut, more tabbable styles
This commit is contained in:
parent
d3184113cc
commit
ab167d565a
11 changed files with 32 additions and 20 deletions
|
@ -6,7 +6,7 @@ export function Toggle(props: { onClick: () => void; enabled?: boolean }) {
|
||||||
type="button"
|
type="button"
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"w-11 h-6 p-1 rounded-full grid transition-colors duration-100 group/toggle",
|
"w-11 h-6 p-1 rounded-full grid transition-colors duration-100 group/toggle tabbable",
|
||||||
props.enabled ? "bg-buttons-toggle" : "bg-buttons-toggleDisabled"
|
props.enabled ? "bg-buttons-toggle" : "bg-buttons-toggleDisabled"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import c from "classnames";
|
import classNames from "classnames";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ function MediaCardContent({
|
||||||
flareSize={300}
|
flareSize={300}
|
||||||
cssColorVar="--colors-mediaCard-hoverAccent"
|
cssColorVar="--colors-mediaCard-hoverAccent"
|
||||||
backgroundClass="bg-mediaCard-hoverBackground duration-100"
|
backgroundClass="bg-mediaCard-hoverBackground duration-100"
|
||||||
className={c({
|
className={classNames({
|
||||||
"rounded-xl bg-background-main group-hover:opacity-100": canLink,
|
"rounded-xl bg-background-main group-hover:opacity-100": canLink,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
@ -155,7 +155,13 @@ export function MediaCard(props: MediaCardProps) {
|
||||||
|
|
||||||
if (!props.linkable) return <span>{content}</span>;
|
if (!props.linkable) return <span>{content}</span>;
|
||||||
return (
|
return (
|
||||||
<Link to={link} className={props.closable ? "hover:cursor-default" : ""}>
|
<Link
|
||||||
|
to={link}
|
||||||
|
className={classNames(
|
||||||
|
"tabbable",
|
||||||
|
props.closable ? "hover:cursor-default" : ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
{content}
|
{content}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|
|
@ -14,9 +14,10 @@ export function ColorOption(props: {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
|
type="button"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"p-1.5 bg-video-context-buttonFocus rounded transition-colors duration-100",
|
"tabbable p-1.5 bg-video-context-buttonFocus rounded transition-colors duration-100",
|
||||||
props.active ? "bg-opacity-100" : "bg-opacity-0 cursor-pointer"
|
props.active ? "bg-opacity-100" : "bg-opacity-0 cursor-pointer"
|
||||||
)}
|
)}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
|
@ -29,7 +30,7 @@ export function ColorOption(props: {
|
||||||
<Icon className="text-sm text-black" icon={Icons.CHECKMARK} />
|
<Icon className="text-sm text-black" icon={Icons.CHECKMARK} />
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +78,11 @@ export function CaptionSetting(props: {
|
||||||
};
|
};
|
||||||
}, [isFocused]);
|
}, [isFocused]);
|
||||||
|
|
||||||
const inputClasses = `py-1 bg-video-context-inputBg rounded text-white cursor-text ${
|
const inputClasses = `tabbable py-1 bg-video-context-inputBg rounded text-white cursor-text ${
|
||||||
props.controlButtons ? "text-center px-4 w-24" : "px-3 text-left w-20"
|
props.controlButtons ? "text-center px-4 w-24" : "px-3 text-left w-20"
|
||||||
}`;
|
}`;
|
||||||
const arrowButtonClasses =
|
const arrowButtonClasses =
|
||||||
"hover:text-white transition-colors duration-100 w-full h-full flex justify-center items-center hover:bg-video-context-buttonOverInputHover rounded";
|
"tabbable hover:text-white transition-colors duration-100 w-full h-full flex justify-center items-center hover:bg-video-context-buttonOverInputHover rounded";
|
||||||
const textTransformer = props.textTransformer ?? ((s) => s);
|
const textTransformer = props.textTransformer ?? ((s) => s);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -153,6 +153,7 @@ export function CaptionsView({ id }: { id: string }) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => router.navigate("/captions/settings")}
|
onClick={() => router.navigate("/captions/settings")}
|
||||||
|
className="py-1 -my-1 px-3 -mx-3 rounded tabbable"
|
||||||
>
|
>
|
||||||
Customize
|
Customize
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -17,7 +17,7 @@ function ButtonList(props: {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"w-full px-2 py-1 rounded-md",
|
"w-full px-2 py-1 rounded-md tabbable",
|
||||||
props.selected === option
|
props.selected === option
|
||||||
? "bg-video-context-buttons-active text-white"
|
? "bg-video-context-buttons-active text-white"
|
||||||
: null
|
: null
|
||||||
|
|
|
@ -9,14 +9,15 @@ export function BackLink(props: { url: string }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => history.push(props.url)}
|
onClick={() => history.push(props.url)}
|
||||||
className="flex items-center cursor-pointer text-type-secondary hover:text-white transition-colors duration-200 font-medium"
|
className="py-1 -my-1 px-2 -mx-2 tabbable rounded-lg flex items-center cursor-pointer text-type-secondary hover:text-white transition-colors duration-200 font-medium"
|
||||||
>
|
>
|
||||||
<Icon className="mr-2" icon={Icons.ARROW_LEFT} />
|
<Icon className="mr-2" icon={Icons.ARROW_LEFT} />
|
||||||
<span className="md:hidden">{t("videoPlayer.backToHomeShort")}</span>
|
<span className="md:hidden">{t("videoPlayer.backToHomeShort")}</span>
|
||||||
<span className="hidden md:block">{t("videoPlayer.backToHome")}</span>
|
<span className="hidden md:block">{t("videoPlayer.backToHome")}</span>
|
||||||
</span>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const VideoPlayerButton = forwardRef<
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(e) => props.onClick?.(e.currentTarget as HTMLButtonElement)}
|
onClick={(e) => props.onClick?.(e.currentTarget as HTMLButtonElement)}
|
||||||
className={classNames([
|
className={classNames([
|
||||||
"p-2 rounded-full hover:bg-video-buttonBackground hover:bg-opacity-50 transition-transform duration-100 flex items-center",
|
"tabbable p-2 rounded-full hover:bg-video-buttonBackground hover:bg-opacity-50 transition-transform duration-100 flex items-center",
|
||||||
props.activeClass ??
|
props.activeClass ??
|
||||||
"active:scale-110 active:bg-opacity-75 active:text-white",
|
"active:scale-110 active:bg-opacity-75 active:text-white",
|
||||||
props.className ?? "",
|
props.className ?? "",
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function Input(props: {
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
className="w-full py-2 px-3 pl-[calc(0.75rem+24px)] focus:outline-none bg-video-context-inputBg rounded placeholder:text-video-context-inputPlaceholder"
|
className="w-full py-2 px-3 pl-[calc(0.75rem+24px)] tabbable bg-video-context-inputBg rounded placeholder:text-video-context-inputPlaceholder"
|
||||||
value={props.value}
|
value={props.value}
|
||||||
onInput={(e) => props.onInput(e.currentTarget.value)}
|
onInput={(e) => props.onInput(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function BackLink(props: {
|
||||||
<Title rightSide={props.rightSide}>
|
<Title rightSide={props.rightSide}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="-ml-2 p-2 rounded hover:bg-video-context-light hover:bg-opacity-10"
|
className="-ml-2 p-2 rounded tabbable hover:bg-video-context-light hover:bg-opacity-10"
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
>
|
>
|
||||||
<Icon className="text-xl" icon={Icons.ARROW_LEFT} />
|
<Icon className="text-xl" icon={Icons.ARROW_LEFT} />
|
||||||
|
@ -57,9 +57,9 @@ export function Link(props: {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
}) {
|
}) {
|
||||||
const classes = classNames("flex py-2 px-3 rounded w-full -ml-3", {
|
const classes = classNames("flex py-2 px-3 rounded-lg w-full -ml-3", {
|
||||||
"cursor-default": !props.clickable,
|
"cursor-default": !props.clickable,
|
||||||
"hover:bg-video-context-hoverColor hover:bg-opacity-50 cursor-pointer":
|
"hover:bg-video-context-hoverColor hover:bg-opacity-50 cursor-pointer tabbable":
|
||||||
props.clickable,
|
props.clickable,
|
||||||
"bg-video-context-hoverColor bg-opacity-50": props.active,
|
"bg-video-context-hoverColor bg-opacity-50": props.active,
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,12 @@ import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { useCaptions } from "@/components/player/hooks/useCaptions";
|
import { useCaptions } from "@/components/player/hooks/useCaptions";
|
||||||
import { useVolume } from "@/components/player/hooks/useVolume";
|
import { useVolume } from "@/components/player/hooks/useVolume";
|
||||||
|
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||||
import { usePlayerStore } from "@/stores/player/store";
|
import { usePlayerStore } from "@/stores/player/store";
|
||||||
import { useEmpheralVolumeStore } from "@/stores/volume";
|
import { useEmpheralVolumeStore } from "@/stores/volume";
|
||||||
|
|
||||||
export function KeyboardEvents() {
|
export function KeyboardEvents() {
|
||||||
|
const router = useOverlayRouter("");
|
||||||
const display = usePlayerStore((s) => s.display);
|
const display = usePlayerStore((s) => s.display);
|
||||||
const mediaPlaying = usePlayerStore((s) => s.mediaPlaying);
|
const mediaPlaying = usePlayerStore((s) => s.mediaPlaying);
|
||||||
const time = usePlayerStore((s) => s.progress.time);
|
const time = usePlayerStore((s) => s.progress.time);
|
||||||
|
@ -90,6 +92,7 @@ export function KeyboardEvents() {
|
||||||
dataRef.current.display?.[
|
dataRef.current.display?.[
|
||||||
dataRef.current.mediaPlaying.isPaused ? "play" : "pause"
|
dataRef.current.mediaPlaying.isPaused ? "play" : "pause"
|
||||||
]();
|
]();
|
||||||
|
if (k === "Escape") router.close();
|
||||||
|
|
||||||
// captions
|
// captions
|
||||||
if (k === "c") dataRef.current.toggleLastUsed().catch(() => {}); // ignore errors
|
if (k === "c") dataRef.current.toggleLastUsed().catch(() => {}); // ignore errors
|
||||||
|
@ -114,7 +117,7 @@ export function KeyboardEvents() {
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("keydown", keyEventHandler);
|
window.removeEventListener("keydown", keyEventHandler);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [router]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,6 +216,6 @@ input[type=range].styled-slider.slider-progress::-ms-fill-lower {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbable:focus {
|
.tabbable:focus {
|
||||||
outline: 1px solid theme('colors.themePreview.primary');
|
outline: 2px solid theme('colors.themePreview.primary');
|
||||||
box-shadow: 0 0 10px theme('colors.themePreview.secondary');
|
box-shadow: 0 0 10px theme('colors.themePreview.secondary');
|
||||||
}
|
}
|
Loading…
Reference in a new issue