Skip to content

Commit

Permalink
Merge pull request #44 from readium/theming
Browse files Browse the repository at this point in the history
Theming
  • Loading branch information
JayPanoz authored Dec 18, 2024
2 parents 5753d79 + 6465134 commit 41cca0d
Show file tree
Hide file tree
Showing 30 changed files with 2,217 additions and 118 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.7",
"readium-css": "github:readium/readium-css#json",
"readium-css": "github:readium/readium-css#theming-improvements",
"typescript": "^5",
"vercel": "39.1.1"
},
Expand Down
1,638 changes: 1,629 additions & 9 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/components/ArrowButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export const ArrowButton = (props: ReaderArrowProps) => {
const button = useRef<HTMLButtonElement>(null);
const isImmersive = useAppSelector(state => state.reader.isImmersive);
const isFullscreen = useAppSelector(state => state.reader.isFullscreen);
const hasReachedDynamicBreakpoint = useAppSelector(state => state.reader.hasReachedDynamicBreakpoint);
const staticBreakpoint = useAppSelector(state => state.reader.staticBreakpoint);
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);

Expand Down
35 changes: 28 additions & 7 deletions src/components/Reader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

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

import "./assets/styles/reader.css";
Expand All @@ -21,10 +21,10 @@ import { ReaderFooter } from "./ReaderFooter";

import { useEpubNavigator } from "@/hooks/useEpubNavigator";
import { useFullscreen } from "@/hooks/useFullscreen";
import { useTheming } from "@/hooks/useTheming";

import Peripherals from "@/helpers/peripherals";
import { CUSTOM_SCHEME, ScrollActions, ScrollBackTo } from "@/helpers/scrollAffordance";
import { propsToCSSVars } from "@/helpers/propsToCSSVars";
import { localData } from "@/helpers/localData";
import { getPlatformModifier } from "@/helpers/keyboard/getMetaKeys";

Expand All @@ -33,11 +33,11 @@ import { setFXL, setRTL, setProgression, setRunningHead } from "@/lib/publicatio
import { useAppSelector, useAppDispatch } from "@/lib/hooks";

import debounce from "debounce";
import { useBreakpoints } from "@/hooks/useBreakpoints";

interface IRCSSSettings {
paginated: boolean;
colCount: string;
theme: Themes;
}

export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHref: string }) => {
Expand All @@ -47,10 +47,12 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre

const isPaged = useAppSelector(state => state.reader.isPaged);
const colCount = useAppSelector(state => state.reader.colCount);
const theme = useAppSelector(state => state.theming.theme);

const RCSSSettings = useRef<IRCSSSettings>({
paginated: isPaged,
colCount: colCount
colCount: colCount,
theme: theme
});

const isImmersive = useAppSelector(state => state.reader.isImmersive);
Expand All @@ -62,7 +64,7 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre
const dispatch = useAppDispatch();

const fs = useFullscreen();
const staticBreakpoint = useBreakpoints();
const theming = useTheming();

const {
EpubNavigatorLoad,
Expand All @@ -80,6 +82,7 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre
applyReadiumCSSStyles,
handleColCountReflow,
handleScrollReflow,
handleTheme,
setFXLPages,
handleProgression
} = useEpubNavigator();
Expand Down Expand Up @@ -123,6 +126,13 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre
applyReadiumCSSStyles({
"--RS__pageGutter": `${RSPrefs.typography.pageGutter}px`
});

if (RCSSSettings.current.theme === Themes.auto) {
handleTheme(theming.inferThemeAuto());
} else {
handleTheme(RCSSSettings.current.theme);
}

if (RCSSSettings.current.paginated) {
await applyColumns(RCSSSettings.current.colCount);
} else {
Expand Down Expand Up @@ -263,8 +273,19 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre
}
}, [colCount, navLayout, setFXLPages, handleColCountReflow]);

// Handling side effects on Navigator
useEffect(() => {
RCSSSettings.current.theme = theme;

if (theme === Themes.auto) {
handleTheme(theming.inferThemeAuto());
} else {
handleTheme(theme);
}
}, [theme, handleTheme, theming]);

