mirror of
https://github.com/suitenumerique/docs
synced 2026-04-21 13:37:20 +00:00
🚸(frontend) hint min char search users
We give a hint to the user about the minimum number of characters required to perform a search in the quick search input of the doc share modal. This is to improve the user experience.
This commit is contained in:
parent
03fd1fe50e
commit
fb92a43755
6 changed files with 72 additions and 8 deletions
|
|
@ -6,6 +6,10 @@ and this project adheres to
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- 🚸(frontend) hint min char search users #2064
|
||||
|
||||
### Changed
|
||||
|
||||
- 💄(frontend) improve comments highlights #1961
|
||||
|
|
|
|||
|
|
@ -17,6 +17,41 @@ test.describe('Document create member', () => {
|
|||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('it checks search hints', async ({ page, browserName }) => {
|
||||
await createDoc(page, 'select-multi-users', browserName, 1);
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
const shareModal = page.getByLabel('Share the document');
|
||||
await expect(shareModal.getByText('Document owner')).toBeVisible();
|
||||
|
||||
const inputSearch = page.getByTestId('quick-search-input');
|
||||
await inputSearch.fill('u');
|
||||
await expect(shareModal.getByText('Document owner')).toBeHidden();
|
||||
await expect(
|
||||
shareModal.getByText('Type at least 3 characters to display user names'),
|
||||
).toBeVisible();
|
||||
await inputSearch.fill('user');
|
||||
await expect(
|
||||
shareModal.getByText('Type at least 3 characters to display user names'),
|
||||
).toBeHidden();
|
||||
await expect(shareModal.getByText('Choose a user')).toBeVisible();
|
||||
await inputSearch.fill('anything');
|
||||
await expect(shareModal.getByText('Choose a user')).toBeHidden();
|
||||
await expect(
|
||||
shareModal.getByText(
|
||||
'No results. Type a full email address to invite someone.',
|
||||
),
|
||||
).toBeVisible();
|
||||
await inputSearch.fill('anything@test.com');
|
||||
await expect(
|
||||
shareModal.getByText(
|
||||
'No results. Type a full email address to invite someone.',
|
||||
),
|
||||
).toBeHidden();
|
||||
await expect(shareModal.getByText('Choose the email')).toBeVisible();
|
||||
});
|
||||
|
||||
test('it selects 2 users and 1 invitation', async ({ page, browserName }) => {
|
||||
const inputFill = 'user.test';
|
||||
const responsePromise = page.waitForResponse(
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export const QuickSearchInput = ({
|
|||
$direction="row"
|
||||
$align="center"
|
||||
className="quick-search-input"
|
||||
$gap={spacingsTokens['2xs']}
|
||||
$gap={spacingsTokens['xxs']}
|
||||
$padding={{ horizontal: 'base', vertical: 'xxs' }}
|
||||
>
|
||||
<Icon iconName="search" $variation="secondary" aria-hidden="true" />
|
||||
|
|
@ -62,6 +62,7 @@ export const QuickSearchInput = ({
|
|||
placeholder={placeholder ?? t('Search')}
|
||||
onValueChange={onFilter}
|
||||
maxLength={254}
|
||||
minLength={6}
|
||||
data-testid="quick-search-input"
|
||||
/>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -18,14 +18,15 @@ export const QuickSearchStyle = createGlobalStyle`
|
|||
[cmdk-input] {
|
||||
border: none;
|
||||
width: 100%;
|
||||
font-size: 17px;
|
||||
font-size: 16px;
|
||||
background: white;
|
||||
outline: none;
|
||||
color: var(--c--contextuals--content--semantic--neutral--primary);
|
||||
border-radius: var(--c--globals--spacings--0);
|
||||
font-family: var(--c--globals--font--families--base);
|
||||
|
||||
&::placeholder {
|
||||
color: var(--c--globals--colors--gray-500);
|
||||
color: var(--c--contextuals--content--semantic--neutral--tertiary);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,8 @@ export const DocShareAddMemberList = ({
|
|||
$scope="surface"
|
||||
$theme="tertiary"
|
||||
$variation=""
|
||||
$border="1px solid var(--c--contextuals--border--semantic--contextual--primary)"
|
||||
$border="1px solid var(--c--contextuals--border--surface--primary)"
|
||||
$margin={{ bottom: 'sm' }}
|
||||
>
|
||||
<Box
|
||||
$direction="row"
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
|
|||
/>
|
||||
)}
|
||||
{showMemberSection && isRootDoc && (
|
||||
<Box $padding={{ horizontal: 'base' }}>
|
||||
<Box $padding={{ horizontal: 'base', top: 'base' }}>
|
||||
<QuickSearchGroupAccessRequest doc={doc} />
|
||||
<QuickSearchGroupInvitation doc={doc} />
|
||||
<QuickSearchGroupMember doc={doc} />
|
||||
|
|
@ -301,6 +301,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => {
|
|||
searchUsersRawData={searchUsersQuery.data}
|
||||
onSelect={onSelect}
|
||||
userQuery={userQuery}
|
||||
minLength={API_USERS_SEARCH_QUERY_MIN_LENGTH}
|
||||
/>
|
||||
)}
|
||||
</QuickSearch>
|
||||
|
|
@ -321,14 +322,35 @@ interface QuickSearchInviteInputSectionProps {
|
|||
onSelect: (usr: User) => void;
|
||||
searchUsersRawData: User[] | undefined;
|
||||
userQuery: string;
|
||||
minLength: number;
|
||||
}
|
||||
|
||||
const QuickSearchInviteInputSection = ({
|
||||
onSelect,
|
||||
searchUsersRawData,
|
||||
userQuery,
|
||||
minLength,
|
||||
}: QuickSearchInviteInputSectionProps) => {
|
||||
const { t } = useTranslation();
|
||||
const hint = useMemo(() => {
|
||||
if (userQuery.length < minLength) {
|
||||
return t('Type at least {{minLength}} characters to display user names', {
|
||||
minLength,
|
||||
});
|
||||
}
|
||||
if (isValidEmail(userQuery)) {
|
||||
return t('Choose the email');
|
||||
}
|
||||
if (!searchUsersRawData?.length) {
|
||||
return t('No results. Type a full email address to invite someone.');
|
||||
}
|
||||
|
||||
return t('Choose a user');
|
||||
}, [minLength, searchUsersRawData?.length, t, userQuery]);
|
||||
|
||||
useEffect(() => {
|
||||
announce(hint, 'polite');
|
||||
}, [hint]);
|
||||
|
||||
const searchUserData: QuickSearchData<User> = useMemo(() => {
|
||||
const users = searchUsersRawData || [];
|
||||
|
|
@ -347,7 +369,7 @@ const QuickSearchInviteInputSection = ({
|
|||
);
|
||||
|
||||
return {
|
||||
groupName: t('Search user result'),
|
||||
groupName: hint,
|
||||
elements: users,
|
||||
endActions:
|
||||
isEmail && !hasEmailInUsers
|
||||
|
|
@ -359,12 +381,12 @@ const QuickSearchInviteInputSection = ({
|
|||
]
|
||||
: undefined,
|
||||
};
|
||||
}, [onSelect, searchUsersRawData, t, userQuery]);
|
||||
}, [searchUsersRawData, userQuery, hint, onSelect]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
aria-label={t('List search user result card')}
|
||||
$padding={{ horizontal: 'base', bottom: '3xs' }}
|
||||
$padding={{ horizontal: 'base', bottom: '3xs', top: 'base' }}
|
||||
>
|
||||
<QuickSearchGroup
|
||||
group={searchUserData}
|
||||
|
|
|
|||
Loading…
Reference in a new issue