Skip to content

Commit ed39c01

Browse files
committed
♻️(frontent) improve summary feature
- Change Summary to Table of content - No dash before the title - Change font-size depend the type of heading - If more than 2 headings the panel is open by default - improve sticky - highligth the title where you are in the page
1 parent 748ebc8 commit ed39c01

File tree

7 files changed

+239
-74
lines changed

7 files changed

+239
-74
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to
2020
- ♻️ Allow null titles on documents for easier creation #234
2121
- 🛂(backend) stop to list public doc to everyone #234
2222
- 🚚(frontend) change visibility in share modal #235
23+
- ⚡️(frontend) Improve summary #244
2324

2425
## Fixed
2526

src/frontend/apps/e2e/__tests__/app-impress/doc-summary.spec.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ test.describe('Doc Summary', () => {
1515
await page.getByLabel('Open the document options').click();
1616
await page
1717
.getByRole('button', {
18-
name: 'Summary',
18+
name: 'Table of content',
1919
})
2020
.click();
2121

@@ -29,7 +29,7 @@ test.describe('Doc Summary', () => {
2929
await page.locator('.bn-block-outer').last().click();
3030

3131
// Create space to fill the viewport
32-
for (let i = 0; i < 6; i++) {
32+
for (let i = 0; i < 5; i++) {
3333
await page.keyboard.press('Enter');
3434
}
3535

@@ -40,25 +40,49 @@ test.describe('Doc Summary', () => {
4040
await page.locator('.bn-block-outer').last().click();
4141

4242
// Create space to fill the viewport
43-
for (let i = 0; i < 4; i++) {
43+
for (let i = 0; i < 5; i++) {
4444
await page.keyboard.press('Enter');
4545
}
4646

4747
await editor.locator('.bn-block-outer').last().fill('/');
4848
await page.getByText('Heading 3').click();
4949
await page.keyboard.type('Another World');
5050

51-
await expect(panel.getByText('Hello World')).toBeVisible();
52-
await expect(panel.getByText('Super World')).toBeVisible();
51+
const hello = panel.getByText('Hello World');
52+
const superW = panel.getByText('Super World');
53+
const another = panel.getByText('Another World');
5354

54-
await panel.getByText('Another World').click();
55+
await expect(hello).toBeVisible();
56+
await expect(hello).toHaveCSS('font-size', '19.2px');
57+
await expect(hello).toHaveAttribute('aria-selected', 'true');
58+
59+
await expect(superW).toBeVisible();
60+
await expect(superW).toHaveCSS('font-size', '16px');
61+
await expect(superW).toHaveAttribute('aria-selected', 'false');
62+
63+
await expect(another).toBeVisible();
64+
await expect(another).toHaveCSS('font-size', '12.8px');
65+
await expect(another).toHaveAttribute('aria-selected', 'false');
66+
67+
await hello.click();
68+
69+
await expect(editor.getByText('Hello World')).toBeInViewport();
70+
await expect(hello).toHaveAttribute('aria-selected', 'true');
71+
await expect(superW).toHaveAttribute('aria-selected', 'false');
72+
73+
await another.click();
5574

5675
await expect(editor.getByText('Hello World')).not.toBeInViewport();
76+
await expect(hello).toHaveAttribute('aria-selected', 'false');
77+
await expect(superW).toHaveAttribute('aria-selected', 'true');
5778

5879
await panel.getByText('Back to top').click();
5980
await expect(editor.getByText('Hello World')).toBeInViewport();
81+
await expect(hello).toHaveAttribute('aria-selected', 'true');
82+
await expect(superW).toHaveAttribute('aria-selected', 'false');
6083

6184
await panel.getByText('Go to bottom').click();
6285
await expect(editor.getByText('Hello World')).not.toBeInViewport();
86+
await expect(superW).toHaveAttribute('aria-selected', 'true');
6387
});
6488
});

src/frontend/apps/impress/src/components/Panel.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Box, Card, IconBG, Text } from '@/components';
55
import { useCunninghamTheme } from '@/cunningham';
66

77
interface PanelProps {
8-
title: string;
8+
title?: string;
99
setIsPanelOpen: (isOpen: boolean) => void;
1010
}
1111

@@ -53,11 +53,14 @@ export const Panel = ({
5353
{...closedOverridingStyles}
5454
>
5555
<Box
56-
$overflow="hidden"
56+
$overflow="inherit"
57+
$position="sticky"
5758
$css={`
59+
top: 0;
5860
opacity: ${isOpen ? '1' : '0'};
5961
transition: ${transition};
6062
`}
63+
$maxHeight="100%"
6164
>
6265
<Box
6366
$padding={{ all: 'small' }}
@@ -90,9 +93,11 @@ export const Panel = ({
9093
}}
9194
$radius="2px"
9295
/>
93-
<Text $weight="bold" $size="l" $theme="primary">
94-
{title}
95-
</Text>
96+
{title && (
97+
<Text $weight="bold" $size="l" $theme="primary">
98+
{title}
99+
</Text>
100+
)}
96101
</Box>
97102
{children}
98103
</Box>

src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Panel } from '@/components/Panel';
99
import { useCunninghamTheme } from '@/cunningham';
1010
import { DocHeader } from '@/features/docs/doc-header';
1111
import { Doc } from '@/features/docs/doc-management';
12-
import { Summary, useDocSummaryStore } from '@/features/docs/doc-summary';
12+
import { Summary } from '@/features/docs/doc-summary';
1313
import {
1414
VersionList,
1515
Versions,
@@ -28,8 +28,6 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
2828
query: { versionId },
2929
} = useRouter();
3030
const { isPanelVersionOpen, setIsPanelVersionOpen } = useDocVersionStore();
31-
const { isPanelSummaryOpen, setIsPanelSummaryOpen } = useDocSummaryStore();
32-
3331
const { t } = useTranslation();
3432

3533
const isVersion = versionId && typeof versionId === 'string';
@@ -72,11 +70,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
7270
<VersionList doc={doc} />
7371
</Panel>
7472
)}
75-
{isPanelSummaryOpen && (
76-
<Panel title={t('SUMMARY')} setIsPanelOpen={setIsPanelSummaryOpen}>
77-
<Summary doc={doc} />
78-
</Panel>
79-
)}
73+
<Summary doc={doc} />
8074
</Box>
8175
</>
8276
);

src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
9191
icon={<span className="material-icons">summarize</span>}
9292
size="small"
9393
>
94-
<Text $theme="primary">{t('Summary')}</Text>
94+
<Text $theme="primary">{t('Table of content')}</Text>
9595
</Button>
9696
<Button
9797
onClick={() => {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { BlockNoteEditor } from '@blocknote/core';
2+
import { useState } from 'react';
3+
4+
import { BoxButton, Text } from '@/components';
5+
import { useCunninghamTheme } from '@/cunningham';
6+
7+
const sizeMap: { [key: number]: string } = {
8+
1: '1.2rem',
9+
2: '1rem',
10+
3: '0.8rem',
11+
};
12+
13+
export type HeadingsHighlight = {
14+
headingId: string;
15+
isVisible: boolean;
16+
}[];
17+
18+
interface HeadingProps {
19+
editor: BlockNoteEditor;
20+
level: number;
21+
text: string;
22+
headingId: string;
23+
isHighlight: boolean;
24+
}
25+
26+
export const Heading = ({
27+
headingId,
28+
editor,
29+
isHighlight,
30+
level,
31+
text,
32+
}: HeadingProps) => {
33+
const [isHover, setIsHover] = useState(isHighlight);
34+
const { colorsTokens } = useCunninghamTheme();
35+
36+
return (
37+
<BoxButton
38+
key={headingId}
39+
onMouseOver={() => setIsHover(true)}
40+
onMouseLeave={() => setIsHover(false)}
41+
onClick={() => {
42+
editor.focus();
43+
editor.setTextCursorPosition(headingId, 'end');
44+
document.querySelector(`[data-id="${headingId}"]`)?.scrollIntoView({
45+
behavior: 'smooth',
46+
block: 'start',
47+
});
48+
}}
49+
>
50+
<Text
51+
$theme="primary"
52+
$padding={{ vertical: 'xtiny', left: 'tiny' }}
53+
$size={sizeMap[level]}
54+
$hasTransition
55+
$css={
56+
isHover || isHighlight
57+
? `box-shadow: -2px 0px 0px ${colorsTokens()[isHighlight ? 'primary-500' : 'primary-400']};`
58+
: ''
59+
}
60+
aria-selected={isHighlight}
61+
>
62+
{text}
63+
</Text>
64+
</BoxButton>
65+
);
66+
};

0 commit comments

Comments
 (0)