diff --git a/packages/web/components/elements/LogoBox.tsx b/packages/web/components/elements/LogoBox.tsx index 276941f07..1105263bc 100644 --- a/packages/web/components/elements/LogoBox.tsx +++ b/packages/web/components/elements/LogoBox.tsx @@ -1,4 +1,4 @@ -import { LIBRARY_LEFT_MENU_WIDTH } from '../templates/homeFeed/LibraryFilterMenu' +import { LIBRARY_LEFT_MENU_WIDTH } from '../templates/navMenu/LibraryMenu' import { theme } from '../tokens/stitches.config' import { OmnivoreFullLogo } from './images/OmnivoreFullLogo' import { OmnivoreNameLogo } from './images/OmnivoreNameLogo' diff --git a/packages/web/components/elements/StyledText.tsx b/packages/web/components/elements/StyledText.tsx index 0a47e4747..c9460941e 100644 --- a/packages/web/components/elements/StyledText.tsx +++ b/packages/web/components/elements/StyledText.tsx @@ -192,6 +192,8 @@ const textVariants = { fontSize: '12px', lineHeight: '20px', color: '$thTextSubtle2', + marginBlockStart: '0', + marginTop: '10px', }, error: { color: '$error', diff --git a/packages/web/components/patterns/LibraryCards/LibraryListCard.tsx b/packages/web/components/patterns/LibraryCards/LibraryListCard.tsx index 524c76848..b930e9c68 100644 --- a/packages/web/components/patterns/LibraryCards/LibraryListCard.tsx +++ b/packages/web/components/patterns/LibraryCards/LibraryListCard.tsx @@ -14,7 +14,7 @@ import { FLAIR_ICON_NAMES, } from './LibraryCardStyles' import { sortedLabels } from '../../../lib/labelsSort' -import { LIBRARY_LEFT_MENU_WIDTH } from '../../templates/homeFeed/LibraryFilterMenu' +import { LIBRARY_LEFT_MENU_WIDTH } from '../../templates/navMenu/LibraryMenu' import { LibraryHoverActions } from './LibraryHoverActions' import { useHover, diff --git a/packages/web/components/patterns/LoadingView.tsx b/packages/web/components/patterns/LoadingView.tsx index b2a496fe7..2f71e8c60 100644 --- a/packages/web/components/patterns/LoadingView.tsx +++ b/packages/web/components/patterns/LoadingView.tsx @@ -6,7 +6,7 @@ type LoadingViewProps = { } export function LoadingView(props: LoadingViewProps): JSX.Element { - applyStoredTheme(false) + applyStoredTheme() return ( - - - ) diff --git a/packages/web/components/templates/PrimaryDropdown.tsx b/packages/web/components/templates/PrimaryDropdown.tsx index 5c44615e6..bed04ebeb 100644 --- a/packages/web/components/templates/PrimaryDropdown.tsx +++ b/packages/web/components/templates/PrimaryDropdown.tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import { Moon, Sun } from 'phosphor-react' import { ReactNode, useCallback, useState } from 'react' import { useGetViewerQuery } from '../../lib/networking/queries/useGetViewerQuery' -import { currentTheme, updateTheme } from '../../lib/themeUpdater' +import { getCurrentLocalTheme, updateTheme } from '../../lib/themeUpdater' import { Avatar } from '../elements/Avatar' import { AvatarDropdown } from '../elements/AvatarDropdown' import { @@ -271,7 +271,7 @@ export const StyledToggleButton = styled('button', { }) function ThemeSection(props: PrimaryDropdownProps): JSX.Element { - const [displayTheme, setDisplayTheme] = useState(currentTheme()) + const [displayTheme, setDisplayTheme] = useState(getCurrentLocalTheme()) const doUpdateTheme = useCallback( (newTheme: ThemeId) => { @@ -315,7 +315,7 @@ function ThemeSection(props: PrimaryDropdownProps): JSX.Element { }} > { doUpdateTheme(ThemeId.Light) }} @@ -324,7 +324,7 @@ function ThemeSection(props: PrimaryDropdownProps): JSX.Element { { doUpdateTheme(ThemeId.Dark) }} diff --git a/packages/web/components/templates/PrimaryLayout.tsx b/packages/web/components/templates/PrimaryLayout.tsx index e08f3f08b..3ccd71fd0 100644 --- a/packages/web/components/templates/PrimaryLayout.tsx +++ b/packages/web/components/templates/PrimaryLayout.tsx @@ -12,6 +12,7 @@ import { deinitAnalytics, setupAnalytics } from '../../lib/analytics' import { primaryCommands } from '../../lib/keyboardShortcuts/navigationShortcuts' import { applyStoredTheme } from '../../lib/themeUpdater' import { logout } from '../../lib/logout' +import { useApplyLocalTheme } from '../../lib/hooks/useApplyLocalTheme' type PrimaryLayoutProps = { children: ReactNode @@ -23,7 +24,7 @@ type PrimaryLayoutProps = { } export function PrimaryLayout(props: PrimaryLayoutProps): JSX.Element { - applyStoredTheme(false) + useApplyLocalTheme() const { viewerData } = useGetViewerQuery() const router = useRouter() diff --git a/packages/web/components/templates/SettingsLayout.tsx b/packages/web/components/templates/SettingsLayout.tsx index a7df5dedd..6f05780f7 100644 --- a/packages/web/components/templates/SettingsLayout.tsx +++ b/packages/web/components/templates/SettingsLayout.tsx @@ -11,7 +11,7 @@ import { KeyboardShortcutListModal } from './KeyboardShortcutListModal' import { PageMetaData } from '../patterns/PageMetaData' import { DEFAULT_HEADER_HEIGHT } from './homeFeed/HeaderSpacer' import { logout } from '../../lib/logout' -import { SettingsMenu } from './SettingsMenu' +import { SettingsMenu } from './navMenu/SettingsMenu' type SettingsLayoutProps = { title?: string @@ -26,7 +26,7 @@ export function SettingsLayout(props: SettingsLayoutProps): JSX.Element { useState(false) useKeyboardShortcuts(navigationCommands(router)) - applyStoredTheme(false) + applyStoredTheme() const showLogout = useCallback(() => { setShowLogoutConfirmation(true) diff --git a/packages/web/components/templates/article/EpubContainer.tsx b/packages/web/components/templates/article/EpubContainer.tsx index a4c90f30b..ea9ae366e 100644 --- a/packages/web/components/templates/article/EpubContainer.tsx +++ b/packages/web/components/templates/article/EpubContainer.tsx @@ -3,7 +3,11 @@ import { Box, VStack } from '../../elements/LayoutPrimitives' import { v4 as uuidv4 } from 'uuid' import { nanoid } from 'nanoid' import { useState, useEffect, useRef, useMemo } from 'react' -import { currentTheme, getTheme, isDarkTheme } from '../../../lib/themeUpdater' +import { + getCurrentLocalTheme, + getTheme, + isDarkTheme, +} from '../../../lib/themeUpdater' import PSPDFKit from 'pspdfkit' import { Instance, HighlightAnnotation, List, Annotation, Rect } from 'pspdfkit' import type { Highlight } from '../../../lib/networking/fragments/highlightFragment' @@ -38,15 +42,13 @@ type EpubPatch = { export default function EpubContainer(props: EpubContainerProps): JSX.Element { const epubRef = useRef(null) const renditionRef = useRef(undefined) - const [shareTarget, setShareTarget] = useState( - undefined - ) + const [shareTarget, setShareTarget] = + useState(undefined) const [touchStart, setTouchStart] = useState(0) const [notebookKey, setNotebookKey] = useState(uuidv4()) const [noteTarget, setNoteTarget] = useState(undefined) - const [noteTargetPageIndex, setNoteTargetPageIndex] = useState< - number | undefined - >(undefined) + const [noteTargetPageIndex, setNoteTargetPageIndex] = + useState(undefined) const highlightsRef = useRef([]) const book = useMemo(() => { @@ -102,7 +104,7 @@ export default function EpubContainer(props: EpubContainerProps): JSX.Element { } }) - const themeId = currentTheme() + const themeId = getCurrentLocalTheme() if (themeId) { const readerTheme = getTheme(themeId) renditionRef.current.themes.override( diff --git a/packages/web/components/templates/article/ReaderSettingsControl.tsx b/packages/web/components/templates/article/ReaderSettingsControl.tsx index 3c0c0665f..57d4aecb1 100644 --- a/packages/web/components/templates/article/ReaderSettingsControl.tsx +++ b/packages/web/components/templates/article/ReaderSettingsControl.tsx @@ -13,10 +13,17 @@ import { TickedRangeSlider } from '../../elements/TickedRangeSlider' import { showSuccessToast } from '../../../lib/toastHelpers' import { ReaderSettings } from '../../../lib/hooks/useReaderSettings' import { useCallback, useState } from 'react' -import { currentThemeName, updateTheme } from '../../../lib/themeUpdater' +import { + getCurrentLocalTheme, + 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 { Checkbox } from '@radix-ui/react-checkbox' +import { useCurrentTheme } from '../../../lib/hooks/useCurrentTheme' +import { useDarkModeListener } from '../../../lib/hooks/useDarkModeListener' type ReaderSettingsProps = { readerSettings: ReaderSettings @@ -564,7 +571,9 @@ function LayoutControls(props: LayoutControlsProps): JSX.Element { } function ThemeSelector(): JSX.Element { - const [currentTheme, setCurrentTheme] = useState(currentThemeName()) + const isDarkMode = useDarkModeListener() + const { currentTheme, setCurrentTheme, resetSystemTheme } = useCurrentTheme() + return ( - Themes + + Themes + { + console.log('clicked use system') + updateTheme(ThemeId.System) + }} + > + + { + if (event.target.checked) { + setCurrentTheme(ThemeId.System) + } else { + resetSystemTheme() + } + event.stopPropagation() + }} + > + + + { - updateTheme(ThemeId.Light) - setCurrentTheme(currentThemeName()) + setCurrentTheme(ThemeId.Light) }} > {currentTheme == ThemeId.Light && ( @@ -635,8 +686,7 @@ function ThemeSelector(): JSX.Element { }} data-state={currentTheme == ThemeId.Dark ? 'selected' : 'unselected'} onClick={() => { - updateTheme(ThemeId.Dark) - setCurrentTheme(currentThemeName()) + setCurrentTheme(ThemeId.Dark) }} > {currentTheme == ThemeId.Dark && } @@ -663,8 +713,7 @@ function ThemeSelector(): JSX.Element { }} data-state={currentTheme == ThemeId.Sepia ? 'selected' : 'unselected'} onClick={() => { - updateTheme(ThemeId.Sepia) - setCurrentTheme(currentThemeName()) + setCurrentTheme(ThemeId.Sepia) }} > {currentTheme == ThemeId.Sepia && } @@ -693,8 +742,7 @@ function ThemeSelector(): JSX.Element { currentTheme == ThemeId.Apollo ? 'selected' : 'unselected' } onClick={() => { - updateTheme(ThemeId.Apollo) - setCurrentTheme(currentThemeName()) + setCurrentTheme(ThemeId.Apollo) }} > {currentTheme == ThemeId.Apollo && ( diff --git a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx index dc7ca5777..361f24f11 100644 --- a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx +++ b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx @@ -1,6 +1,6 @@ import { Box } from '../../elements/LayoutPrimitives' import { useMemo } from 'react' -import { LIBRARY_LEFT_MENU_WIDTH } from './LibraryFilterMenu' +import { LIBRARY_LEFT_MENU_WIDTH } from '../navMenu/LibraryMenu' import { LayoutType } from './HomeFeedContainer' import { SuggestionBox, SuggestionAction } from '../../elements/SuggestionBox' diff --git a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx index 0bf63a5cf..b6313765c 100644 --- a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx +++ b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx @@ -36,7 +36,7 @@ import { AddLinkModal } from './AddLinkModal' import { EditLibraryItemModal } from './EditItemModals' import { EmptyLibrary } from './EmptyLibrary' import { HighlightItemsLayout } from './HighlightsLayout' -import { LibraryFilterMenu } from './LibraryFilterMenu' +import { LibraryFilterMenu } from '../navMenu/LibraryMenu' import { LibraryHeader, MultiSelectMode, @@ -96,13 +96,11 @@ export function HomeFeedContainer(): JSX.Element { const gridContainerRef = useRef(null) - const [labelsTarget, setLabelsTarget] = useState( - undefined - ) + const [labelsTarget, setLabelsTarget] = + useState(undefined) - const [notebookTarget, setNotebookTarget] = useState( - undefined - ) + const [notebookTarget, setNotebookTarget] = + useState(undefined) const [showAddLinkModal, setShowAddLinkModal] = useState(false) const [showEditTitleModal, setShowEditTitleModal] = useState(false) diff --git a/packages/web/components/templates/homeFeed/LibraryHeader.tsx b/packages/web/components/templates/homeFeed/LibraryHeader.tsx index 3d444209f..a178bd4b7 100644 --- a/packages/web/components/templates/homeFeed/LibraryHeader.tsx +++ b/packages/web/components/templates/homeFeed/LibraryHeader.tsx @@ -16,7 +16,7 @@ import { import { LayoutType } from './HomeFeedContainer' import { OmnivoreSmallLogo } from '../../elements/images/OmnivoreNameLogo' import { DEFAULT_HEADER_HEIGHT, HeaderSpacer } from './HeaderSpacer' -import { LIBRARY_LEFT_MENU_WIDTH } from '../../templates/homeFeed/LibraryFilterMenu' +import { LIBRARY_LEFT_MENU_WIDTH } from '../navMenu/LibraryMenu' import { CardCheckbox } from '../../patterns/LibraryCards/LibraryCardStyles' import { Dropdown, DropdownOption } from '../../elements/DropdownElements' import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation' @@ -36,7 +36,6 @@ import { HeaderCheckboxIcon } from '../../elements/icons/HeaderCheckboxIcon' import { HeaderSearchIcon } from '../../elements/icons/HeaderSearchIcon' import { HeaderToggleGridIcon } from '../../elements/icons/HeaderToggleGridIcon' import { HeaderToggleListIcon } from '../../elements/icons/HeaderToggleListIcon' -import useWindowDimensions from '../../../lib/hooks/useGetWindowDimensions' export type MultiSelectMode = 'off' | 'none' | 'some' | 'visible' | 'search' @@ -124,20 +123,6 @@ export function LibraryHeader(props: LibraryHeaderProps): JSX.Element { } function LargeHeaderLayout(props: LibraryHeaderProps): JSX.Element { - const dimensions = useWindowDimensions() - const [showSearchBar, setShowSearchBar] = useState(false) - const [pinnedSearches, setPinnedSearches] = usePersistedState< - PinnedSearch[] | null - >({ - key: `--library-pinned-searches`, - initialValue: [], - isSessionStorage: false, - }) - - const isWideWindow = useMemo(() => { - return dimensions.width >= 480 - }, [dimensions]) - return ( ) : ( - <> - {(!showSearchBar || isWideWindow) && ( - <> - - - - - - )} - - {showSearchBar ? ( - - ) : ( - - )} - - - + )} ) } +const HeaderControls = (props: LibraryHeaderProps): JSX.Element => { + const [showSearchBar, setShowSearchBar] = useState(false) + return ( + <> + + + + + + {showSearchBar ? ( + + ) : ( + + )} + + + + ) +} + type MenuHeaderButtonProps = { showFilterMenu: boolean setShowFilterMenu: (show: boolean) => void diff --git a/packages/web/components/templates/navMenu/Footer.tsx b/packages/web/components/templates/navMenu/Footer.tsx new file mode 100644 index 000000000..f8b0a9804 --- /dev/null +++ b/packages/web/components/templates/navMenu/Footer.tsx @@ -0,0 +1,50 @@ +import { HStack, SpanBox } from '../../elements/LayoutPrimitives' +import { SplitButton } from '../../elements/SplitButton' +import { PrimaryDropdown } from '../PrimaryDropdown' +import { LIBRARY_LEFT_MENU_WIDTH } from './LibraryMenu' + +type NavMenuFooterProps = { + setShowAddLinkModal?: (show: true) => void +} + +export const NavMenuFooter = (props: NavMenuFooterProps): JSX.Element => { + return ( + + + + {props.setShowAddLinkModal && ( + { + props.setShowAddLinkModal && props.setShowAddLinkModal(true) + }} + /> + )} + + + ) +} diff --git a/packages/web/components/templates/homeFeed/LibraryFilterMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx similarity index 95% rename from packages/web/components/templates/homeFeed/LibraryFilterMenu.tsx rename to packages/web/components/templates/navMenu/LibraryMenu.tsx index 958b30b73..5b015216b 100644 --- a/packages/web/components/templates/homeFeed/LibraryFilterMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx @@ -22,6 +22,7 @@ import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' import { SplitButton } from '../../elements/SplitButton' import { AvatarDropdown } from '../../elements/AvatarDropdown' import { PrimaryDropdown } from '../PrimaryDropdown' +import { NavMenuFooter } from './Footer' export const LIBRARY_LEFT_MENU_WIDTH = '275px' @@ -122,7 +123,7 @@ export function LibraryFilterMenu(props: LibraryFilterMenuProps): JSX.Element { -