✨(frontend) make the team pannel closable
Team panel was quite wide, and took too much space on small screens. Johann decided to make it closable. Thus, user that needs to navigate quickly between their team can open it, use it and then close it. This animation is a first draft, and should be improved later on. Also, some accessibility issues might ariase, I have ignored them in this first draft.
This commit is contained in:
committed by
aleb_the_flash
parent
ebaa1360e7
commit
e8aba29a68
@@ -23,7 +23,7 @@ export const Menu = () => {
|
||||
$height="100%"
|
||||
$justify="space-between"
|
||||
>
|
||||
<Box className="pt-b" $direction="column" $gap="0.8rem">
|
||||
<Box className="pt-l" $direction="column" $gap="0.8rem">
|
||||
<MenuItem Icon={IconSearch} label={t('Search')} href="/" />
|
||||
<MenuItem Icon={IconFavorite} label={t('Favorite')} href="/favorite" />
|
||||
<MenuItem Icon={IconRecent} label={t('Recent')} href="/recent" />
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import { Panel } from '@/features/teams';
|
||||
import { AppWrapper } from '@/tests/utils';
|
||||
|
||||
import { TeamList } from '../components/Panel/TeamList';
|
||||
@@ -127,4 +129,46 @@ describe('PanelTeams', () => {
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders with team panel open', async () => {
|
||||
fetchMock.mock(`/api/teams/?page=1&ordering=-created_at`, {
|
||||
count: 1,
|
||||
results: [],
|
||||
});
|
||||
|
||||
render(<Panel />, { wrapper: AppWrapper });
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'Close the teams panel' }),
|
||||
).toBeVisible();
|
||||
|
||||
expect(await screen.findByText('Recents')).toBeVisible();
|
||||
});
|
||||
|
||||
it('closes and opens the team panel', async () => {
|
||||
fetchMock.mock(`/api/teams/?page=1&ordering=-created_at`, {
|
||||
count: 1,
|
||||
results: [],
|
||||
});
|
||||
|
||||
render(<Panel />, { wrapper: AppWrapper });
|
||||
|
||||
expect(await screen.findByText('Recents')).toBeVisible();
|
||||
|
||||
await userEvent.click(
|
||||
screen.getByRole('button', {
|
||||
name: 'Close the teams panel',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('Recents')).not.toBeVisible();
|
||||
|
||||
await userEvent.click(
|
||||
screen.getByRole('button', {
|
||||
name: 'Open the teams panel',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('Recents')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="11.5" transform="rotate(-180 12 12)" fill="white" stroke="currentColor"/>
|
||||
<path d="M14.1683 16.232C14.4803 15.92 14.4803 15.416 14.1683 15.104L11.0643 12L14.1683 8.896C14.4803 8.584 14.4803 8.08 14.1683 7.768C13.8563 7.456 13.3523 7.456 13.0403 7.768L9.36834 11.44C9.05634 11.752 9.05634 12.256 9.36834 12.568L13.0403 16.24C13.3443 16.544 13.8563 16.544 14.1683 16.232Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 500 B |
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { Box, BoxButton, Text } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import IconOpenClose from '@/features/teams/assets/icon-open-close.svg';
|
||||
|
||||
import { PanelActions } from './PanelActions';
|
||||
import { TeamList } from './TeamList';
|
||||
@@ -11,32 +12,69 @@ export const Panel = () => {
|
||||
const { t } = useTranslation();
|
||||
const { colorsTokens } = useCunninghamTheme();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
|
||||
const closedOverridingStyles = !isOpen && {
|
||||
$width: '0',
|
||||
$maxWidth: '0',
|
||||
$minWidth: '0',
|
||||
};
|
||||
|
||||
const transition = 'all 0.5s ease-in-out';
|
||||
|
||||
return (
|
||||
<Box
|
||||
$width="100%"
|
||||
$maxWidth="20rem"
|
||||
$minWidth="14rem"
|
||||
$css={`
|
||||
position: relative;
|
||||
border-right: 1px solid ${colorsTokens()['primary-300']};
|
||||
transition: ${transition};
|
||||
`}
|
||||
$height="inherit"
|
||||
aria-label="Teams panel"
|
||||
{...closedOverridingStyles}
|
||||
>
|
||||
<Box
|
||||
className="p-s"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$justify="space-between"
|
||||
<BoxButton
|
||||
aria-label={
|
||||
isOpen ? t('Close the teams panel') : t('Open the teams panel')
|
||||
}
|
||||
$color={colorsTokens()['primary-600']}
|
||||
$css={`
|
||||
border-bottom: 1px solid ${colorsTokens()['primary-300']};
|
||||
position: absolute;
|
||||
right: -1.2rem;
|
||||
top: 1.03rem;
|
||||
transform: rotate(${isOpen ? '0' : '180'}deg);
|
||||
transition: ${transition};
|
||||
`}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
<IconOpenClose width={24} height={24} />
|
||||
</BoxButton>
|
||||
<Box
|
||||
$css={`
|
||||
overflow: hidden;
|
||||
opacity: ${isOpen ? '1' : '0'};
|
||||
transition: ${transition};
|
||||
`}
|
||||
>
|
||||
<Text $weight="bold" $size="1.25rem">
|
||||
{t('Recents')}
|
||||
</Text>
|
||||
<PanelActions />
|
||||
<Box
|
||||
className="pr-l pl-s pt-s pb-s"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$justify="space-between"
|
||||
$css={`
|
||||
border-bottom: 1px solid ${colorsTokens()['primary-300']};
|
||||
`}
|
||||
>
|
||||
<Text $weight="bold" $size="1.25rem">
|
||||
{t('Recents')}
|
||||
</Text>
|
||||
<PanelActions />
|
||||
</Box>
|
||||
<TeamList />
|
||||
</Box>
|
||||
<TeamList />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -88,6 +88,9 @@ export const TeamItem = ({ team }: TeamProps) => {
|
||||
<Text
|
||||
$weight="bold"
|
||||
$color={!hasMembers ? colorsTokens()['greyscale-600'] : undefined}
|
||||
$css={`
|
||||
min-width: 14rem;
|
||||
`}
|
||||
>
|
||||
{team.name}
|
||||
</Text>
|
||||
|
||||
@@ -73,7 +73,7 @@ export const TeamList = () => {
|
||||
}, [data?.pages]);
|
||||
|
||||
return (
|
||||
<Box $css="overflow: auto;" ref={containerRef}>
|
||||
<Box $css="overflow-y: auto; overflow-x: hidden;" ref={containerRef}>
|
||||
<InfiniteScroll
|
||||
hasMore={hasNextPage}
|
||||
isLoading={isFetchingNextPage}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"Cells icon": "Icône Cellules",
|
||||
"Choose a role": "Choisissez un rôle",
|
||||
"Close the modal": "Fermer la modale",
|
||||
"Close the teams panel": "Fermer le menu des groupes",
|
||||
"Confirm deletion": "Confirmer la suppression",
|
||||
"Contacts": "Contacts",
|
||||
"Content modal to delete the team": "Contenu modal pour supprimer le groupe",
|
||||
@@ -62,6 +63,7 @@
|
||||
"Names": "Noms",
|
||||
"New name...": "Nouveau nom...",
|
||||
"Open the member options modal": "Ouvrir les options de membre dans la fenêtre modale",
|
||||
"Open the teams panel": "Ouvrir le menu des groupes",
|
||||
"Open the team options": "Ouvrir les options de groupe",
|
||||
"Ouch !": "Ooops !",
|
||||
"Owner": "Propriétaire",
|
||||
|
||||
Reference in New Issue
Block a user