️(frontend) hide decorative emojis in document title from SR

Mark UI title emojis as aria-hidden while keeping accessible text labels.
This commit is contained in:
Cyril
2026-09-02 11:12:55 +02:00
committed by Ovgodd
parent 681f9a8c40
commit 3d3f58582d
6 changed files with 24 additions and 10 deletions
+1
View File
@@ -19,6 +19,7 @@ and this project adheres to
- ♿️(frontend) announce search loading state for screen readers #2526
- ♻️(frontend) change favorite to star #2539
- 🚚(frontend) add doc move to doc options #2555
- ♿(frontend) hide decorative emojis in document titles from SR #2527
### Fixed
@@ -85,7 +85,6 @@ export const DocLeftPanelCollapseButton = () => {
currentDoc?.title ?? '',
);
const docTitle = titleWithoutEmoji || untitledDocument;
const buttonTitle = emoji ? `${emoji} ${docTitle}` : docTitle;
const shouldShowButtonTitle = !isPanelOpen && !isDocTitleVisible;
const ariaLabel = isPanelOpen
? t('Hide the side panel for {{title}}', { title: docTitle })
@@ -94,7 +93,14 @@ export const DocLeftPanelCollapseButton = () => {
return (
<LeftPanelCollapseButton
ariaLabel={ariaLabel}
buttonTitle={shouldShowButtonTitle ? buttonTitle : undefined}
buttonTitle={
shouldShowButtonTitle ? (
<>
{emoji && <span aria-hidden="true">{emoji} </span>}
{docTitle}
</>
) : undefined
}
/>
);
};
@@ -38,11 +38,16 @@ export const DocTitleText = () => {
const { isMobile } = useResponsiveStore();
const { currentDoc } = useDocStore();
const { untitledDocument } = useTrans();
const { emoji, titleWithoutEmoji } = getEmojiAndTitle(
currentDoc?.title ?? '',
);
const displayTitle = titleWithoutEmoji || untitledDocument;
return (
<Box className={CLASS_DOC_TITLE} $direction="row" $align="center">
<Text as="h2" $margin="none" $size={isMobile ? 'h4' : 'h2'}>
{currentDoc?.title || untitledDocument}
{emoji && <span aria-hidden="true">{emoji} </span>}
{displayTitle}
</Text>
</Box>
);
@@ -10,6 +10,7 @@ import { useResponsiveStore } from '@/stores';
import { useDocUtils, useTrans } from '../hooks';
import { Doc } from '../types';
import { getEmojiAndTitle } from '../utils';
const ItemTextCss = css`
overflow: hidden;
@@ -38,7 +39,8 @@ export const SimpleDocItem = ({
const { untitledDocument } = useTrans();
const { isChild } = useDocUtils(doc);
const { relativeDate, formatDate } = useDate();
const docTitle = doc.title || untitledDocument;
const { emoji, titleWithoutEmoji } = getEmojiAndTitle(doc.title || '');
const docTitle = titleWithoutEmoji || untitledDocument;
const docRelativeUpdate = relativeDate(doc.updated_at);
const itemAriaLabel = `${t('Open document {{title}}', { title: docTitle })}. ${t(
'Last update: {{update}}',
@@ -91,6 +93,7 @@ export const SimpleDocItem = ({
data-testid="doc-title"
title={docTitle}
>
{emoji && <span aria-hidden="true">{emoji} </span>}
{docTitle}
</Text>
@@ -144,7 +144,6 @@ const DocSubPageItemContent = (props: TreeViewNodeProps<Doc>) => {
}
};
const docTitle = doc.title || untitledDocument;
const isCurrentPage = router.query?.id === doc.id;
const isDeleted = !!doc.deleted_at;
const actionsRef = useRef<HTMLDivElement>(null);
@@ -187,8 +186,8 @@ const DocSubPageItemContent = (props: TreeViewNodeProps<Doc>) => {
tabIndex={-1}
aria-label={
isDeleted
? t('{{title}} (deleted)', { title: docTitle })
: t('Open document {{title}}', { title: docTitle })
? t('{{title}} (deleted)', { title: displayTitle })
: t('Open document {{title}}', { title: displayTitle })
}
aria-current={isCurrentPage ? 'page' : undefined}
data-testid={`doc-sub-page-item-${doc.id}`}
@@ -300,7 +299,7 @@ const DocSubPageItemContent = (props: TreeViewNodeProps<Doc>) => {
$align="center"
className="light-doc-item-actions actions"
role="toolbar"
aria-label={t('Actions for {{title}}', { title: docTitle })}
aria-label={t('Actions for {{title}}', { title: displayTitle })}
>
<DocTreeItemActions
doc={doc}
@@ -1,4 +1,5 @@
import { Button } from '@gouvfr-lasuite/ui-components';
import { ReactNode } from 'react';
import { Text } from '@/components';
import { FadeComponent } from '@/components/Effect';
@@ -13,7 +14,7 @@ export const LeftPanelCollapseButton = ({
buttonTitle,
}: {
ariaLabel: string;
buttonTitle?: string;
buttonTitle?: ReactNode;
}) => {
const { isPanelOpen, togglePanel } = useLeftPanelStore();
const { isSmallMobile } = useResponsiveStore();
@@ -36,7 +37,6 @@ export const LeftPanelCollapseButton = ({
$size="sm"
$weight={700}
$color="var(--c--globals--colors--gray-1000)"
title={buttonTitle}
>
{buttonTitle}
</Text>