const handleResize = debounce(() => {
if (navLayout() === EPUBLayout.reflowable) {
if (navLayout() === EPUBLayout.reflowable) {
if (RCSSSettings.current.paginated) {
handleColCountReflow(RCSSSettings.current.colCount);
} else {
Expand Down Expand Up @@ -333,7 +354,7 @@ export const Reader = ({ rawManifest, selfHref }: { rawManifest: object, selfHre

return (
<>
<main style={ propsToCSSVars(RSPrefs.theming) }>
<main>
<ReaderHeader
toc={ publication.current?.tableOfContents || new Links([]) }
/>
Expand Down
3 changes: 2 additions & 1 deletion src/components/ReadingDisplayLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export enum ReadingDisplayLayoutOption {
paginated = "page_option"
}

export const ReadingDisplayLayout = ({ isFXL }: { isFXL: boolean }) => {
export const ReadingDisplayLayout = () => {
const isPaged = useAppSelector(state => state.reader.isPaged);
const isFXL = useAppSelector(state => state.publication.isFXL);
const dispatch = useAppDispatch();

const handleChange = (value: string) => {
Expand Down
78 changes: 78 additions & 0 deletions src/components/ReadingDisplayTheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { CSSProperties, useRef } from "react";

import { RSPrefs, Themes } from "@/preferences";
import Locale from "../resources/locales/en.json";
import settingsStyles from "./assets/styles/readerSettings.module.css";

import CheckIcon from "./assets/icons/check.svg";

import { Label, Radio, RadioGroup } from "react-aria-components";

import { useAppDispatch, useAppSelector } from "@/lib/hooks";
import { setTheme } from "@/lib/themeReducer";

import classNames from "classnames";

export const ReadingDisplayTheme = () => {
const theme = useAppSelector(state => state.theming.theme);
const isFXL = useAppSelector(state => state.publication.isFXL);

const themeItems = useRef(isFXL ? RSPrefs.theming.themes.fxlOrder : RSPrefs.theming.themes.reflowOrder);

const dispatch = useAppDispatch();

const handleTheme = (value: string) => {
dispatch(setTheme(value));
};

// Yeah so it’s easier to inline styles from preferences for these
// than spamming the entire app with all custom properties right now
const doStyles = (t: Themes) => {
let cssProps: CSSProperties = {
boxSizing: "border-box",
color: "#999999"
};

if (t === Themes.auto) {
cssProps.background = `linear-gradient(148deg, ${ RSPrefs.theming.themes[Themes.light].background } 0%, ${ RSPrefs.theming.themes[Themes.dark].background } 48%)`;
cssProps.color = "#ffffff";
cssProps.border = `1px solid ${ RSPrefs.theming.themes[Themes.light].subdue }`;
} else {
cssProps.background = RSPrefs.theming.themes[t].background;
cssProps.color = RSPrefs.theming.themes[t].text;
cssProps.border = `1px solid ${ RSPrefs.theming.themes[t].subdue }`;
};

return cssProps;
};

return (
<>
<div>
<RadioGroup
orientation="horizontal"
value={ theme }
onChange={ handleTheme }
>
<Label className={ settingsStyles.readerSettingsLabel }>{ Locale.reader.settings.themes.title }</Label>
<div className={ classNames(settingsStyles.readerSettingsRadioWrapper, settingsStyles.readerSettingsThemesWrapper) }>
{ themeItems.current.map(( t ) =>
<Radio
className={ classNames(
settingsStyles.readerSettingsRadio,
settingsStyles.readerSettingsThemeRadio
) }
value={ t }
id={ t }
key={ t }
style={ doStyles(t) }
>
<span>{ Locale.reader.settings.themes[t as keyof typeof Themes] } { t === theme ? <CheckIcon aria-hidden="true" focusable="false" /> : <></>}</span>
</Radio>
) }
</div>
</RadioGroup>
</div>
</>
)
}
8 changes: 5 additions & 3 deletions src/components/SettingsAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import { OverflowMenuItem } from "./Templates/OverflowMenuItem";
import { ActionComponentVariant, ActionKeys, IActionComponent } from "./Templates/ActionComponent";
import { ReadingDisplayCol } from "./ReadingDisplayCol";
import { ReadingDisplayLayout } from "./ReadingDisplayLayout";
import { ReadingDisplayTheme } from "./ReadingDisplayTheme";

import { setHovering, setSettingsOpen } from "@/lib/readerReducer";
import { useAppDispatch, useAppSelector } from "@/lib/hooks";

export const SettingsAction: React.FC<IActionComponent> = ({ variant }) => {
const isOpen = useAppSelector(state => state.reader.settingsOpen);
const isFXL = useAppSelector(state => state.publication.isFXL);
const dispatch = useAppDispatch();

const setOpen = (value: boolean) => {
Expand Down Expand Up @@ -71,9 +71,11 @@ export const SettingsAction: React.FC<IActionComponent> = ({ variant }) => {
<CloseIcon aria-hidden="true" focusable="false" />
</Button>
<Heading slot="title" className={ readerSharedUI.popoverHeading }>{ Locale.reader.settings.heading }</Heading>
<ReadingDisplayTheme />
<Separator />
<ReadingDisplayCol />
<Separator/>
<ReadingDisplayLayout isFXL={ isFXL } />
<Separator />
<ReadingDisplayLayout />
</Dialog>
</Popover>
</DialogTrigger>
Expand Down
1 change: 1 addition & 0 deletions src/components/assets/icons/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions src/components/assets/styles/arrowButton.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
box-sizing: border-box;
padding: 5px;

background-color: var(--color-secondary);
border: 1px solid var(--color-primary);
background-color: var(--theme-background);
border: 1px solid var(--theme-text);
}

.container .viewportLarge {
Expand All @@ -49,7 +49,7 @@
}

.container button[data-focused] {
outline: auto;
outline: 2px solid var(--theme-focus);
opacity: 1;
}

Expand All @@ -62,6 +62,6 @@
}

.container button svg {
fill: var(--color-primary);
stroke: var(--color-primary);
fill: var(--theme-text);
stroke: var(--theme-text);
}
14 changes: 7 additions & 7 deletions src/components/assets/styles/overflowMenu.module.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.overflowPopover {
background-color: var(--color-secondary);
color: var(--color-primary);
background-color: var(--theme-background);
color: var(--theme-text);
padding: 10px;
border-radius: 5px;
border: 1px solid var(--color-primary);
border: 1px solid var(--theme-text);
position: relative;
}

Expand All @@ -16,11 +16,11 @@
}

.menuItem[data-hovered] {
background-color: var(--color-hover);
background-color: var(--theme-hover);
}

.menuItem[data-focus-visible] {
outline: auto;
outline: 2px solid var(--theme-focus);
}

.menuItem > svg {
Expand All @@ -35,9 +35,9 @@
.menuItemKbdShortcut {
font-family: monospace;
font-weight: bold;
color: var(--color-subdued);
color: var(--theme-subdue);
padding: 5px;
margin-left: auto;
border-radius: 5px;
border: 1px solid var(--color-subdued);
border: 1px solid var(--theme-subdue);
}
2 changes: 1 addition & 1 deletion src/components/assets/styles/progression.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#current {
color: var(--color-primary);
color: var(--theme-text);
font-variant-numeric: lining-nums tabular-nums;
}
27 changes: 20 additions & 7 deletions src/components/assets/styles/reader.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
:root {
/* Borrowed from Thorium src/renderer/assets/styles/variable.scss */
--color-primary: #4d4d4d;
--color-secondary: white;
--color-disabled: #767676;
--color-subdued: #999999;
--color-hover: #eaeaea;
--color-selected: #eaeaea;
--theme-text: ;
--theme-background: ;
--theme-link: ;
--theme-visited: ;
--theme-subdue: ;
--theme-disable: ;
--theme-hover: ;
--theme-onHover: ;
--theme-select: ;
--theme-onSelect: ;
--theme-focus: ;
--theme-elevate: ;
--theme-immerse: ;
}

html,
Expand All @@ -27,7 +34,7 @@ body {
box-sizing: border-box;
gap: 2px;
touch-action: manipulation;
background-color: #FFFFFF;
background-color: var(--theme-background);
}

/* Necessary to have all three so that there is no offset when switching paginated/scroll */
Expand All @@ -49,6 +56,7 @@ main {
flex-direction: column;
height: 100vh;
height: 100dvh;
background-color: var(--theme-background);
}

#wrapper {
Expand Down Expand Up @@ -109,4 +117,9 @@ button {

/* Focus no outline */
outline: none;
}

::selection {
background-color: var(--theme-select);
color: var(--theme-onSelect);
}
2 changes: 1 addition & 1 deletion src/components/assets/styles/readerHeader.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
.header h1 {
font-size: 1rem;
line-height: 1;
color: var(--color-primary);
color: var(--theme-text);
font-weight: normal;
grid-area: header-center;
justify-self: center;
Expand Down
Loading

0 comments on commit 41cca0d

Please sign in to comment.