💄(frontend) adapt language picker design

Adapt the language picker design to
to fit with the new design of the app.
This commit is contained in:
Anthony LC
2025-02-18 12:12:41 +01:00
committed by Anthony LC
parent 757c09b189
commit 50d098c777
18 changed files with 149 additions and 133 deletions

View File

@@ -97,7 +97,7 @@ export const addNewMember = async (
// Choose a role // Choose a role
await page.getByLabel('doc-role-dropdown').click(); await page.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: role }).click(); await page.getByRole('menuitem', { name: role }).click();
await page.getByRole('button', { name: 'Invite' }).click(); await page.getByRole('button', { name: 'Invite' }).click();
return users[index].email; return users[index].email;

View File

@@ -37,10 +37,10 @@ test.describe('Doc Editor', () => {
// Change language to French // Change language to French
await header.click(); await header.click();
await header.getByRole('combobox').getByText('English').click(); await header.getByRole('button', { name: /Language/ }).click();
await header.getByRole('option', { name: 'Français' }).click(); await page.getByRole('menuitem', { name: 'Français' }).click();
await expect( await expect(
header.getByRole('combobox').getByText('Français'), header.getByRole('button').getByText('Français'),
).toBeVisible(); ).toBeVisible();
// Trigger slash menu to show french menu // Trigger slash menu to show french menu
@@ -130,7 +130,7 @@ test.describe('Doc Editor', () => {
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Connected', name: 'Connected',
}) })
.click(); .click();

View File

