(frontend) enhance DocShareModal and footer components

- Refactored DocShareModal to improve user experience with dynamic list
height and responsive design adjustments.
- Introduced new styling for modal elements using createGlobalStyle for
better visual consistency.
- Updated footer button text from 'Ok' to 'OK' for improved clarity.
- Enhanced user selection handling and search functionality within the
modal for better document sharing experience.
This commit is contained in:
Nathan Panchout
2025-01-09 09:14:55 +01:00
committed by Anthony LC
parent 098df5c0b5
commit f02dcae52a
2 changed files with 128 additions and 94 deletions

View File

@@ -1,7 +1,7 @@
import { Modal, ModalSize } from '@openfun/cunningham-react';
import { useMemo, useState } from 'react';
import { useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { createGlobalStyle, css } from 'styled-components';
import { useDebouncedCallback } from 'use-debounce';
import { Box } from '@/components';
@@ -29,20 +29,33 @@ import { DocShareMemberItem } from './DocShareMemberItem';
import { DocShareModalFooter } from './DocShareModalFooter';
import { DocShareModalInviteUserRow } from './DocShareModalInviteUserByEmail';
const ShareModalStyle = createGlobalStyle`
.c__modal__title {
padding-bottom: 0 !important;
}
`;
type Props = {
doc: Doc;
onClose: () => void;
};
export const DocShareModal = ({ doc, onClose }: Props) => {
const { t } = useTranslation();
const selectedUsersRef = useRef<HTMLDivElement>(null);
const { isDesktop } = useResponsiveStore();
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
const [userQuery, setUserQuery] = useState('');
const [inputValue, setInputValue] = useState('');
const [listHeight, setListHeight] = useState<string>('400px');
const canShare = doc.abilities.accesses_manage;
const showMemberSection = inputValue === '' && selectedUsers.length === 0;
const showFooter = selectedUsers.length === 0 && !inputValue;
const onSelect = (user: User) => {
setSelectedUsers((prev) => [...prev, user]);
@@ -73,7 +86,10 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
const count = membersQuery.data?.pages[0]?.count ?? 1;
return {
groupName: t('Share with {{count}} users', {
groupName:
count === 1
? t('Document owner')
: t('Share with {{count}} users', {
count: count,
}),
elements: members,
@@ -147,7 +163,20 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
});
};
const handleRef = (node: HTMLDivElement) => {
const contentHeight = isDesktop ? '690px' : '100dvh - 34px'; // 690px is the height of the content in desktop ad 34px is the height of the modal title in mobile
const inputHeight = canShare ? 70 : 0;
const marginTop = 11;
const footerHeight = node?.clientHeight ?? 0;
const selectedUsersHeight = selectedUsersRef.current?.clientHeight ?? 0;
const height = `calc(${contentHeight} - ${footerHeight}px - ${selectedUsersHeight}px - ${inputHeight}px - ${marginTop}px)`;
setListHeight(height);
};
return (
<>
<Modal
isOpen
closeOnClickOutside
@@ -157,26 +186,28 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
onClose={onClose}
title={<Box $align="flex-start">{t('Share the document')}</Box>}
>
<ShareModalStyle />
<Box
aria-label={t('Share modal')}
$direction="column"
$height={isDesktop ? '690px' : `calc(100dvh - 34px)`}
$overflow="hidden"
$justify="space-between"
>
<Box
$flex={1}
className="toto"
$css={css`
overflow-y: auto;
[cmdk-list] {
overflow-y: auto;
height: ${isDesktop
? '400px'
: 'calc(100vh - 49px - 68px - 229px)'};
height: ${listHeight};
}
`}
>
<div ref={selectedUsersRef}>
{canShare && selectedUsers.length > 0 && (
<Box $padding={{ horizontal: 'base' }} $margin={{ top: '11px' }}>
<Box
$padding={{ horizontal: 'base' }}
$margin={{ top: '11px' }}
>
<DocShareAddMemberList
doc={doc}
selectedUsers={selectedUsers}
@@ -189,6 +220,7 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
/>
</Box>
)}
</div>
<Box data-testid="doc-share-quick-search">
<QuickSearch
@@ -239,10 +271,12 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
</QuickSearch>
</Box>
</Box>
{selectedUsers.length === 0 && !inputValue && (
<DocShareModalFooter doc={doc} onClose={onClose} />
)}
<Box ref={handleRef}>
{showFooter && <DocShareModalFooter doc={doc} onClose={onClose} />}
</Box>
</Box>
</Modal>
</>
);
};

View File

@@ -61,7 +61,7 @@ export const DocShareModalFooter = ({ doc, onClose }: Props) => {
{t('Copy link')}
</Button>
<Button onClick={onClose} color="primary">
{t('Ok')}
{t('OK')}
</Button>
</Box>
</Box>