Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sheets #51

Draft
wants to merge 86 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
ecfbe2a
[Experimental] Visual arrow nav in RadioGroup
JayPanoz Dec 19, 2024
3f5f68e
remove autofocus from close
JayPanoz Dec 19, 2024
5eb58bc
Add comment to clarify prop for arrow nav
JayPanoz Dec 19, 2024
a4638b1
Init Popover sheet
JayPanoz Dec 19, 2024
aaa892a
Init FullScreenSheet
JayPanoz Dec 19, 2024
ae266ad
Init SheetWithBreakpoints component
JayPanoz Dec 20, 2024
e8026a3
Add prefs for sheets
JayPanoz Dec 20, 2024
5cea595
Use enum keys in actions
JayPanoz Dec 20, 2024
626cd7a
Change heading of settings sheet
JayPanoz Dec 20, 2024
139927d
Enforce max-height for popover sheet
JayPanoz Dec 23, 2024
c7f50ab
Sticky heading in popover sheet
JayPanoz Dec 23, 2024
82123d3
Set focus on popover open
JayPanoz Dec 23, 2024
642cc77
Fallback on close button for popover focus
JayPanoz Dec 23, 2024
82a1034
Init docker component
JayPanoz Dec 26, 2024
da8f60a
Rename docker styles
JayPanoz Dec 27, 2024
3bb1836
Formatting
JayPanoz Dec 27, 2024
57e612d
Turn dockable pref into enum
JayPanoz Dec 30, 2024
212fa0d
Add theming pref for border radius
JayPanoz Dec 30, 2024
86e635a
Aesthetic changes to settings popover
JayPanoz Dec 30, 2024
f30dbc6
Remove separators from Settings
JayPanoz Dec 30, 2024
93f62b7
Init styles for fullscreen sheet
JayPanoz Dec 30, 2024
259e49d
Correct styles for fullscreen sheet and settings
JayPanoz Dec 30, 2024
2c919ee
[WIP] Actions Revamp
JayPanoz Jan 2, 2025
6eba11e
Align toc popover styles
JayPanoz Jan 2, 2025
051ad29
Make useCollapsibility items–agnostic
JayPanoz Jan 3, 2025
0e12ce8
Create Prefs interface
JayPanoz Jan 3, 2025
6fe35c3
Bring back actions to original state
JayPanoz Jan 3, 2025
497ec0b
Create closebutton component
JayPanoz Jan 3, 2025
b6a6d84
Move docker to Actions component
JayPanoz Jan 3, 2025
ca08596
Return ActionsWithCollapsibility even if empty
JayPanoz Jan 3, 2025
73857b6
Handle displayOrder pref for Docker
JayPanoz Jan 4, 2025
b90284d
Update OverflowMenu
JayPanoz Jan 4, 2025
4434b92
Make collapsibility disableable
JayPanoz Jan 4, 2025
0f480b2
Remove keyword smart from collapsibility
JayPanoz Jan 4, 2025
d32a2e4
Disable outline for sheet containers
JayPanoz Jan 6, 2025
88aa67c
Make popover first docking option
JayPanoz Jan 6, 2025
3d66455
Change label for pop over in overflow menu
JayPanoz Jan 6, 2025
4076567
Add Docker to fullscreen sheet
JayPanoz Jan 6, 2025
525747c
Improve consistency of icons
JayPanoz Jan 6, 2025
4338871
Bump ReadiumCSS
JayPanoz Jan 6, 2025
f108737
Merge branch 'arrow-nav-themes' into sheets
JayPanoz Jan 6, 2025
c57ce22
Focus on keyboard nav instead of useEffect
JayPanoz Jan 6, 2025
0404032
Attempt to fix overflow menu transition
JayPanoz Jan 6, 2025
8ac5089
Init Docked Sheet
JayPanoz Jan 7, 2025
7f0cfef
Modify structure of Reader for docking elements
JayPanoz Jan 7, 2025
a53a0e7
Add aria labels for docking elements
JayPanoz Jan 7, 2025
af9bb34
Replace offsetWidth with clientWidth
JayPanoz Jan 8, 2025
504e03b
Merge branch 'develop' into sheets
JayPanoz Jan 8, 2025
17849be
Small CSS improvements
JayPanoz Jan 8, 2025
0a5530e
Merge branch 'sheets' of https://github.com/readium/playground into s…
JayPanoz Jan 8, 2025
7c6901a
Switch from flex to positioning for docked sheets
JayPanoz Jan 8, 2025
43de633
Remove docking options in FullscreenSheet
JayPanoz Jan 8, 2025
786df7c
Add display condition for overflow menu
JayPanoz Jan 8, 2025
14e5303
Resize FXL spread on docking
JayPanoz Jan 8, 2025
094a620
Make settings action button a toggle
JayPanoz Jan 8, 2025
6a8986f
Remove stack cb from Docker
JayPanoz Jan 8, 2025
46e433e
Merge branch 'develop' into sheets
JayPanoz Jan 9, 2025
b165bdc
Update deps
JayPanoz Jan 9, 2025
3b81be2
Rename floating docking key to transient
JayPanoz Jan 10, 2025
638ad0a
Rename enums for docked and dockable
JayPanoz Jan 11, 2025
730af24
Add direction pref
JayPanoz Jan 11, 2025
2eef5fc
Create models + actionsReducer
JayPanoz Jan 11, 2025
a59d25d
Create breakpointsMap helper
JayPanoz Jan 11, 2025
0568db3
Improve models
JayPanoz Jan 11, 2025
d74bf3a
[WIP] useDocking hook
JayPanoz Jan 11, 2025
d7d7e86
correct fullscreen sheet for toc
JayPanoz Jan 11, 2025
d1ed41c
Init resizable sheets
JayPanoz Jan 12, 2025
f5811a0
Make handle more visible
JayPanoz Jan 12, 2025
4587c95
plug resize handler on panel group layout
JayPanoz Jan 12, 2025
acd022f
Add note about useDocking hook
JayPanoz Jan 12, 2025
64d6a9a
Update dock model in actions Pref
JayPanoz Jan 12, 2025
afdcd80
usePanelHandler hook
JayPanoz Jan 12, 2025
f89699a
rename panel custom hook
JayPanoz Jan 12, 2025
91a14a4
Switch to new docking system
JayPanoz Jan 13, 2025
01bccbd
Small improvements
JayPanoz Jan 16, 2025
14a4003
Remove sync of mount/unmount dock panel
JayPanoz Jan 16, 2025
c22be8a
init bottom sheet
JayPanoz Jan 16, 2025
056c396
Styling of draggable bottom sheet
JayPanoz Jan 16, 2025
9fb4b2e
Move bottom sheet header
JayPanoz Jan 16, 2025
d8604ec
Bottom sheet Snap points
JayPanoz Jan 16, 2025
ab06d5e
Make bottom sheet blocking
JayPanoz Jan 16, 2025
0a65e5c
Get around bottom sheet blocking overlay
JayPanoz Jan 17, 2025
e5b7d7e
Remove width of resize handle
JayPanoz Jan 17, 2025
2af0eaf
actions hook + proper handling overflowMenu
JayPanoz Jan 18, 2025
276d437
Update deps
JayPanoz Jan 18, 2025
0c1b6c2
UseActions hook in docker actions
JayPanoz Jan 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,24 @@
"classnames": "^2.5.1",
"debounce": "^2.2.0",
"json-templates": "^5.1.0",
"next": "15.1.1",
"next": "15.1.4",
"react": "^19.0.0",
"react-aria-components": "^1.5.0",
"react-aria-components": "^1.6.0",
"react-dom": "^19.0.0",
"react-redux": "^9.2.0"
"react-redux": "^9.2.0",
"react-resizable-panels": "^2.1.7",
"react-spring-bottom-sheet": "^3.4.1"
},
"devDependencies": {
"@svgr/webpack": "^8.1.0",
"@types/json-templates": "^3.0.3",
"@types/node": "^22.10.2",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.2",
"eslint": "^9.17.0",
"eslint-config-next": "15.1.1",
"@types/node": "^22.10.7",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3",
"eslint": "^9.18.0",
"eslint-config-next": "15.1.4",
"readium-css": "github:readium/readium-css",
"typescript": "^5.7.2",
"typescript": "^5.7.3",
"vercel": "39.1.1"
},
"overrides": {
Expand Down
2,306 changes: 1,292 additions & 1,014 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions src/components/Actions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";

import { ActionComponentVariant, IActions } from "@/models/actions";

export const Actions = ({
items,
className,
label
}: IActions) => {

return (
<>
<div
className={ className }
aria-label={ label }
>
{ items.map(({ Comp, key, associatedKey, ...props }) =>
<Comp
key={ key }
variant={ ActionComponentVariant.button }
{ ...(associatedKey ? { associatedKey: associatedKey } : {}) }
{ ...props }
/>) }
</div>
</>
)
}
51 changes: 51 additions & 0 deletions src/components/ActionsWithCollapsibility.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ActionComponentVariant, IActionsWithCollapsibility } from "@/models/actions";

