💫(frontend) fix the help button to the bottom in tree

The tree take a bit of time to load, during this
time the help button was not at the bottom of
the left panel. To fix this issue, we addded a
skeleton for the tree in wait for the tree to
load, by doing this, the help button
is always at the bottom.
This commit is contained in:
Anthony LC
2026-03-19 13:28:22 +01:00
parent 0867ccef1a
commit 0b37996899
7 changed files with 143 additions and 97 deletions
+4
View File
@@ -6,6 +6,10 @@ and this project adheres to
## [Unreleased]
### Changed
- 💫(frontend) fix the help button to the bottom in tree #2073
## [v4.8.2] - 2026-03-19
### Changed
@@ -18,6 +18,7 @@ import {
useMoveDoc,
useTrans,
} from '@/docs/doc-management';
import { TreeSkeleton } from '@/features/skeletons/components/TreeSkeleton';
import { CLASS_DOC_TITLE } from '../../doc-header';
import { KEY_DOC_TREE, useDocTree } from '../api/useDocTree';
@@ -257,7 +258,7 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
}, [currentDoc, treeContext]);
if (!treeContext || !treeContext.root) {
return null;
return <TreeSkeleton />;
}
return (
@@ -2,7 +2,6 @@ import { useRouter } from 'next/router';
import { css } from 'styled-components';
import { Box, SeparatedSection } from '@/components';
import { useDocStore } from '@/docs/doc-management';
import { LeftPanelTargetFilters } from './LefPanelTargetFilters';
import { LeftPanelDocContent } from './LeftPanelDocContent';
@@ -12,33 +11,35 @@ export const LeftPanelContent = () => {
const router = useRouter();
const isHome = router.pathname === '/';
const isDoc = router.pathname === '/docs/[id]';
const { currentDoc } = useDocStore();
return (
<>
{isHome && (
<>
<Box
$width="100%"
$css={css`
flex: 0 0 auto;
`}
className="--docs--home-left-panel-content"
>
<SeparatedSection showSeparator={false}>
<LeftPanelTargetFilters />
</SeparatedSection>
</Box>
<Box
$flex={1}
$width="100%"
$css="overflow-y: auto; overflow-x: hidden;"
>
<LeftPanelFavorites />
</Box>
</>
)}
{isDoc && currentDoc && <LeftPanelDocContent doc={currentDoc} />}
</>
);
if (isHome) {
return (
<>
<Box
$width="100%"
$css={css`
flex: 0 0 auto;
`}
className="--docs--home-left-panel-content"
>
<SeparatedSection showSeparator={false}>
<LeftPanelTargetFilters />
</SeparatedSection>
</Box>
<Box
$flex={1}
$width="100%"
$css="overflow-y: auto; overflow-x: hidden;"
>
<LeftPanelFavorites />
</Box>
</>
);
}
if (isDoc) {
return <LeftPanelDocContent />;
}
return null;
};
@@ -1,15 +1,13 @@
import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
import { Box } from '@/components';
import { Doc } from '@/docs/doc-management';
import { Doc, useDocStore } from '@/docs/doc-management';
import { DocTree } from '@/docs/doc-tree/';
import { TreeSkeleton } from '@/features/skeletons/components/TreeSkeleton';
export const LeftPanelDocContent = ({ doc }: { doc: Doc }) => {
export const LeftPanelDocContent = () => {
const tree = useTreeContext<Doc>();
if (!tree) {
return null;
}
const { currentDoc } = useDocStore();
return (
<Box
@@ -18,7 +16,11 @@ export const LeftPanelDocContent = ({ doc }: { doc: Doc }) => {
$css="width: 100%; overflow-y: auto; overflow-x: hidden;"
className="--docs--left-panel-doc-content"
>
<DocTree currentDoc={doc} />
{tree && currentDoc ? (
<DocTree currentDoc={currentDoc} />
) : (
<TreeSkeleton />
)}
</Box>
);
};
@@ -1,69 +1,12 @@
import { css, keyframes } from 'styled-components';
import { Box, BoxType } from '@/components';
import { Box } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { useResponsiveStore } from '@/stores';
const shimmer = keyframes`
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
`;
type SkeletonLineProps = Partial<BoxType>;
type SkeletonCircleProps = Partial<BoxType>;
import { SkeletonCircle, SkeletonLine } from './SkeletionUI';
export const DocEditorSkeleton = () => {
const { isDesktop } = useResponsiveStore();
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
const SkeletonLine = ({ $css, ...props }: SkeletonLineProps) => {
return (
<Box
$width="100%"
$height="16px"
$css={css`
background: linear-gradient(
90deg,
${colorsTokens['black-050']} 0%,
${colorsTokens['black-100']} 50%,
${colorsTokens['black-050']} 100%
);
background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear;
border-radius: 4px;
${$css}
`}
{...props}
/>
);
};
const SkeletonCircle = ({ $css, ...props }: SkeletonCircleProps) => {
return (
<Box
$width="32px"
$height="32px"
$css={css`
background: linear-gradient(
90deg,
${colorsTokens['black-050']} 0%,
${colorsTokens['black-100']} 50%,
${colorsTokens['black-050']} 100%
);
background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear;
border-radius: 50%;
${$css}
`}
{...props}
/>
);
};
const { spacingsTokens } = useCunninghamTheme();
return (
<>
@@ -0,0 +1,65 @@
import { css, keyframes } from 'styled-components';
import { Box, BoxType } from '@/components/Box';
import { useCunninghamTheme } from '@/cunningham/useCunninghamTheme';
const shimmer = keyframes`
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
`;
type SkeletonLineProps = Partial<BoxType>;
type SkeletonCircleProps = Partial<BoxType>;
export const SkeletonLine = ({ $css, ...props }: SkeletonLineProps) => {
const { colorsTokens } = useCunninghamTheme();
return (
<Box
$width="100%"
$height="16px"
$css={css`
background: linear-gradient(
90deg,
${colorsTokens['black-050']} 0%,
${colorsTokens['black-100']} 50%,
${colorsTokens['black-050']} 100%
);
background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear;
border-radius: 4px;
${$css}
`}
{...props}
/>
);
};
export const SkeletonCircle = ({ $css, ...props }: SkeletonCircleProps) => {
const { colorsTokens } = useCunninghamTheme();
return (
<Box
$width="32px"
$height="32px"
$css={css`
background: linear-gradient(
90deg,
${colorsTokens['black-050']} 0%,
${colorsTokens['black-100']} 50%,
${colorsTokens['black-050']} 100%
);
background-size: 1000px 100%;
animation: ${shimmer} 2s infinite linear;
border-radius: 50%;
${$css}
`}
{...props}
/>
);
};
@@ -0,0 +1,30 @@
import { Box } from '@/components';
import { SkeletonLine } from './SkeletionUI';
export const TreeSkeleton = () => {
return (
<Box className="--docs--tree-skeleton">
<SkeletonLine
$width="92%"
$height="40px"
$margin={{ left: 'sm', top: 'sm' }}
/>
<SkeletonLine
$width="92%"
$height="30px"
$margin={{ left: 'sm', top: 'sm' }}
/>
<SkeletonLine
$width="92%"
$height="30px"
$margin={{ left: 'sm', top: 'sm' }}
/>
<SkeletonLine
$width="92%"
$height="30px"
$margin={{ left: 'sm', top: 'sm' }}
/>
</Box>
);
};