@@ -89,7 +89,7 @@ test.describe('Doc Header', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Delete document', name: 'Delete document',
}) })
.click(); .click();
@@ -153,7 +153,7 @@ test.describe('Doc Header', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await expect( await expect(
page.getByRole('button', { name: 'Delete document' }), page.getByRole('menuitem', { name: 'Delete document' }),
).toBeDisabled(); ).toBeDisabled();
// Click somewhere else to close the options // Click somewhere else to close the options
@@ -177,7 +177,7 @@ test.describe('Doc Header', () => {
await invitationCard.getByRole('button', { name: 'more_horiz' }).click(); await invitationCard.getByRole('button', { name: 'more_horiz' }).click();
await expect( await expect(
page.getByRole('button', { page.getByRole('menuitem', {
name: 'delete', name: 'delete',
}), }),
).toBeEnabled(); ).toBeEnabled();
@@ -195,7 +195,7 @@ test.describe('Doc Header', () => {
await memberCard.getByRole('button', { name: 'more_horiz' }).click(); await memberCard.getByRole('button', { name: 'more_horiz' }).click();
await expect( await expect(
page.getByRole('button', { page.getByRole('menuitem', {
name: 'delete', name: 'delete',
}), }),
).toBeEnabled(); ).toBeEnabled();
@@ -233,7 +233,7 @@ test.describe('Doc Header', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await expect( await expect(
page.getByRole('button', { name: 'Delete document' }), page.getByRole('menuitem', { name: 'Delete document' }),
).toBeDisabled(); ).toBeDisabled();
// Click somewhere else to close the options // Click somewhere else to close the options
@@ -295,7 +295,7 @@ test.describe('Doc Header', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await expect( await expect(
page.getByRole('button', { name: 'Delete document' }), page.getByRole('menuitem', { name: 'Delete document' }),
).toBeDisabled(); ).toBeDisabled();
// Click somewhere else to close the options // Click somewhere else to close the options
@@ -352,7 +352,7 @@ test.describe('Doc Header', () => {
// Copy content to clipboard // Copy content to clipboard
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page.getByRole('button', { name: 'Copy as Markdown' }).click(); await page.getByRole('menuitem', { name: 'Copy as Markdown' }).click();
await expect(page.getByText('Copied to clipboard')).toBeVisible(); await expect(page.getByText('Copied to clipboard')).toBeVisible();
// Test that clipboard is in Markdown format // Test that clipboard is in Markdown format
@@ -387,7 +387,7 @@ test.describe('Doc Header', () => {
// Copy content to clipboard // Copy content to clipboard
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page.getByRole('button', { name: 'Copy as HTML' }).click(); await page.getByRole('menuitem', { name: 'Copy as HTML' }).click();
await expect(page.getByText('Copied to clipboard')).toBeVisible(); await expect(page.getByText('Copied to clipboard')).toBeVisible();
// Test that clipboard is in HTML format // Test that clipboard is in HTML format
@@ -460,7 +460,7 @@ test.describe('Documents Header mobile', () => {
await expect(page.getByRole('button', { name: 'Copy link' })).toBeHidden(); await expect(page.getByRole('button', { name: 'Copy link' })).toBeHidden();
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page.getByRole('button', { name: 'Share' }).click(); await page.getByRole('menuitem', { name: 'Share' }).click();
await page.getByRole('button', { name: 'Copy link' }).click(); await page.getByRole('button', { name: 'Copy link' }).click();
await expect(page.getByText('Link Copied !')).toBeVisible(); await expect(page.getByText('Link Copied !')).toBeVisible();
// Test that clipboard is in HTML format // Test that clipboard is in HTML format
@@ -494,7 +494,7 @@ test.describe('Documents Header mobile', () => {
await goToGridDoc(page); await goToGridDoc(page);
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page.getByRole('button', { name: 'Share' }).click(); await page.getByRole('menuitem', { name: 'Share' }).click();
await expect(page.getByLabel('Share modal')).toBeVisible(); await expect(page.getByLabel('Share modal')).toBeVisible();
await page.getByRole('button', { name: 'close' }).click(); await page.getByRole('button', { name: 'close' }).click();

View File

@@ -65,15 +65,15 @@ test.describe('Document create member', () => {
// Check roles are displayed // Check roles are displayed
await list.getByLabel('doc-role-dropdown').click(); await list.getByLabel('doc-role-dropdown').click();
await expect(page.getByRole('button', { name: 'Reader' })).toBeVisible(); await expect(page.getByRole('menuitem', { name: 'Reader' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Editor' })).toBeVisible(); await expect(page.getByRole('menuitem', { name: 'Editor' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Owner' })).toBeVisible(); await expect(page.getByRole('menuitem', { name: 'Owner' })).toBeVisible();
await expect( await expect(
page.getByRole('button', { name: 'Administrator' }), page.getByRole('menuitem', { name: 'Administrator' }),
).toBeVisible(); ).toBeVisible();
// Validate // Validate
await page.getByRole('button', { name: 'Administrator' }).click(); await page.getByRole('menuitem', { name: 'Administrator' }).click();
await page.getByRole('button', { name: 'Invite' }).click(); await page.getByRole('button', { name: 'Invite' }).click();
// Check invitation added // Check invitation added
@@ -121,7 +121,7 @@ test.describe('Document create member', () => {
// Choose a role // Choose a role
const container = page.getByTestId('doc-share-add-member-list'); const container = page.getByTestId('doc-share-add-member-list');
await container.getByLabel('doc-role-dropdown').click(); await container.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Owner' }).click(); await page.getByRole('menuitem', { name: 'Owner' }).click();
const responsePromiseCreateInvitation = page.waitForResponse( const responsePromiseCreateInvitation = page.waitForResponse(
(response) => (response) =>
@@ -139,7 +139,7 @@ test.describe('Document create member', () => {
// Choose a role // Choose a role
await container.getByLabel('doc-role-dropdown').click(); await container.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Owner' }).click(); await page.getByRole('menuitem', { name: 'Owner' }).click();
const responsePromiseCreateInvitationFail = page.waitForResponse( const responsePromiseCreateInvitationFail = page.waitForResponse(
(response) => (response) =>
@@ -162,8 +162,8 @@ test.describe('Document create member', () => {
await createDoc(page, 'user-invitation', browserName, 1); await createDoc(page, 'user-invitation', browserName, 1);
const header = page.locator('header').first(); const header = page.locator('header').first();
await header.getByRole('combobox').getByText('EN').click(); await header.getByRole('button', { name: /Language/ }).click();
await header.getByRole('option', { name: 'translate Français' }).click(); await page.getByRole('menuitem', { name: 'Français' }).click();
await page.getByRole('button', { name: 'Partager' }).click(); await page.getByRole('button', { name: 'Partager' }).click();
@@ -178,7 +178,7 @@ test.describe('Document create member', () => {
// Choose a role // Choose a role
const container = page.getByTestId('doc-share-add-member-list'); const container = page.getByTestId('doc-share-add-member-list');
await container.getByLabel('doc-role-dropdown').click(); await container.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Administrateur' }).click(); await page.getByRole('menuitem', { name: 'Administrateur' }).click();
const responsePromiseCreateInvitation = page.waitForResponse( const responsePromiseCreateInvitation = page.waitForResponse(
(response) => (response) =>
@@ -212,7 +212,7 @@ test.describe('Document create member', () => {
// Choose a role // Choose a role
const container = page.getByTestId('doc-share-add-member-list'); const container = page.getByTestId('doc-share-add-member-list');
await container.getByLabel('doc-role-dropdown').click(); await container.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Administrator' }).click(); await page.getByRole('menuitem', { name: 'Administrator' }).click();
const responsePromiseCreateInvitation = page.waitForResponse( const responsePromiseCreateInvitation = page.waitForResponse(
(response) => (response) =>
@@ -232,14 +232,14 @@ test.describe('Document create member', () => {
await expect(userInvitation).toBeVisible(); await expect(userInvitation).toBeVisible();
await userInvitation.getByLabel('doc-role-dropdown').click(); await userInvitation.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Reader' }).click(); await page.getByRole('menuitem', { name: 'Reader' }).click();
const moreActions = userInvitation.getByRole('button', { const moreActions = userInvitation.getByRole('button', {
name: 'more_horiz', name: 'more_horiz',
}); });
await moreActions.click(); await moreActions.click();
await page.getByRole('button', { name: 'Delete' }).click(); await page.getByRole('menuitem', { name: 'Delete' }).click();
await expect(userInvitation).toBeHidden(); await expect(userInvitation).toBeHidden();
}); });

View File

@@ -161,12 +161,12 @@ test.describe('Document list members', () => {
await list.click(); await list.click();
await currentUserRole.click(); await currentUserRole.click();
await page.getByRole('button', { name: 'Administrator' }).click(); await page.getByRole('menuitem', { name: 'Administrator' }).click();
await list.click(); await list.click();
await expect(currentUserRole).toBeVisible(); await expect(currentUserRole).toBeVisible();
await currentUserRole.click(); await currentUserRole.click();
await page.getByRole('button', { name: 'Reader' }).click(); await page.getByRole('menuitem', { name: 'Reader' }).click();
await list.click(); await list.click();
await expect(currentUserRole).toBeHidden(); await expect(currentUserRole).toBeHidden();
}); });
@@ -215,11 +215,11 @@ test.describe('Document list members', () => {
await expect(mySelfMoreActions).toBeVisible(); await expect(mySelfMoreActions).toBeVisible();
await userReaderMoreActions.click(); await userReaderMoreActions.click();
await page.getByRole('button', { name: 'Delete' }).click(); await page.getByRole('menuitem', { name: 'Delete' }).click();
await expect(userReader).toBeHidden(); await expect(userReader).toBeHidden();
await mySelfMoreActions.click(); await mySelfMoreActions.click();
await page.getByRole('button', { name: 'Delete' }).click(); await page.getByRole('menuitem', { name: 'Delete' }).click();
await expect( await expect(
page.getByText('You do not have permission to view this document.'), page.getByText('You do not have permission to view this document.'),
).toBeVisible(); ).toBeVisible();

View File

@@ -19,7 +19,7 @@ test.describe('Doc Version', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Version history', name: 'Version history',
}) })
.click(); .click();
@@ -59,7 +59,7 @@ test.describe('Doc Version', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Version history', name: 'Version history',
}) })
.click(); .click();
@@ -91,7 +91,7 @@ test.describe('Doc Version', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await expect( await expect(
page.getByRole('button', { name: 'Version history' }), page.getByRole('menuitem', { name: 'Version history' }),
).toBeDisabled(); ).toBeDisabled();
}); });
@@ -120,7 +120,7 @@ test.describe('Doc Version', () => {
await page.getByLabel('Open the document options').click(); await page.getByLabel('Open the document options').click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Version history', name: 'Version history',
}) })
.click(); .click();

View File

@@ -50,7 +50,7 @@ test.describe('Doc Visibility', () => {
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Connected', name: 'Connected',
}) })
.click(); .click();
@@ -60,7 +60,7 @@ test.describe('Doc Visibility', () => {
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Public', name: 'Public',
}) })
.click(); .click();
@@ -162,7 +162,7 @@ test.describe('Doc Visibility: Restricted', () => {
// Choose a role // Choose a role
const container = page.getByTestId('doc-share-add-member-list'); const container = page.getByTestId('doc-share-add-member-list');
await container.getByLabel('doc-role-dropdown').click(); await container.getByLabel('doc-role-dropdown').click();
await page.getByRole('button', { name: 'Administrator' }).click(); await page.getByRole('menuitem', { name: 'Administrator' }).click();
await page.getByRole('button', { name: 'Invite' }).click(); await page.getByRole('button', { name: 'Invite' }).click();
@@ -215,7 +215,7 @@ test.describe('Doc Visibility: Public', () => {
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Public', name: 'Public',
}) })
.click(); .click();
@@ -227,7 +227,7 @@ test.describe('Doc Visibility: Public', () => {
await expect(page.getByLabel('Visibility mode')).toBeVisible(); await expect(page.getByLabel('Visibility mode')).toBeVisible();
await page.getByLabel('Visibility mode').click(); await page.getByLabel('Visibility mode').click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Reading', name: 'Reading',
}) })
.click(); .click();
@@ -289,7 +289,7 @@ test.describe('Doc Visibility: Public', () => {
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Public', name: 'Public',
}) })
.click(); .click();
@@ -357,7 +357,7 @@ test.describe('Doc Visibility: Authenticated', () => {
const selectVisibility = page.getByLabel('Visibility', { exact: true }); const selectVisibility = page.getByLabel('Visibility', { exact: true });
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Connected', name: 'Connected',
}) })
.click(); .click();
@@ -407,7 +407,7 @@ test.describe('Doc Visibility: Authenticated', () => {
const selectVisibility = page.getByLabel('Visibility', { exact: true }); const selectVisibility = page.getByLabel('Visibility', { exact: true });
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Connected', name: 'Connected',
}) })
.click(); .click();
@@ -461,7 +461,7 @@ test.describe('Doc Visibility: Authenticated', () => {
const selectVisibility = page.getByLabel('Visibility', { exact: true }); const selectVisibility = page.getByLabel('Visibility', { exact: true });
await selectVisibility.click(); await selectVisibility.click();
await page await page
.getByRole('button', { .getByRole('menuitem', {
name: 'Connected', name: 'Connected',
}) })
.click(); .click();

View File

@@ -12,7 +12,7 @@ test.describe('Home page', () => {
const footer = page.locator('footer').first(); const footer = page.locator('footer').first();
await expect(header).toBeVisible(); await expect(header).toBeVisible();
await expect( await expect(
header.getByRole('combobox', { name: 'Language' }), header.getByRole('button', { name: /Language/ }),
).toBeVisible(); ).toBeVisible();
await expect( await expect(
header.getByRole('button', { name: 'Les services de La Suite numé' }), header.getByRole('button', { name: 'Les services de La Suite numé' }),

View File

@@ -9,19 +9,20 @@ test.describe('Language', () => {
await expect(page.getByLabel('Logout')).toBeVisible(); await expect(page.getByLabel('Logout')).toBeVisible();
const header = page.locator('header').first(); const header = page.locator('header').first();
await header.getByRole('combobox').getByText('English').click(); await header
await header.getByRole('option', { name: 'Français' }).click(); .getByRole('button', { name: /Language/ })
.getByText('English')
.click();
await page.getByRole('menuitem', { name: 'Français' }).click();
await expect( await expect(
header.getByRole('combobox').getByText('Français'), header.getByRole('button').getByText('Français'),
).toBeVisible(); ).toBeVisible();
await expect(page.getByLabel('Se déconnecter')).toBeVisible(); await expect(page.getByLabel('Se déconnecter')).toBeVisible();
await header.getByRole('combobox').getByText('Français').click(); await header.getByRole('button').getByText('Français').click();
await header.getByRole('option', { name: 'Deutsch' }).click(); await page.getByRole('menuitem', { name: 'Deutsch' }).click();
await expect( await expect(header.getByRole('button').getByText('Deutsch')).toBeVisible();
header.getByRole('combobox').getByText('Deutsch'),
).toBeVisible();
await expect(page.getByLabel('Abmelden')).toBeVisible(); await expect(page.getByLabel('Abmelden')).toBeVisible();
}); });
@@ -53,8 +54,11 @@ test.describe('Language', () => {
// Switch language to French // Switch language to French
const header = page.locator('header').first(); const header = page.locator('header').first();
await header.getByRole('combobox').getByText('English').click(); await header
await header.getByRole('option', { name: 'Français' }).click(); .getByRole('button', { name: /Language/ })
.getByText('English')
.click();
await page.getByRole('menuitem', { name: 'Français' }).click();
// Check for French 404 response // Check for French 404 response
await check404Response('Pas trouvé.'); await check404Response('Pas trouvé.');

View File

@@ -29,7 +29,7 @@ test.describe('Left panel mobile', () => {
const header = page.locator('header').first(); const header = page.locator('header').first();
const homeButton = page.getByRole('button', { name: 'house' }); const homeButton = page.getByRole('button', { name: 'house' });
const newDocButton = page.getByRole('button', { name: 'New doc' }); const newDocButton = page.getByRole('button', { name: 'New doc' });
const languageButton = page.getByRole('combobox', { name: 'Language' }); const languageButton = page.getByRole('button', { name: /Language/ });
const logoutButton = page.getByRole('button', { name: 'Logout' }); const logoutButton = page.getByRole('button', { name: 'Logout' });
await expect(homeButton).not.toBeInViewport(); await expect(homeButton).not.toBeInViewport();

View File

@@ -381,6 +381,7 @@ const config = {
'color-active': 'var(--c--theme--colors--primary-100)', 'color-active': 'var(--c--theme--colors--primary-100)',
}, },
'color-hover': 'var(--c--theme--colors--primary-text)', 'color-hover': 'var(--c--theme--colors--primary-text)',
color: 'var(--c--theme--colors--primary-800)',
}, },
secondary: { secondary: {
background: { background: {

View File

@@ -8,17 +8,20 @@ import {
import { Button, Popover } from 'react-aria-components'; import { Button, Popover } from 'react-aria-components';
import styled from 'styled-components'; import styled from 'styled-components';
import { BoxProps } from './Box';
const StyledPopover = styled(Popover)` const StyledPopover = styled(Popover)`
background-color: white; background-color: white;
border-radius: 4px; border-radius: 4px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
border: 1px solid #dddddd; border: 1px solid #dddddd;
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
`; `;
const StyledButton = styled(Button)` interface StyledButtonProps {
$css?: BoxProps['$css'];
}
const StyledButton = styled(Button)<StyledButtonProps>`
cursor: pointer; cursor: pointer;
border: none; border: none;
background: none; background: none;
@@ -29,10 +32,12 @@ const StyledButton = styled(Button)`
font-size: 0.938rem; font-size: 0.938rem;
padding: 0; padding: 0;
text-wrap: nowrap; text-wrap: nowrap;
${({ $css }) => $css};
`; `;
export interface DropButtonProps { export interface DropButtonProps {
button: ReactNode; button: ReactNode;
buttonCss?: BoxProps['$css'];
isOpen?: boolean; isOpen?: boolean;
onOpenChange?: (isOpen: boolean) => void; onOpenChange?: (isOpen: boolean) => void;
label?: string; label?: string;
@@ -40,6 +45,7 @@ export interface DropButtonProps {
export const DropButton = ({ export const DropButton = ({
button, button,
buttonCss,
isOpen = false, isOpen = false,
onOpenChange, onOpenChange,
children, children,
@@ -64,6 +70,7 @@ export const DropButton = ({
ref={triggerRef} ref={triggerRef}
onPress={() => onOpenChangeHandler(true)} onPress={() => onOpenChangeHandler(true)}
aria-label={label} aria-label={label}
$css={buttonCss}
> >
{button} {button}
</StyledButton> </StyledButton>

View File

@@ -1,4 +1,4 @@
import { PropsWithChildren, useState } from 'react'; import { PropsWithChildren, useRef, useState } from 'react';
import { css } from 'styled-components'; import { css } from 'styled-components';
import { Box, BoxButton, BoxProps, DropButton, Icon, Text } from '@/components'; import { Box, BoxButton, BoxProps, DropButton, Icon, Text } from '@/components';
@@ -20,6 +20,7 @@ export type DropdownMenuProps = {
showArrow?: boolean; showArrow?: boolean;
label?: string; label?: string;
arrowCss?: BoxProps['$css']; arrowCss?: BoxProps['$css'];
buttonCss?: BoxProps['$css'];
disabled?: boolean; disabled?: boolean;
topMessage?: string; topMessage?: string;
}; };
@@ -30,6 +31,7 @@ export const DropdownMenu = ({
disabled = false, disabled = false,
showArrow = false, showArrow = false,
arrowCss, arrowCss,
buttonCss,
label, label,
topMessage, topMessage,
}: PropsWithChildren<DropdownMenuProps>) => { }: PropsWithChildren<DropdownMenuProps>) => {
@@ -37,6 +39,7 @@ export const DropdownMenu = ({
const spacings = theme.spacingsTokens(); const spacings = theme.spacingsTokens();
const colors = theme.colorsTokens(); const colors = theme.colorsTokens();
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const blockButtonRef = useRef<HTMLDivElement>(null);
const onOpenChange = (isOpen: boolean) => { const onOpenChange = (isOpen: boolean) => {
setIsOpen(isOpen); setIsOpen(isOpen);
@@ -51,10 +54,17 @@ export const DropdownMenu = ({
isOpen={isOpen} isOpen={isOpen}
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
label={label} label={label}
buttonCss={buttonCss}
button={ button={
showArrow ? ( showArrow ? (
<Box $direction="row" $align="center"> <Box
<div>{children}</div> ref={blockButtonRef}
$direction="row"
$align="center"
$position="relative"
aria-controls="menu"
>
<Box>{children}</Box>
<Icon <Icon
$variation="600" $variation="600"
$css={ $css={
@@ -67,11 +77,17 @@ export const DropdownMenu = ({
/> />
</Box> </Box>
) : ( ) : (
children <Box ref={blockButtonRef} aria-controls="menu">
{children}
</Box>
) )
} }
> >
<Box $maxWidth="320px"> <Box
$maxWidth="320px"
$minWidth={`${blockButtonRef.current?.clientWidth}px`}
role="menu"
>
{topMessage && ( {topMessage && (
<Text <Text
$variation="700" $variation="700"
@@ -90,6 +106,7 @@ export const DropdownMenu = ({
const isDisabled = option.disabled !== undefined && option.disabled; const isDisabled = option.disabled !== undefined && option.disabled;
return ( return (
<BoxButton <BoxButton
role="menuitem"
aria-label={option.label} aria-label={option.label}
data-testid={option.testId} data-testid={option.testId}
$direction="row" $direction="row"

View File

@@ -25,7 +25,9 @@ export interface TextProps extends BoxProps {
$size?: TextSizes | (string & {}); $size?: TextSizes | (string & {});
$theme?: $theme?:
| 'primary' | 'primary'
| 'primary-text'
| 'secondary' | 'secondary'
| 'secondary-text'
| 'info' | 'info'
| 'success' | 'success'
| 'warning' | 'warning'

View File

@@ -406,6 +406,10 @@ input:-webkit-autofill:focus {
); );
} }
.c__button--primary-text {
color: var(--c--components--button--primary-text--color);
}
.c__button--primary-text:hover, .c__button--primary-text:hover,
.c__button--primary-text:focus-visible { .c__button--primary-text:focus-visible {
background-color: var( background-color: var(

View File

@@ -505,6 +505,9 @@
--c--components--button--primary-text--color-hover: var( --c--components--button--primary-text--color-hover: var(
--c--theme--colors--primary-text --c--theme--colors--primary-text
); );
--c--components--button--primary-text--color: var(
--c--theme--colors--primary-800
);
--c--components--button--secondary--background--color-hover: #f6f6f6; --c--components--button--secondary--background--color-hover: #f6f6f6;
--c--components--button--secondary--background--color-active: #ededed; --c--components--button--secondary--background--color-active: #ededed;
--c--components--button--secondary--border--color: var( --c--components--button--secondary--border--color: var(

View File

@@ -505,6 +505,7 @@ export const tokens = {
'color-active': 'var(--c--theme--colors--primary-100)', 'color-active': 'var(--c--theme--colors--primary-100)',
}, },
'color-hover': 'var(--c--theme--colors--primary-text)', 'color-hover': 'var(--c--theme--colors--primary-text)',
color: 'var(--c--theme--colors--primary-800)',
}, },
secondary: { secondary: {
background: { 'color-hover': '#F6F6F6', 'color-active': '#EDEDED' }, background: { 'color-hover': '#F6F6F6', 'color-active': '#EDEDED' },

View File

@@ -1,84 +1,61 @@
import { Select } from '@openfun/cunningham-react';
import { Settings } from 'luxon'; import { Settings } from 'luxon';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import styled from 'styled-components'; import { css } from 'styled-components';
import { Box, Text } from '@/components/'; import { DropdownMenu, Text } from '@/components/';
import { LANGUAGES_ALLOWED } from '@/i18n/conf'; import { LANGUAGES_ALLOWED } from '@/i18n/conf';
const SelectStyled = styled(Select)<{ $isSmall?: boolean }>`
flex-shrink: 0;
width: auto;
.c__select__wrapper {
min-height: 2rem;
height: auto;
border-color: transparent;
padding: 0 0.15rem 0 0.45rem;
border-radius: 1px;
.labelled-box .labelled-box__children {
padding-right: 2rem;
.c_select__render .typo-text {
${({ $isSmall }) => $isSmall && `display: none;`}
}
}
&:hover {
box-shadow: none !important;
}
}
`;
export const LanguagePicker = () => { export const LanguagePicker = () => {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const { preload: languages } = i18n.options; const { preload: languages } = i18n.options;
Settings.defaultLocale = i18n.language; const language = i18n.language;
Settings.defaultLocale = language;
const optionsPicker = useMemo(() => { const optionsPicker = useMemo(() => {
return (languages || []).map((lang) => ({ return (languages || []).map((lang) => ({
value: lang, label: LANGUAGES_ALLOWED[lang],
label: lang, isSelected: language === lang,
render: () => ( callback: () => {
<Box i18n.changeLanguage(lang).catch((err) => {
className="c_select__render"
$direction="row"
$gap="0.7rem"
$align="center"
>
<Text
$isMaterialIcon
$size="1rem"
$theme="primary"
$weight="bold"
$variation="800"
>
translate
</Text>
<Text $theme="primary" $weight="500" $variation="800">
{LANGUAGES_ALLOWED[lang]}
</Text>
</Box>
),
}));
}, [languages]);
return (
<SelectStyled
label={t('Language')}
showLabelWhenSelected={false}
clearable={false}
hideLabel
defaultValue={i18n.language}
className="c_select__no_bg"
options={optionsPicker}
onChange={(e) => {
i18n.changeLanguage(e.target.value as string).catch((err) => {
console.error('Error changing language', err); console.error('Error changing language', err);
}); });
}} },
/> }));
}, [i18n, language, languages]);
return (
<DropdownMenu
options={optionsPicker}
showArrow
buttonCss={css`
&:hover {
background-color: var(
--c--components--button--primary-text--background--color-hover
);
}
border-radius: 4px;
padding: 0.5rem 0.6rem;
& > div {
gap: 0.2rem;
display: flex;
}
& .material-icons {
color: var(--c--components--button--primary-text--color) !important;
}
`}
>
<Text
$theme="primary"
aria-label={t('Language')}
$direction="row"
$gap="0.5rem"
>
<Text $isMaterialIcon $color="inherit" $size="xl">
translate
</Text>
{LANGUAGES_ALLOWED[language]}
</Text>
</DropdownMenu>
); );
}; };