import { OverflowMenu } from "./OverflowMenu";

import { useCollapsibility } from "@/hooks/useCollapsibility";

export const ActionsWithCollapsibility = ({
id,
items,
prefs,
className,
overflowActionCallback,
overflowMenuClassName,
overflowMenuDisplay,
label,
}: IActionsWithCollapsibility) => {
const Actions = useCollapsibility(items, prefs);

return (
<>
<div
className={ className }
aria-label={ label }
>
{ Actions.ActionIcons.map(({ Comp, key, associatedKey, ...props }) =>
<Comp
key={ key }
variant={ ActionComponentVariant.button }
{ ...(associatedKey ? { associatedKey: associatedKey } : {}) }
{ ...props }
/>)
}

<OverflowMenu
id={ id }
display={ overflowMenuDisplay || true }
className={ overflowMenuClassName }
actionFallback={ overflowActionCallback }
>
{ Actions.MenuItems.map(({ Comp, key, associatedKey, ...props }) =>
<Comp
key={ key }
variant={ ActionComponentVariant.menu }
{ ...(associatedKey ? { associatedKey: associatedKey } : {}) }
{ ...props }
/>) }
</OverflowMenu>
</div>
</>
)
}
24 changes: 13 additions & 11 deletions src/components/ArrowButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React, { useEffect, useRef, useState } from "react";

