diff --git a/packages/appreader/src/index.jsx b/packages/appreader/src/index.jsx index 18aba5c8b..3f0c815cd 100644 --- a/packages/appreader/src/index.jsx +++ b/packages/appreader/src/index.jsx @@ -84,7 +84,7 @@ const App = () => { margin={window.margin} maxWidthPercentage={window.maxWidthPercentage} lineHeight={window.lineHeight} - highContrastFont={window.prefersHighContrastFont ?? true} + highContrastText={window.prefersHighContrastFont ?? true} articleMutations={{ createHighlightMutation: (input) => mutation('createHighlight', input), diff --git a/packages/web/components/templates/article/ArticleContainer.tsx b/packages/web/components/templates/article/ArticleContainer.tsx index 217d9b19f..93f427d7e 100644 --- a/packages/web/components/templates/article/ArticleContainer.tsx +++ b/packages/web/components/templates/article/ArticleContainer.tsx @@ -19,6 +19,7 @@ import { LabelChip } from '../../elements/LabelChip' import { Label } from '../../../lib/networking/fragments/labelFragment' import { Recommendation } from '../../../lib/networking/queries/useGetLibraryItemsQuery' import { Avatar } from '../../elements/Avatar' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' type ArticleContainerProps = { article: ArticleAttributes @@ -32,8 +33,9 @@ type ArticleContainerProps = { fontFamily?: string lineHeight?: number maxWidthPercentage?: number - highContrastFont?: boolean + highContrastText?: boolean showHighlightsModal: boolean + justifyText?: boolean setShowHighlightsModal: React.Dispatch> } @@ -116,8 +118,8 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element { const [fontFamilyOverride, setFontFamilyOverride] = useState( null ) - const [highContrastFont, setHighContrastFont] = useState( - props.highContrastFont ?? false + const [highContrastText, setHighContrastText] = useState( + props.highContrastText ?? false ) const highlightHref = useRef( window.location.hash ? window.location.hash.split('#')[1] : null @@ -175,7 +177,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element { const handleFontContrastChange = async (event: UpdateFontContrastEvent) => { const highContrast = event.fontContrast == 'high' - setHighContrastFont(highContrast) + setHighContrastText(highContrast) } interface UpdateFontSizeEvent extends Event { @@ -257,7 +259,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element { maxWidthPercentage: maxWidthPercentageOverride ?? props.maxWidthPercentage, lineHeight: lineHeightOverride ?? props.lineHeight ?? 150, fontFamily: fontFamilyOverride ?? props.fontFamily ?? 'inter', - readerFontColor: highContrastFont + readerFontColor: highContrastText ? theme.colors.readerFontHighContrast.toString() : theme.colors.readerFont.toString(), readerTableHeaderColor: theme.colors.readerTableHeader.toString(), @@ -283,6 +285,9 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element { background: props.isAppleAppEmbed ? 'unset' : theme.colors.readerBg.toString(), + '.article-inner-css': { + textAlign: props.justifyText ? 'justify' : 'start', + }, '--text-font-family': styles.fontFamily, '--text-font-size': `${styles.fontSize}px`, '--line-height': `${styles.lineHeight}%`, diff --git a/packages/web/components/templates/article/DisplaySettingsModal.tsx b/packages/web/components/templates/article/DisplaySettingsModal.tsx index b736db31e..b0a3177d0 100644 --- a/packages/web/components/templates/article/DisplaySettingsModal.tsx +++ b/packages/web/components/templates/article/DisplaySettingsModal.tsx @@ -17,11 +17,6 @@ type DisplaySettingsModalProps = { export function DisplaySettingsModal( props: DisplaySettingsModalProps ): JSX.Element { - const top = - props.triggerElementRef?.current?.getBoundingClientRect().bottom ?? 0 - const left = - props.triggerElementRef?.current?.getBoundingClientRect().left ?? 0 - return ( diff --git a/packages/web/components/templates/article/ReaderSettingsControl.tsx b/packages/web/components/templates/article/ReaderSettingsControl.tsx index 92265b912..2ef976e24 100644 --- a/packages/web/components/templates/article/ReaderSettingsControl.tsx +++ b/packages/web/components/templates/article/ReaderSettingsControl.tsx @@ -2,7 +2,13 @@ import { HStack, VStack, SpanBox } from '../../elements/LayoutPrimitives' import { Button } from '../../elements/Button' import { StyledText } from '../../elements/StyledText' import { styled, theme, ThemeId } from '../../tokens/stitches.config' -import { ArrowsHorizontal, ArrowsInLineHorizontal, Check } from 'phosphor-react' +import { + ArrowsHorizontal, + ArrowsInLineHorizontal, + CaretLeft, + CaretRight, + Check, +} from 'phosphor-react' import { TickedRangeSlider } from '../../elements/TickedRangeSlider' import { showSuccessToast } from '../../../lib/toastHelpers' import { ReaderSettings } from '../../../lib/hooks/useReaderSettings' @@ -10,6 +16,8 @@ import { useCallback, useMemo, useState } from 'react' import { currentThemeName, updateTheme } from '../../../lib/themeUpdater' import { LineHeightIncreaseIcon } from '../../elements/images/LineHeightIncreaseIconProps' import { LineHeightDecreaseIcon } from '../../elements/images/LineHeightDecreaseIcon' +import * as Switch from '@radix-ui/react-switch' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' type ReaderSettingsProps = { readerSettings: ReaderSettings @@ -33,7 +41,158 @@ const FONT_FAMILIES = [ 'Source Serif Pro', ] +type SettingsProps = { + readerSettings: ReaderSettings + setShowAdvanced: (show: boolean) => void +} + export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element { + const [showAdvanced, setShowAdvanced] = useState(false) + + return ( + <> + {showAdvanced ? ( + + ) : ( + + )} + + ) +} + +function AdvancedSettings(props: SettingsProps): JSX.Element { + return ( + + + + + + { + props.readerSettings.setJustifyText(checked) + }} + > + + + + + + + { + props.readerSettings.setHighContrastText(checked) + }} + > + + + + + ) +} + +const SwitchRoot = styled(Switch.Root, { + all: 'unset', + width: 42, + height: 25, + backgroundColor: '$thBorderColor', + borderRadius: '9999px', + position: 'relative', + WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', + '&:focus': { boxShadow: `0 0 0 2px $thBorderColor` }, + '&[data-state="checked"]': { backgroundColor: '$thBorderColor' }, +}) + +const SwitchThumb = styled(Switch.Thumb, { + display: 'block', + width: 21, + height: 21, + backgroundColor: '$thTextContrast2', + borderRadius: '9999px', + transition: 'transform 100ms', + transform: 'translateX(2px)', + willChange: 'transform', + '&[data-state="checked"]': { transform: 'translateX(19px)' }, +}) + +const Label = styled('label', { + color: 'white', + fontSize: 15, + lineHeight: 1, +}) + +function BasicSettings(props: SettingsProps): JSX.Element { return ( @@ -48,11 +207,15 @@ export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element { - + + ) diff --git a/packages/web/lib/hooks/useReaderSettings.tsx b/packages/web/lib/hooks/useReaderSettings.tsx index 0ff7c684a..af2293bd3 100644 --- a/packages/web/lib/hooks/useReaderSettings.tsx +++ b/packages/web/lib/hooks/useReaderSettings.tsx @@ -33,10 +33,17 @@ export type ReaderSettings = { fontFamily: string setFontFamily: (newStyle: string) => void + + justifyText: boolean | undefined + setJustifyText: (set: boolean) => void + highContrastText: boolean | undefined + setHighContrastText: (set: boolean) => void } export const useReaderSettings = (): ReaderSettings => { const { preferencesData } = useGetUserPreferences() + const [, updateState] = useState({}) + const [fontSize, setFontSize] = usePersistedState({ key: 'fontSize', initialValue: preferencesData?.fontSize ?? 20, @@ -53,6 +60,17 @@ export const useReaderSettings = (): ReaderSettings => { key: 'fontFamily', initialValue: DEFAULT_FONT, }) + const [highContrastText, setHighContrastText] = usePersistedState< + boolean | undefined + >({ + key: `--display-high-contrast-text`, + initialValue: false, + }) + + const [justifyText, setJustifyText] = usePersistedState({ + key: `--display-justify-text`, + initialValue: false, + }) const [showSetLabelsModal, setShowSetLabelsModal] = useState(false) const [showEditDisplaySettingsModal, setShowEditDisplaySettingsModal] = useState(false) @@ -65,6 +83,12 @@ export const useReaderSettings = (): ReaderSettings => { })() } + // const [hideMargins, setHideMargins] = usePersistedState({ + // key: `--display-hide-margins`, + // initialValue: false, + // isSessionStorage: false, + // }) + const actionHandler = useCallback( (action: string, arg?: unknown) => { switch (action) { @@ -199,5 +223,9 @@ export const useReaderSettings = (): ReaderSettings => { actionHandler, setFontFamily, fontFamily, + justifyText, + setJustifyText, + highContrastText, + setHighContrastText, } } diff --git a/packages/web/pages/[username]/[slug]/index.tsx b/packages/web/pages/[username]/[slug]/index.tsx index 1a071ee4d..af9c9b364 100644 --- a/packages/web/pages/[username]/[slug]/index.tsx +++ b/packages/web/pages/[username]/[slug]/index.tsx @@ -376,6 +376,8 @@ export default function Home(): JSX.Element { labels={labels} showHighlightsModal={showHighlightsModal} setShowHighlightsModal={setShowHighlightsModal} + justifyText={readerSettings.justifyText ?? undefined} + highContrastText={readerSettings.highContrastText ?? undefined} articleMutations={{ createHighlightMutation, deleteHighlightMutation, @@ -413,9 +415,9 @@ export default function Home(): JSX.Element { + onOpenChange={() => { readerSettings.setShowEditDisplaySettingsModal(false) - } + }} /> )} {readerSettings.showDeleteConfirmation && ( diff --git a/packages/web/styles/articleInnerStyling.css b/packages/web/styles/articleInnerStyling.css index 1b9b26c7f..b8cb3dddc 100644 --- a/packages/web/styles/articleInnerStyling.css +++ b/packages/web/styles/articleInnerStyling.css @@ -324,7 +324,6 @@ on smaller screens we display the note icon } .article-inner-css .page { - text-align: start; word-wrap: break-word; font-size: var(--text-font-size);