diff --git a/package.json b/package.json index 00293d1..ec0b27e 100644 --- a/package.json +++ b/package.json @@ -52,12 +52,15 @@ "eslint": "^8", "eslint-config-next": "14.2.7", "readium-css": "github:readium/readium-css#json", - "typescript": "^5" + "typescript": "^5", + "vercel": "39.1.1" }, "overrides": { - "@babel/core": "7.25.2" + "@babel/core": "7.25.2", + "vercel": "$vercel" }, "resolutions": { - "@babel/core": "7.25.2" + "@babel/core": "7.25.2", + "vercel": "$vercel" } } diff --git a/src/app/page.tsx b/src/app/page.tsx index b5322b5..8a45f05 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -13,6 +13,12 @@ export default function Home() {
  • Moby Dick (reflow)
  • +
  • + The House of the Seven Gables (reflow advanced) +
  • +
  • + Les Diaboliques (reflow french) +
  • Bella the Dragon (FXL)
  • diff --git a/src/components/ArrowButton.tsx b/src/components/ArrowButton.tsx index 89abc5c..d7f1b96 100644 --- a/src/components/ArrowButton.tsx +++ b/src/components/ArrowButton.tsx @@ -14,6 +14,8 @@ import { Button, PressEvent, Tooltip, TooltipTrigger } from "react-aria-componen import { useAppSelector } from "@/lib/hooks"; import classNames from "classnames"; +import { isActiveElement } from "@/helpers/focus"; +import { StaticBreakpoints } from "@/hooks/useBreakpoints"; export interface ReaderArrowProps { direction: "left" | "right"; @@ -26,8 +28,10 @@ export const ArrowButton = (props: ReaderArrowProps) => { const button = useRef(null); const isImmersive = useAppSelector(state => state.reader.isImmersive); const isFullscreen = useAppSelector(state => state.reader.isFullscreen); - const hasReachedBreakpoint = useAppSelector(state => state.reader.hasReachedBreakpoint); + const hasReachedDynamicBreakpoint = useAppSelector(state => state.reader.hasReachedDynamicBreakpoint); + const staticBreakpoint = useAppSelector(state => state.reader.staticBreakpoint); const isRTL = useAppSelector(state => state.publication.isRTL); + const isFXL = useAppSelector(state => state.publication.isFXL); const [isHovering, setIsHovering] = useState(false); @@ -35,7 +39,7 @@ export const ArrowButton = (props: ReaderArrowProps) => { const handleClassNameFromState = () => { let className = ""; - if (isImmersive && !hasReachedBreakpoint || isFullscreen) { + if (isImmersive && !hasReachedDynamicBreakpoint || isFullscreen) { className = readerStateStyles.immersiveHidden; } else if (isImmersive) { className = readerStateStyles.immersive; @@ -44,22 +48,34 @@ export const ArrowButton = (props: ReaderArrowProps) => { }; const handleClassNameFromBreakpoint = () => { - return hasReachedBreakpoint ? arrowStyles.viewportLarge : ""; + if (isFXL && (staticBreakpoint === StaticBreakpoints.large || staticBreakpoint === StaticBreakpoints.xLarge)) { + return arrowStyles.viewportLarge; + } else if (!isFXL && hasReachedDynamicBreakpoint) { + return arrowStyles.viewportLarge; + } else { + return ""; + } }; useEffect(() => { - if ((props.disabled || (isImmersive && !isHovering)) && document.activeElement === button.current) { + if ((props.disabled || (isImmersive && !isHovering)) && isActiveElement(button.current)) { button.current!.blur(); } }); + const blurOnEsc = (event: React.KeyboardEvent) => { + if (isActiveElement(button.current) && event.code === "Escape") { + button.current!.blur(); + } + }; + // Unlike preventFocusOnPress, this gives a visual feedback // the button has been pressed in immersive mode (esp. when hidden) // CSS needs to take care of hover state though, as it will be applied // on mobile depending on the length of the press const handleNonKeyboardFocus = (event: PressEvent) => { if (event.pointerType !== "keyboard") { - if (document.activeElement === button.current) { + if (isActiveElement(button.current)) { button.current!.blur() } } @@ -74,8 +90,10 @@ export const ArrowButton = (props: ReaderArrowProps) => { onPress={ props.onPressCallback } onPressEnd={ handleNonKeyboardFocus } onHoverChange={ (e) => setIsHovering(e) } + onKeyDown={ blurOnEsc } className={ classNames(props.className, handleClassNameFromBreakpoint(), handleClassNameFromState()) } - isDisabled={ props.disabled }> + isDisabled={ props.disabled } + > { props.direction === "left" ?