From 9a44b8a82051e634d3b8fb8eeec01d1fc66d7b2e Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 30 Oct 2023 11:41:18 +0000 Subject: [PATCH 01/17] switch sidebar mode between lg/md --- apps/app/src/stores/ui.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/app/src/stores/ui.tsx b/apps/app/src/stores/ui.tsx index ae5f4660602..29081bf1ecd 100644 --- a/apps/app/src/stores/ui.tsx +++ b/apps/app/src/stores/ui.tsx @@ -250,28 +250,28 @@ type DetectSidebarModeUtils = { } export const useSidebarMode = (): SWRResponseWithUtils => { - const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd(); + const { data: isDeviceSmallerThanLg } = useIsDeviceSmallerThanLg(); const { data: editorMode } = useEditorMode(); const { data: isCollapsedModeUnderDockMode } = usePreferCollapsedMode(); - const condition = isDeviceSmallerThanMd != null && editorMode != null && isCollapsedModeUnderDockMode != null; + const condition = isDeviceSmallerThanLg != null && editorMode != null && isCollapsedModeUnderDockMode != null; const isEditorMode = editorMode === EditorMode.Editor; const fetcher = useCallback(( - [, isDeviceSmallerThanMd, isEditorMode, isCollapsedModeUnderDockMode]: [Key, boolean|undefined, boolean|undefined, boolean|undefined], + [, isDeviceSmallerThanLg, isEditorMode, isCollapsedModeUnderDockMode]: [Key, boolean|undefined, boolean|undefined, boolean|undefined], ) => { - if (isDeviceSmallerThanMd) { + if (isDeviceSmallerThanLg) { return SidebarMode.DRAWER; } return isEditorMode || isCollapsedModeUnderDockMode ? SidebarMode.COLLAPSED : SidebarMode.DOCK; }, []); const swrResponse = useSWRImmutable( - condition ? ['sidebarMode', isDeviceSmallerThanMd, isEditorMode, isCollapsedModeUnderDockMode] : null, + condition ? ['sidebarMode', isDeviceSmallerThanLg, isEditorMode, isCollapsedModeUnderDockMode] : null, // calcDrawerMode, fetcher, - { fallbackData: fetcher(['sidebarMode', isDeviceSmallerThanMd, isEditorMode, isCollapsedModeUnderDockMode]) }, + { fallbackData: fetcher(['sidebarMode', isDeviceSmallerThanLg, isEditorMode, isCollapsedModeUnderDockMode]) }, ); const _isDrawerMode = useCallback(() => swrResponse.data === SidebarMode.DRAWER, [swrResponse.data]); From 972a253f4b15f9c222a6dcaacd9b2df298f32e42 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 30 Oct 2023 13:45:33 +0000 Subject: [PATCH 02/17] clean code --- apps/app/src/components/IdenticalPathPage.module.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/app/src/components/IdenticalPathPage.module.scss b/apps/app/src/components/IdenticalPathPage.module.scss index 54332f2cfc7..8704f9f8771 100644 --- a/apps/app/src/components/IdenticalPathPage.module.scss +++ b/apps/app/src/components/IdenticalPathPage.module.scss @@ -1,6 +1 @@ @use '@growi/ui/src/styles/molecules/page_list'; -@use '~/styles/molecules/page-accessories-control'; - -.grw-page-accessories-control :global { - @extend %grw-page-accessories-control; -} From 32f0221773b5554b559cad5d3fd511b39e3f2685 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 30 Oct 2023 13:46:43 +0000 Subject: [PATCH 03/17] improve layout --- .../src/components/Layout/PageViewLayout.tsx | 4 +- .../PageAccessoriesControl.module.scss | 30 +++++++++ .../PageAccessoriesControl.tsx | 42 +++++++++++++ .../PageSideContents.module.scss | 5 +- .../PageSideContents/PageSideContents.tsx | 63 +++++++------------ .../molecules/_page-accessories-control.scss | 16 ----- 6 files changed, 99 insertions(+), 61 deletions(-) create mode 100644 apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss create mode 100644 apps/app/src/components/PageSideContents/PageAccessoriesControl.tsx delete mode 100644 apps/app/src/styles/molecules/_page-accessories-control.scss diff --git a/apps/app/src/components/Layout/PageViewLayout.tsx b/apps/app/src/components/Layout/PageViewLayout.tsx index 08375d2e90b..7e8b079748a 100644 --- a/apps/app/src/components/Layout/PageViewLayout.tsx +++ b/apps/app/src/components/Layout/PageViewLayout.tsx @@ -21,11 +21,11 @@ export const PageViewLayout = (props: Props): JSX.Element => { { headerContents != null && headerContents } { sideContents != null ? ( -
+
{children}
-
+
{sideContents}
diff --git a/apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss b/apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss new file mode 100644 index 00000000000..e47fe9a9af2 --- /dev/null +++ b/apps/app/src/components/PageSideContents/PageAccessoriesControl.module.scss @@ -0,0 +1,30 @@ +@use '@growi/core/scss/bootstrap/init' as bs; + +.btn-page-accessories :global { + display: flex; + align-items: center; + padding: 6px 8px; + + .grw-labels { + flex-grow: 1; + align-items: center; + justify-content: space-between; + } +} + +// smaller than lg +@include bs.media-breakpoint-down(md) { + .btn-page-accessories :global { + .material-symbols-outlined { + font-size: 2em; + } + } +} + +// larger than lg +@include bs.media-breakpoint-up(md) { + .btn-page-accessories :global { + flex-grow: 1; + padding: 1px 5px 1px 10px; + } +} diff --git a/apps/app/src/components/PageSideContents/PageAccessoriesControl.tsx b/apps/app/src/components/PageSideContents/PageAccessoriesControl.tsx new file mode 100644 index 00000000000..154ece37a26 --- /dev/null +++ b/apps/app/src/components/PageSideContents/PageAccessoriesControl.tsx @@ -0,0 +1,42 @@ +import { type ReactNode, memo } from 'react'; + +import CountBadge from '../Common/CountBadge'; + + +import styles from './PageAccessoriesControl.module.scss'; + +const moduleClass = styles['btn-page-accessories']; + + +type Props = { + className?: string, + icon: ReactNode, + label: ReactNode, + count?: number, + onClick?: () => void, +} + +export const PageAccessoriesControl = memo((props: Props): JSX.Element => { + const { + icon, label, count, + className, + onClick, + } = props; + + return ( + + ); +}); diff --git a/apps/app/src/components/PageSideContents/PageSideContents.module.scss b/apps/app/src/components/PageSideContents/PageSideContents.module.scss index 9f93e7a7573..b2c617c8b74 100644 --- a/apps/app/src/components/PageSideContents/PageSideContents.module.scss +++ b/apps/app/src/components/PageSideContents/PageSideContents.module.scss @@ -1,5 +1,2 @@ -@use '~/styles/molecules/page-accessories-control'; - -.grw-page-accessories-control :global { - @extend %grw-page-accessories-control; +.grw-page-accessories-controls :global { } diff --git a/apps/app/src/components/PageSideContents/PageSideContents.tsx b/apps/app/src/components/PageSideContents/PageSideContents.tsx index 8a953ddf21d..e6d1491e874 100644 --- a/apps/app/src/components/PageSideContents/PageSideContents.tsx +++ b/apps/app/src/components/PageSideContents/PageSideContents.tsx @@ -4,7 +4,7 @@ import { getIdForRef, type IPageHasId, type IPageInfoForOperation } from '@growi import { pagePathUtils } from '@growi/core/dist/utils'; import { useTranslation } from 'next-i18next'; import dynamic from 'next/dynamic'; -import { Link } from 'react-scroll'; +import { scroller } from 'react-scroll'; import { useUpdateStateAfterSave } from '~/client/services/page-operation'; import { apiPost } from '~/client/util/apiv1-client'; @@ -21,6 +21,7 @@ import { PageTagsSkeleton } from '../PageTags'; import TableOfContents from '../TableOfContents'; import styles from './PageSideContents.module.scss'; +import { PageAccessoriesControl } from './PageAccessoriesControl'; const { isTopPage, isUsersHomepage, isTrashPage } = pagePathUtils; @@ -104,48 +105,32 @@ export const PageSideContents = (props: PageSideContentsProps): JSX.Element => { {/* Tags */} - {/* Page list */} -
+
+ {/* Page list */} {!isSharedUser && ( - +
+ subject} + label={t('page_list')} + // Do not display CountBadge if '/trash/*': https://github.com/weseek/growi/pull/7600 + count={ !isTrash && pageInfo != null ? (pageInfo as IPageInfoForOperation).descendantCount : undefined } + onClick={() => openDescendantPageListModal(pagePath)} /> +
+ )} + + {/* Comments */} + {!isTopPagePath && ( +
+ chat} + label="Comments" + count={ pageInfo != null ? (pageInfo as IPageInfoForOperation).commentCount : undefined } + onClick={() => scroller.scrollTo('comments-container', { smooth: false, offset: -120 })} /> +
)}
- {/* Comments */} - {!isTopPagePath && ( -
- - - -
- )} - -
+
{isUsersHomepagePath && }
diff --git a/apps/app/src/styles/molecules/_page-accessories-control.scss b/apps/app/src/styles/molecules/_page-accessories-control.scss deleted file mode 100644 index 91f0c7945fb..00000000000 --- a/apps/app/src/styles/molecules/_page-accessories-control.scss +++ /dev/null @@ -1,16 +0,0 @@ -%grw-page-accessories-control { - .grw-btn-page-accessories { - padding-right: 1rem; - padding-left: 1rem; - - svg { - width: 16px; - height: 16px; - } - } - .grw-page-accessories-control-icon { - display: flex; - justify-content: center; - width: 20px; - } -} From 3f663fa57346ed686babbf86042e788cab08b874 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 30 Oct 2023 14:10:23 +0000 Subject: [PATCH 04/17] refactor scss --- .../Layout/PageViewLayout.module.scss | 24 +++++++++++++ .../src/components/Layout/PageViewLayout.tsx | 2 +- .../Navbar/GrowiContextualSubNavigation.tsx | 35 +++++++++---------- apps/app/src/styles/_layout.scss | 16 --------- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/apps/app/src/components/Layout/PageViewLayout.module.scss b/apps/app/src/components/Layout/PageViewLayout.module.scss index 0185bcada1b..5572d4306c8 100644 --- a/apps/app/src/components/Layout/PageViewLayout.module.scss +++ b/apps/app/src/components/Layout/PageViewLayout.module.scss @@ -1,3 +1,27 @@ +@use '@growi/core/scss/bootstrap/init' as bs; + .page-view-layout :global { min-height: calc(100vh - 48px - 250px); // 100vh - subnavigation height - page-comments-row minimum height + + .grw-side-contents-container { + margin-bottom: 1rem; + + @include bs.media-breakpoint-up(lg) { + width: 250px; + min-width: 250px; + margin-left: 30px; + } + } +} + +// sticky +.page-view-layout :global { + .grw-side-contents-sticky-container { + position: sticky; + + $subnavigation-height: 50px; + $page-view-layout-margin-top: 32px; + $page-path-nav-height: 99px; + top: calc($subnavigation-height + $page-view-layout-margin-top + $page-path-nav-height + 4px); + } } diff --git a/apps/app/src/components/Layout/PageViewLayout.tsx b/apps/app/src/components/Layout/PageViewLayout.tsx index 7e8b079748a..9c11345ba0d 100644 --- a/apps/app/src/components/Layout/PageViewLayout.tsx +++ b/apps/app/src/components/Layout/PageViewLayout.tsx @@ -16,7 +16,7 @@ export const PageViewLayout = (props: Props): JSX.Element => { return ( <> -
+
{ headerContents != null && headerContents } { sideContents != null diff --git a/apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx b/apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx index 571ad2ea7d4..cd16d3441e5 100644 --- a/apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx +++ b/apps/app/src/components/Navbar/GrowiContextualSubNavigation.tsx @@ -335,24 +335,23 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): `} data-testid="grw-contextual-sub-nav" > -
- {pageId != null && ( - - )} -
+ {pageId != null && ( + + )} + {isAbleToChangeEditorMode && ( Date: Mon, 30 Oct 2023 15:01:49 +0000 Subject: [PATCH 05/17] WIP: add toggler --- .../Sidebar/AppTitle/AppTitle.module.scss | 1 + apps/app/src/components/Sidebar/Sidebar.tsx | 12 +++++++++--- .../Sidebar/SidebarHead/ToggleCollapseButton.tsx | 16 +++++++++++----- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss b/apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss index d7c3eaf6c25..429304b84de 100644 --- a/apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss +++ b/apps/app/src/components/Sidebar/AppTitle/AppTitle.module.scss @@ -29,6 +29,7 @@ .on-subnavigation { $grw-contextual-sub-navigation-width: 500px; + top: 0; left: var.$grw-sidebar-nav-width; // set width for truncation width: calc(100vw - $grw-contextual-sub-navigation-width); diff --git a/apps/app/src/components/Sidebar/Sidebar.tsx b/apps/app/src/components/Sidebar/Sidebar.tsx index aaa394a281f..2c7284a6cc8 100644 --- a/apps/app/src/components/Sidebar/Sidebar.tsx +++ b/apps/app/src/components/Sidebar/Sidebar.tsx @@ -21,6 +21,7 @@ import { SidebarHead } from './SidebarHead'; import { SidebarNav, type SidebarNavProps } from './SidebarNav'; import styles from './Sidebar.module.scss'; +import { ToggleCollapseButton } from './SidebarHead/ToggleCollapseButton'; const SidebarContents = dynamic(() => import('./SidebarContents').then(mod => mod.SidebarContents), { ssr: false }); @@ -168,7 +169,7 @@ const DrawableContainer = memo((props: DrawableContainerProps): JSX.Element => { export const Sidebar = (): JSX.Element => { - const { data: sidebarMode, isCollapsedMode } = useSidebarMode(); + const { data: sidebarMode, isDrawerMode, isDockMode } = useSidebarMode(); // css styles const grwSidebarClass = styles['grw-sidebar']; @@ -188,10 +189,15 @@ export const Sidebar = (): JSX.Element => { return ( <> - { sidebarMode != null && isCollapsedMode() && } + { sidebarMode != null && isDrawerMode() && ( +
+ +
+ ) } + { sidebarMode != null && !isDockMode() && } - { sidebarMode != null && !isCollapsedMode() && } + { sidebarMode != null && isDockMode() && } diff --git a/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx b/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx index bb39e9b86df..16f8c680714 100644 --- a/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx +++ b/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx @@ -1,4 +1,4 @@ -import { memo, useCallback } from 'react'; +import { memo, useCallback, useMemo } from 'react'; import { useCollapsedContentsOpened, usePreferCollapsedMode, useDrawerOpened, useSidebarMode, @@ -10,7 +10,7 @@ import styles from './ToggleCollapseButton.module.scss'; export const ToggleCollapseButton = memo((): JSX.Element => { - const { isDrawerMode, isCollapsedMode, isDockMode } = useSidebarMode(); + const { isDrawerMode, isCollapsedMode } = useSidebarMode(); const { data: isDrawerOpened, mutate: mutateDrawerOpened } = useDrawerOpened(); const { mutate: mutatePreferCollapsedMode } = usePreferCollapsedMode(); const { mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened(); @@ -25,9 +25,15 @@ export const ToggleCollapseButton = memo((): JSX.Element => { }, [isCollapsedMode, mutateCollapsedContentsOpened, mutatePreferCollapsedMode]); const rotationClass = isCollapsedMode() ? 'rotate180' : ''; - const icon = isDrawerMode() || isDockMode() - ? 'first_page' - : 'keyboard_double_arrow_left'; + const icon = useMemo(() => { + if (isDrawerMode()) { + return 'star'; + } + else if (isCollapsedMode()) { + return 'keyboard_double_arrow_left'; + } + return 'first_page'; + }, []); return ( +
+ +
); }; - -export default DrawerToggler; diff --git a/apps/app/src/components/Common/DrawerToggler/index.ts b/apps/app/src/components/Common/DrawerToggler/index.ts new file mode 100644 index 00000000000..be724a31772 --- /dev/null +++ b/apps/app/src/components/Common/DrawerToggler/index.ts @@ -0,0 +1 @@ +export * from './DrawerToggler'; diff --git a/apps/app/src/components/Sidebar/Sidebar.tsx b/apps/app/src/components/Sidebar/Sidebar.tsx index 2c7284a6cc8..e2f3bf39209 100644 --- a/apps/app/src/components/Sidebar/Sidebar.tsx +++ b/apps/app/src/components/Sidebar/Sidebar.tsx @@ -15,13 +15,14 @@ import { useSidebarMode, } from '~/stores/ui'; +import { DrawerToggler } from '../Common/DrawerToggler'; + import { AppTitleOnSidebarHead, AppTitleOnSubnavigation } from './AppTitle/AppTitle'; import { ResizableArea } from './ResizableArea/ResizableArea'; import { SidebarHead } from './SidebarHead'; import { SidebarNav, type SidebarNavProps } from './SidebarNav'; import styles from './Sidebar.module.scss'; -import { ToggleCollapseButton } from './SidebarHead/ToggleCollapseButton'; const SidebarContents = dynamic(() => import('./SidebarContents').then(mod => mod.SidebarContents), { ssr: false }); @@ -190,9 +191,9 @@ export const Sidebar = (): JSX.Element => { return ( <> { sidebarMode != null && isDrawerMode() && ( -
- -
+ + menu + ) } { sidebarMode != null && !isDockMode() && } diff --git a/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx b/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx index 16f8c680714..ab027096e38 100644 --- a/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx +++ b/apps/app/src/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx @@ -26,14 +26,11 @@ export const ToggleCollapseButton = memo((): JSX.Element => { const rotationClass = isCollapsedMode() ? 'rotate180' : ''; const icon = useMemo(() => { - if (isDrawerMode()) { - return 'star'; - } - else if (isCollapsedMode()) { + if (isCollapsedMode()) { return 'keyboard_double_arrow_left'; } return 'first_page'; - }, []); + }, [isCollapsedMode]); return ( - ); - const renderExpandButton = () => (
); - const isCollapsedOptionsSelectorEnabled = isDeviceSmallerThanMd; + const isCollapsedOptionsSelectorEnabled = !isDeviceLargerThanLg; return (
{/* Collapsed SlackNotification */} {isSlackConfigured && ( - +
)}
From 363a3f237f9ac2484939789e75ecdcf2f4afa35c Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 30 Oct 2023 19:33:08 +0000 Subject: [PATCH 17/17] adjust GrowiNavbarBottom --- .../Navbar/GrowiNavbarBottom.module.scss | 15 +++++++++ .../components/Navbar/GrowiNavbarBottom.tsx | 31 +++++++++++++------ apps/app/src/styles/_variables.scss | 2 +- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss b/apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss index 4aeda71d497..c1e78bd4daf 100644 --- a/apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss +++ b/apps/app/src/components/Navbar/GrowiNavbarBottom.module.scss @@ -14,3 +14,18 @@ bottom: #{-1 * var.$grw-navbar-bottom-height}; } } + + +// centering icons +.grw-navbar-bottom :global { + .nav-link { + display: flex; + align-items: center; + } +} + +// == Colors +.grw-navbar-bottom { + background-color: rgba(var(--bs-body-bg-rgb), 0.7); + backdrop-filter: blur(35px); +} diff --git a/apps/app/src/components/Navbar/GrowiNavbarBottom.tsx b/apps/app/src/components/Navbar/GrowiNavbarBottom.tsx index c58093d1e9e..228e016f758 100644 --- a/apps/app/src/components/Navbar/GrowiNavbarBottom.tsx +++ b/apps/app/src/components/Navbar/GrowiNavbarBottom.tsx @@ -18,7 +18,7 @@ export const GrowiNavbarBottom = (): JSX.Element => { const { data: currentPagePath } = useCurrentPagePath(); const { data: isSearchPage } = useIsSearchPage(); - const additionalClasses = ['grw-navbar-bottom', styles['grw-navbar-bottom']]; + const additionalClasses = [styles['grw-navbar-bottom']]; if (isDrawerOpened) { additionalClasses.push('grw-navbar-bottom-drawer-opened'); } @@ -34,18 +34,29 @@ export const GrowiNavbarBottom = (): JSX.Element => {
) } -
+
-
diff --git a/apps/app/src/styles/_variables.scss b/apps/app/src/styles/_variables.scss index 6dc5e587843..a690fc7a270 100644 --- a/apps/app/src/styles/_variables.scss +++ b/apps/app/src/styles/_variables.scss @@ -8,7 +8,7 @@ $grw-marker-green: #6f6; //== Layout $grw-sidebar-nav-width: 48px; -$grw-navbar-bottom-height: 48px; +$grw-navbar-bottom-height: 62px; $grw-editor-navbar-bottom-height: 48px; $grw-scroll-margin-top-in-view: 130px;