Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to
- ♿️(frontend) add aria-hidden to decorative avatar SVGs in share modal #2324
- 🏗️(frontend) move comments to its own folder feature #2374
- ♿️(frontend) align mobile header menu aria-label i18n pattern #2377
- ♿️(frontend) use anchor links for interlinking sub-documents #2391

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useRouter } from 'next/router';
import { useEffect } from 'react';
import { css } from 'styled-components';

import { Box, BoxButton, Text } from '@/components';
import { Box, Text } from '@/components';
import SelectedPageIcon from '@/docs/doc-editor/assets/doc-selected.svg';
import { getEmojiAndTitle, useDoc } from '@/docs/doc-management/';

Expand Down Expand Up @@ -41,19 +41,17 @@ export const LinkSelected = ({
const router = useRouter();
const href = `/docs/${docId}/`;

const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();

// If ctrl or command is pressed, it opens a new tab. If shift is pressed, it opens a new window
if (e.metaKey || e.ctrlKey || e.shiftKey) {
window.open(href, '_blank');
return;
}
void router.push(href);
};

// This triggers on middle-mouse click
const handleAuxClick = (e: React.MouseEvent<HTMLButtonElement>) => {
const handleAuxClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
if (e.button !== 1) {
return;
}
Expand All @@ -63,8 +61,9 @@ export const LinkSelected = ({
};

return (
<BoxButton
as="span"
<Box
as="a"
href={href}
className="--docs--interlinking-link-inline-content"
Comment on lines +64 to 67
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx"
# Show around the cited lines
nl -ba "$FILE" | sed -n '40,90p'

Repository: suitenumerique/docs

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx"
nl -ba "$FILE" | sed -n '40,90p'

Repository: suitenumerique/docs

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx"
# Show with line numbers using cat -n
cat -n "$FILE" | sed -n '40,90p'

Repository: suitenumerique/docs

Length of output: 1769


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "BoxButton|--docs--interlinking-link-inline-content|LinkSelected" src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking src/frontend/apps/impress/src/features/docs/doc-editor -S

Repository: suitenumerique/docs

Length of output: 2799


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect LinkSelected usage and surrounding code
sed -n '1,180p' src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx

# Inspect CalloutBlock BoxButton usage (different component but may show intended patterns)
sed -n '80,170p' src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/CalloutBlock.tsx

# Find BoxButton implementation
rg -n "export (type|interface|const) BoxButton|function BoxButton|BoxButton\s*=" src/frontend -S

Repository: suitenumerique/docs

Length of output: 7467


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/frontend/apps/impress/src/components/BoxButton.tsx"
cat -n "$FILE" | sed -n '1,200p'

Repository: suitenumerique/docs

Length of output: 2655


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect Box implementation to understand how `as` is handled
FILE="src/frontend/apps/impress/src/components/Box.tsx"
if [ -f "$FILE" ]; then
  cat -n "$FILE" | sed -n '1,220p'
else
  echo "Missing $FILE; searching for Box.tsx..."
  fd -a "Box.tsx" src/frontend/apps/impress/src/components | head -n 20
fi

# Also check how Box is imported in LinkSelected
rg -n "import \\{ Box" src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx

Repository: suitenumerique/docs

Length of output: 7553


Avoid rendering a native <a> for this inline interlink control.
LinkSelected currently renders <Box as="a" href={href} ... onClick/onAuxClick> (lines 64-71), which reintroduces native anchor semantics and can conflict with the BlockNote/tiptap interlink behavior this component relies on. Render it as a non-anchor element (e.g., span) with the existing handlers instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx`
around lines 64 - 67, The LinkSelected component currently renders a native
anchor via <Box as="a" href={href} ...>, which reintroduces native anchor
behavior; change it to render a non-anchor element (e.g., <Box as="span"> or
plain <span>) while preserving the existing onClick and onAuxClick handlers and
any accessibility attributes. Update the JSX in LinkSelected to remove the href
prop (or move it to a data-href attribute if the value must be preserved) and
ensure the className "--docs--interlinking-link-inline-content" and event
handlers remain on the new element so BlockNote/tiptap interlink behavior is not
overridden. Verify focus/keyboard interactions still work and adjust
role/tabIndex if needed to maintain accessibility.

Copy link
Copy Markdown
Collaborator Author

@Ovgodd Ovgodd Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of this PR is to use a native <a href> for RGAA 6.1 compliance, a <span> with role="link" and tabindex is explicitly listed as insufficient in the accessibility audit. Native anchor behavior is handled by preventDefault in the click handler.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ovgodd, that's a fair and clear correction — thank you. RGAA 6.1 (and the underlying WCAG success criterion 1.3.1) explicitly requires that links be marked up as native <a href> elements; a <span role="link" tabindex="0"> does not satisfy the criterion. Using <a href> with preventDefault in the click handler is precisely the right pattern here, and my previous suggestion to revert to a non-anchor element was incorrect in this context. I'll retract that concern.

One small thing worth verifying while you're here: in the $css block the focus-visible rule is written as a descendant selector:

.--docs--interlinking-link-inline-content:focus-visible { … }

Since the Box component is that element (not a parent of it), styled-components will look for a child with that class, so the rule may never fire. You likely want:

&:focus-visible { … }
/* or */
&.--docs--interlinking-link-inline-content:focus-visible { … }

✏️ Learnings added
Learnt from: Ovgodd
Repo: suitenumerique/docs PR: 2391
File: src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx:64-67
Timestamp: 2026-06-03T12:43:29.596Z
Learning: In the `LinkSelected` component (`src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/LinkSelected.tsx`), rendering as `<Box as="a" href={href}>` with `preventDefault` in the click handler is intentional and required for RGAA 6.1 / WCAG 1.3.1 compliance. A `<span role="link" tabindex="0">` is explicitly listed as insufficient in the project's accessibility audit. Do not suggest reverting to a non-anchor element.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

data-href={href}
onClick={handleClick}
Expand All @@ -75,6 +74,7 @@ export const LinkSelected = ({
display: inline;
padding: 0.1rem 0.4rem;
border-radius: 4px;
cursor: pointer;
& svg {
position: relative;
top: 2px;
Expand All @@ -85,6 +85,11 @@ export const LinkSelected = ({
--c--contextuals--background--semantic--contextual--primary
);
}
.--docs--interlinking-link-inline-content:focus-visible {
outline: 2px solid
var(--c--contextuals--content--semantic--gray--primary);
outline-offset: 2px;
}
Comment thread
Ovgodd marked this conversation as resolved.
Outdated
transition: background-color var(--c--globals--transitions--duration)
var(--c--globals--transitions--ease-out);

Expand Down Expand Up @@ -129,6 +134,6 @@ export const LinkSelected = ({
{titleWithoutEmoji}
</Box>
</Text>
</BoxButton>
</Box>
);
};
Loading