Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to
- ⚡️(frontend) improve accessibility:
- #1248
- #1235
- #1255
- #1262

## [3.5.0] - 2025-07-31

Expand All @@ -31,9 +33,7 @@ and this project adheres to
- ♻️(frontend) redirect to doc after duplicate #1175
- 🔧(project) change env.d system by using local files #1200
- ⚡️(frontend) improve tree stability #1207
- ⚡️(frontend) improve accessibility
- #1232
- #1255
- ⚡️(frontend) improve accessibility #1232
- 🛂(frontend) block drag n drop when not desktop #1239

### Fixed
Expand Down
10 changes: 5 additions & 5 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ test.describe('Document grid item options', () => {
await page.getByText('push_pin').click();

// Check is pinned
await expect(row.getByLabel('Pin document icon')).toBeVisible();
await expect(row.locator('[data-testid^="doc-pinned-"]')).toBeVisible();
const leftPanelFavorites = page.getByTestId('left-panel-favorites');
await expect(leftPanelFavorites.getByText(docTitle)).toBeVisible();

Expand All @@ -128,7 +128,7 @@ test.describe('Document grid item options', () => {
await page.getByText('Unpin').click();

// Check is unpinned
await expect(row.getByLabel('Pin document icon')).toBeHidden();
await expect(row.locator('[data-testid^="doc-pinned-"]')).toBeHidden();
await expect(leftPanelFavorites.getByText(docTitle)).toBeHidden();
});

Expand Down Expand Up @@ -227,18 +227,18 @@ test.describe('Documents filters', () => {

// Initial state
await expect(allDocs).toBeVisible();
await expect(allDocs).toHaveAttribute('aria-selected', 'true');
await expect(allDocs).toHaveAttribute('aria-current', 'page');

await expect(myDocs).toBeVisible();
await expect(myDocs).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
await expect(myDocs).toHaveAttribute('aria-selected', 'false');
await expect(myDocs).not.toHaveAttribute('aria-current');

await expect(sharedWithMe).toBeVisible();
await expect(sharedWithMe).toHaveCSS(
'background-color',
'rgba(0, 0, 0, 0)',
);
await expect(sharedWithMe).toHaveAttribute('aria-selected', 'false');
await expect(sharedWithMe).not.toHaveAttribute('aria-current');

await allDocs.click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ test.describe('Doc Header', () => {
const row = await getGridRow(page, docTitle);

// Check is pinned
await expect(row.getByLabel('Pin document icon')).toBeVisible();
await expect(row.locator('[data-testid^="doc-pinned-"]')).toBeVisible();
const leftPanelFavorites = page.getByTestId('left-panel-favorites');
await expect(leftPanelFavorites.getByText(docTitle)).toBeVisible();

Expand All @@ -424,7 +424,7 @@ test.describe('Doc Header', () => {
await page.goto('/');

// Check is unpinned
await expect(row.getByLabel('Pin document icon')).toBeHidden();
await expect(row.locator('[data-testid^="doc-pinned-"]')).toBeHidden();
await expect(leftPanelFavorites.getByText(docTitle)).toBeHidden();
});

Expand Down
7 changes: 7 additions & 0 deletions src/frontend/apps/impress/src/components/DropButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const StyledButton = styled(Button)<StyledButtonProps>`
font-size: 0.938rem;
padding: 0;
${({ $css }) => $css};

&:focus-visible {
outline: 2px solid var(--c--theme--colors--primary-500);
outline-offset: 2px;
border-radius: 4px;
transition: none;
}
`;

export interface DropButtonProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,17 @@ export const SimpleDocItem = ({
filter: drop-shadow(0px 2px 2px rgba(0, 0, 0, 0.05));
`}
$padding={`${spacingsTokens['3xs']} 0`}
data-testid={isPinned ? `doc-pinned-${doc.id}` : undefined}
>
{isPinned ? (
<PinnedDocumentIcon
aria-hidden="true"
aria-label={t('Pin document icon')}
color={colorsTokens['primary-500']}
/>
) : (
<SimpleFileIcon
aria-hidden="true"
aria-label={t('Simple document icon')}
color={colorsTokens['primary-500']}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useModal } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';

import { DropdownMenu, DropdownMenuOption, Icon } from '@/components';
import {
Expand Down Expand Up @@ -83,6 +84,13 @@ export const DocsGridActions = ({
iconName="more_horiz"
$theme="primary"
$variation="600"
aria-label={t('More options')}
$css={css`
cursor: pointer;
&:hover {
opacity: 0.8;
}
`}
/>
</DropdownMenu>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { usePathname, useSearchParams } from 'next/navigation';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';

import { Box, BoxButton, Icon, Text } from '@/components';
import { Box, Icon, StyledLink, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { DocDefaultFilter } from '@/docs/doc-management';
import { useLeftPanelStore } from '@/features/left-panel';

export const LeftPanelTargetFilters = () => {
const { t } = useTranslation();

const pathname = usePathname();
const searchParams = useSearchParams();

const { togglePanel } = useLeftPanelStore();
const { colorsTokens, spacingsTokens } = useCunninghamTheme();

const searchParams = useSearchParams();
const target =
(searchParams.get('target') as DocDefaultFilter) ??
DocDefaultFilter.ALL_DOCS;

const router = useRouter();

const defaultQueries = [
{
icon: 'apps',
Expand All @@ -39,44 +37,57 @@ export const LeftPanelTargetFilters = () => {
},
];

const onSelectQuery = (query: DocDefaultFilter) => {
const buildHref = (query: DocDefaultFilter) => {
const params = new URLSearchParams(searchParams);
params.set('target', query);
router.push(`${pathname}?${params.toString()}`);
return `${pathname}?${params.toString()}`;
};

const handleClick = () => {
togglePanel();
};

return (
<Box
as="nav"
aria-label={t('Document sections')}
$justify="center"
$padding={{ horizontal: 'sm' }}
$gap={spacingsTokens['2xs']}
className="--docs--left-panel-target-filters"
>
{defaultQueries.map((query) => {
const isActive = target === query.targetQuery;
const href = buildHref(query.targetQuery);

return (
<BoxButton
aria-label={query.label}
<StyledLink
key={query.label}
onClick={() => onSelectQuery(query.targetQuery)}
$direction="row"
aria-selected={isActive}
$align="center"
$justify="flex-start"
$gap={spacingsTokens['xs']}
$radius={spacingsTokens['3xs']}
$padding={{ all: '2xs' }}
href={href}
aria-label={query.label}
aria-current={isActive ? 'page' : undefined}
onClick={handleClick}
$css={css`
cursor: pointer;
display: flex;
align-items: center;
justify-content: flex-start;
gap: ${spacingsTokens['xs']};
padding: ${spacingsTokens['2xs']};
border-radius: ${spacingsTokens['3xs']};
background-color: ${isActive
? colorsTokens['greyscale-100']
: undefined};
font-weight: ${isActive ? 700 : undefined};
: 'transparent'};
font-weight: ${isActive ? 700 : 400};
color: inherit;
text-decoration: none;
cursor: pointer;
&:hover {
background-color: ${colorsTokens['greyscale-100']};
}
&:focus-visible {
outline: 2px solid ${colorsTokens['primary-500']};
outline-offset: 2px;
}
`}
>
<Icon
Expand All @@ -86,7 +97,7 @@ export const LeftPanelTargetFilters = () => {
<Text $variation={isActive ? '1000' : '700'} $size="sm">
{query.label}
</Text>
</BoxButton>
</StyledLink>
);
})}
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useModal } from '@openfun/cunningham-react';
import { t } from 'i18next';
import { DateTime } from 'luxon';
import { css } from 'styled-components';

import { Box, StyledLink } from '@/components';
Expand All @@ -14,11 +16,12 @@ type LeftPanelFavoriteItemProps = {

export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
const shareModal = useModal();
const { spacingsTokens } = useCunninghamTheme();
const { colorsTokens, spacingsTokens } = useCunninghamTheme();
const { isDesktop } = useResponsiveStore();

return (
<Box
as="li"
$direction="row"
$align="center"
$justify="space-between"
Expand All @@ -28,19 +31,29 @@ export const LeftPanelFavoriteItem = ({ doc }: LeftPanelFavoriteItemProps) => {
.pinned-actions {
opacity: ${isDesktop ? 0 : 1};
}
&:hover {
&:hover,
&:focus-within {
cursor: pointer;

background-color: var(--c--theme--colors--greyscale-100);
.pinned-actions {
opacity: 1;
}
}
&:focus-visible {
outline: 2px solid ${colorsTokens['primary-500']};
outline-offset: 2px;
border-radius: ${spacingsTokens['3xs']};
}
`}
key={doc.id}
className="--docs--left-panel-favorite-item"
>
<StyledLink href={`/docs/${doc.id}`} $css="overflow: auto;">
<StyledLink
href={`/docs/${doc.id}`}
$css="overflow: auto;"
aria-label={`${doc.title}, ${t('Updated')} ${DateTime.fromISO(doc.updated_at).toRelative()}`}
>
<SimpleDocItem showAccesses doc={doc} />
</StyledLink>
<div className="pinned-actions">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ export const LeftPanelFavorites = () => {
}

return (
<Box className="--docs--left-panel-favorites">
<Box
as="nav"
aria-label={t('Pinned documents')}
className="--docs--left-panel-favorites"
>
<HorizontalSeparator $withPadding={false} />
<Box
$justify="center"
Expand All @@ -41,6 +45,7 @@ export const LeftPanelFavorites = () => {
{t('Pinned documents')}
</Text>
<InfiniteScroll
as="ul"
hasMore={docs.hasNextPage}
isLoading={docs.isFetchingNextPage}
next={() => void docs.fetchNextPage()}
Expand Down
Loading
Loading