import { IReaderArrow } from "@/models/layout";
import { StaticBreakpoints } from "@/models/staticBreakpoints";
import { ActionsStateKeys } from "@/models/state/actionsState";

import Locale from "../resources/locales/en.json";

import arrowStyles from "./assets/styles/arrowButton.module.css";
Expand All @@ -12,34 +16,32 @@ import RightArrow from "./assets/icons/arrow_forward.svg";
import { Button, PressEvent, Tooltip, TooltipTrigger } from "react-aria-components";

import { useAppSelector } from "@/lib/hooks";
import { useActions } from "@/hooks/useActions";

import classNames from "classnames";
import { isActiveElement } from "@/helpers/focus";
import { StaticBreakpoints } from "@/hooks/useBreakpoints";

export interface ReaderArrowProps {
direction: "left" | "right";
className?: string;
disabled: boolean;
onPressCallback: () => void;
}
import classNames from "classnames";

export const ArrowButton = (props: ReaderArrowProps) => {
export const ArrowButton = (props: IReaderArrow) => {
const button = useRef<HTMLButtonElement>(null);
const isImmersive = useAppSelector(state => state.reader.isImmersive);
const isFullscreen = useAppSelector(state => state.reader.isFullscreen);
const hasReachedDynamicBreakpoint = useAppSelector(state => state.theming.hasReachedDynamicBreakpoint);
const staticBreakpoint = useAppSelector(state => state.theming.staticBreakpoint);
const isRTL = useAppSelector(state => state.publication.isRTL);
const isFXL = useAppSelector(state => state.publication.isFXL);
const actions = useActions();

const [isHovering, setIsHovering] = useState(false);

const label = (props.direction === "right" && !isRTL || props.direction === "left" && isRTL) ? Locale.reader.navigation.goForward : Locale.reader.navigation.goBackward;

const handleClassNameFromState = () => {
let className = "";
if (isImmersive && !hasReachedDynamicBreakpoint || isFullscreen) {
if (
isImmersive && !hasReachedDynamicBreakpoint ||
isFullscreen ||
!actions.everyOpenDocked()
) {
className = readerStateStyles.immersiveHidden;
} else if (isImmersive) {
className = readerStateStyles.immersive;
Expand Down
56 changes: 56 additions & 0 deletions src/components/CloseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { RSPrefs } from "@/preferences";
import Locale from "../resources/locales/en.json";

import { ICloseButton } from "@/models/actions";

import readerSharedUI from "./assets/styles/readerSharedUI.module.css";

import Close from "./assets/icons/close.svg";

import { Button, Tooltip, TooltipTrigger } from "react-aria-components";

export const CloseButton = ({
ref,
className,
label,
onPressCallback,
withTooltip
}: ICloseButton) => {

if (withTooltip) {
return (
<>
<TooltipTrigger>
<Button
ref={ ref }
className={ className || readerSharedUI.closeButton }
aria-label={ label || Locale.reader.app.docker.close.trigger }
onPress={ onPressCallback }
>
<Close aria-hidden="true" focusable="false" />
</Button>
<Tooltip
className={ readerSharedUI.tooltip }
placement="bottom"
offset={ RSPrefs.theming.icon.tooltipOffset || 0 }
>
{ withTooltip }
</Tooltip>
</TooltipTrigger>
</>
)
} else {
return (
<>
<Button
ref={ ref }
className={ className || readerSharedUI.closeButton }
aria-label={ label || Locale.reader.app.docker.close.trigger }
onPress={ onPressCallback }
>
<Close aria-hidden="true" focusable="false" />
</Button>
</>
)
}
}
10 changes: 6 additions & 4 deletions src/components/FullscreenAction.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React from "react";

import Locale from "../resources/locales/en.json";
import { RSPrefs } from "@/preferences";
import Locale from "../resources/locales/en.json";

import { ActionComponentVariant, ActionKeys, IActionComponent } from "@/models/actions";

import readerSharedUI from "./assets/styles/readerSharedUI.module.css";

import FullscreenCorners from "./assets/icons/fullscreen.svg";
Expand All @@ -11,7 +14,6 @@ import { OverflowMenuItem } from "./Templates/OverflowMenuItem";
import { ActionIcon } from "./Templates/ActionIcon";

import { useFullscreen } from "@/hooks/useFullscreen";
import { ActionComponentVariant, ActionKeys, IActionComponent } from "./Templates/ActionComponent";

import { useAppDispatch } from "@/lib/hooks";
import { setHovering } from "@/lib/readerReducer";
Expand Down Expand Up @@ -43,7 +45,7 @@ export const FullscreenAction: React.FC<IActionComponent> = ({ variant }) => {
<OverflowMenuItem
label={ Locale.reader.fullscreen.trigger }
SVG={ FullscreenCorners }
shortcut={ RSPrefs.actions.fullscreen.shortcut }
shortcut={ RSPrefs.actions.keys[ActionKeys.fullscreen].shortcut }
onActionCallback={ fs.handleFullscreen }
id={ ActionKeys.fullscreen }
/>
Expand All @@ -54,7 +56,7 @@ export const FullscreenAction: React.FC<IActionComponent> = ({ variant }) => {
<>
<ActionIcon
className={ readerSharedUI.iconCompSm }
visibility={ RSPrefs.actions[ActionKeys.fullscreen].visibility }
visibility={ RSPrefs.actions.keys[ActionKeys.fullscreen].visibility }
ariaLabel={ fs.isFullscreen ? Locale.reader.fullscreen.close : Locale.reader.fullscreen.trigger }
SVG={ fs.isFullscreen ? FullscreenExit : FullscreenCorners }
placement="bottom"
Expand Down
9 changes: 5 additions & 4 deletions src/components/JumpToPositionAction.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from "react";

import Locale from "../resources/locales/en.json";
import { RSPrefs } from "@/preferences";
import Locale from "../resources/locales/en.json";

import { ActionComponentVariant, ActionKeys, IActionComponent } from "@/models/actions";

import TargetIcon from "./assets/icons/point_scan.svg";

import { ActionIcon } from "./Templates/ActionIcon";
import { OverflowMenuItem } from "./Templates/OverflowMenuItem";
import { ActionComponentVariant, ActionKeys, IActionComponent } from "./Templates/ActionComponent";

export const JumpToPositionAction: React.FC<IActionComponent> = ({ variant }) => {
if (variant && variant === ActionComponentVariant.menu) {
Expand All @@ -16,7 +17,7 @@ export const JumpToPositionAction: React.FC<IActionComponent> = ({ variant }) =>
<OverflowMenuItem
label={ Locale.reader.jumpToPosition.trigger }
SVG={ TargetIcon }
shortcut={ RSPrefs.actions.jumpToPosition.shortcut }
shortcut={ RSPrefs.actions.keys[ActionKeys.jumpToPosition].shortcut }
id={ ActionKeys.jumpToPosition }
/>
</>
Expand All @@ -25,7 +26,7 @@ export const JumpToPositionAction: React.FC<IActionComponent> = ({ variant }) =>
return(
<>
<ActionIcon
visibility={ RSPrefs.actions[ActionKeys.jumpToPosition].visibility }
visibility={ RSPrefs.actions.keys[ActionKeys.jumpToPosition].visibility }
ariaLabel={ Locale.reader.jumpToPosition.trigger }
SVG={ TargetIcon }
placement="bottom"
Expand Down
57 changes: 37 additions & 20 deletions src/components/OverflowMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import React, { ReactNode } from "react";
import React from "react";

import Locale from "../resources/locales/en.json";

import { ActionVisibility, IOverflowMenu } from "@/models/actions";

import overflowMenuStyles from "./assets/styles/overflowMenu.module.css";

import MenuIcon from "./assets/icons/more_vert.svg";

import { Key, Menu, MenuTrigger, Popover } from "react-aria-components";
import { ActionIcon } from "./Templates/ActionIcon";
import { useAppDispatch, useAppSelector } from "@/lib/hooks";
import { setOverflowMenuOpen, toggleImmersive } from "@/lib/readerReducer";
import { ActionVisibility } from "./Templates/ActionComponent";

export const OverflowMenu = ({ children }: { children?: ReactNode }) => {
const isImmersive = useAppSelector(state => state.reader.isImmersive);
const isHovered = useAppSelector(state => state.reader.isHovering);
import { useAppDispatch } from "@/lib/hooks";
import { toggleImmersive } from "@/lib/readerReducer";
import { setOverflow } from "@/lib/actionsReducer";

export const OverflowMenu = ({
id,
className,
actionFallback,
display,
children
}: IOverflowMenu) => {
const dispatch = useAppDispatch();

const toggleMenuState = (value: boolean) => {
dispatch(setOverflowMenuOpen(value));
dispatch(setOverflow({
key: id,
isOpen: value
}));
}

return(
<>
{ React.Children.toArray(children).length > 0 && (!isImmersive || isHovered) ?

if (React.Children.toArray(children).length > 0 && (display)) {
return (
<>
<MenuTrigger onOpenChange={ (val) => toggleMenuState(val) }>
<ActionIcon
className={ overflowMenuStyles.activeButton }
className={ className ? className : overflowMenuStyles.activeButton }
ariaLabel={ Locale.reader.overflowMenu.active.trigger }
SVG={ MenuIcon }
placement="bottom"
Expand All @@ -38,18 +48,23 @@ export const OverflowMenu = ({ children }: { children?: ReactNode }) => {
className={ overflowMenuStyles.overflowPopover }
>
<Menu
id={ id }
selectionMode="none"
onAction={ (key: Key) => { console.log(key) }

}>
onAction={ (key: Key) => { console.log(key) } }
className={ overflowMenuStyles.overflowMenu }
>
{ children }
</Menu>
</Popover>
</MenuTrigger>
</>
: <>
)
} else {
if (actionFallback) {
return(
<>
<ActionIcon
className={ overflowMenuStyles.hintButton }
className={ className ? className : overflowMenuStyles.hintButton }
ariaLabel={ Locale.reader.overflowMenu.hint.trigger }
SVG={ MenuIcon }
placement="bottom"
Expand All @@ -59,7 +74,9 @@ export const OverflowMenu = ({ children }: { children?: ReactNode }) => {
preventFocusOnPress={ true }
/>
</>
)
} else {
return(<></>)
}
</>
)
}
}
Loading