diff --git a/CHANGELOG.md b/CHANGELOG.md index 98ae36b9..41c0f7aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,17 @@ and this project adheres to ## [Unreleased] +### Changed + +- ♿️(frontend) structure correctly 5xx error alerts #2128 +- ♿️(frontend) make doc search result labels uniquely identifiable #2212 + ### Fixed - 🚸(frontend) redirect on current url tab after 401 #2197 - 🐛(frontend) abort check media status unmount #2194 - ✨(backend) order pinned documents by last updated at #2028 - -### Changed - -- ♿️(frontend) structure correctly 5xx error alerts #2128 -- ♿️(frontend) make doc search result labels uniquely identifiable #2212 +- 🛂(frontend) fix cannot manage member on small screen #2226 ## [v4.8.6] - 2026-04-08 diff --git a/src/frontend/apps/impress/src/components/quick-search/QuickSearchItemContent.tsx b/src/frontend/apps/impress/src/components/quick-search/QuickSearchItemContent.tsx index 070126a5..d95127bf 100644 --- a/src/frontend/apps/impress/src/components/quick-search/QuickSearchItemContent.tsx +++ b/src/frontend/apps/impress/src/components/quick-search/QuickSearchItemContent.tsx @@ -1,7 +1,6 @@ import { ReactNode } from 'react'; import { useCunninghamTheme } from '@/cunningham'; -import { useResponsiveStore } from '@/stores'; import { Box } from '../Box'; @@ -18,29 +17,29 @@ export const QuickSearchItemContent = ({ }: QuickSearchItemContentProps) => { const { spacingsTokens } = useCunninghamTheme(); - const { isDesktop } = useResponsiveStore(); - return ( {left} - {isDesktop && right && ( + {right && ( diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx index de8caf56..1354b4d4 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx @@ -6,7 +6,7 @@ import { } from '@gouvfr-lasuite/cunningham-react'; import { MouseEventHandler, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { createGlobalStyle } from 'styled-components'; +import { createGlobalStyle, css } from 'styled-components'; import { Box, @@ -20,6 +20,7 @@ import { QuickSearchData, QuickSearchGroup } from '@/components/quick-search'; import { useCunninghamTheme } from '@/cunningham'; import { AccessRequest, Doc, Role } from '@/docs/doc-management/'; import { useAuth } from '@/features/auth'; +import { useResponsiveStore } from '@/stores'; import { useAcceptDocAccessRequest, @@ -33,8 +34,12 @@ import { DocRoleDropdown } from './DocRoleDropdown'; import { SearchUserRow } from './SearchUserRow'; const QuickSearchGroupAccessRequestStyle = createGlobalStyle` - .--docs--share-access-request [cmdk-item][data-selected='true'] { - background: inherit + .quick-search-container .--docs--share-access-request [cmdk-item]:hover, + .quick-search-container .--docs--share-access-request [cmdk-item][data-selected='true'] { + background: inherit; + } + .--docs--doc-share-access-request-item:hover { + background: var(--c--contextuals--background--semantic--contextual--primary); } `; @@ -45,6 +50,7 @@ type Props = { const DocShareAccessRequestItem = ({ doc, accessRequest }: Props) => { const { t } = useTranslation(); + const { isSmallMobile } = useResponsiveStore(); const { toast } = useToastProvider(); const { spacingsTokens } = useCunninghamTheme(); const { mutate: acceptDocAccessRequests } = useAcceptDocAccessRequest(); @@ -67,6 +73,15 @@ const DocShareAccessRequestItem = ({ doc, accessRequest }: Props) => { $width="100%" data-testid={`doc-share-access-request-row-${accessRequest.user.email}`} className="--docs--doc-share-access-request-item" + $css={css` + & .--docs--quick-search-item-content { + flex-wrap: wrap; + + .--docs--quick-search-item-content-right { + margin-left: auto; + } + } + `} > { /> @@ -153,6 +168,7 @@ export const QuickSearchGroupAccessRequest = ({ { const { t } = useTranslation(); const { toast } = useToastProvider(); - + const { isSmallMobile } = useResponsiveStore(); const [isLoading, setIsLoading] = useState(false); const { spacingsTokens } = useCunninghamTheme(); const [invitationRole, setInvitationRole] = useState(Role.EDITOR); @@ -118,14 +119,15 @@ export const DocShareAddMemberList = ({ ))} - + {t('Invite')} diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAddMemberListItem.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAddMemberListItem.tsx index 7205ac8c..a973acd7 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAddMemberListItem.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAddMemberListItem.tsx @@ -1,4 +1,5 @@ import { useTranslation } from 'react-i18next'; +import { css } from 'styled-components'; import { Box, BoxButton, Icon, Text } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; @@ -31,7 +32,13 @@ export const DocShareAddMemberListItem = ({ user, onRemoveUser }: Props) => { $theme="neutral" $variation="secondary" > - + {user.full_name || user.email} + ( diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareMember.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareMember.tsx index fd2bc47e..bb8ccbb3 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareMember.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareMember.tsx @@ -30,7 +30,6 @@ export const DocShareMemberItem = ({ const { t } = useTranslation(); const { isLastOwner } = useWhoAmI(access); const { toast } = useToastProvider(); - const { spacingsTokens } = useCunninghamTheme(); const message = isLastOwner @@ -121,7 +120,10 @@ export const QuickSearchGroupMember = ({ }, [membersQuery.data, t]); return ( - + ( diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx index 317b1ca2..8d43218c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx @@ -63,7 +63,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { const API_USERS_SEARCH_QUERY_MIN_LENGTH = config?.API_USERS_SEARCH_QUERY_MIN_LENGTH || 5; - const { isDesktop } = useResponsiveStore(); + const { isLargeScreen } = useResponsiveStore(); /** * The modal content height is calculated based on the viewport height. @@ -75,7 +75,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { * - 690px is the height of the content in desktop * This ensures that the modal content is always visible and does not overflow. */ - const modalContentHeight = isDesktop + const modalContentHeight = isLargeScreen ? 'min(690px, calc(100dvh - 2em - 12px - 34px))' : `calc(100dvh - 34px)`; const [selectedUsers, setSelectedUsers] = useState([]); @@ -181,7 +181,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { closeOnClickOutside data-testid="doc-share-modal" aria-label={t('Share the document')} - size={isDesktop ? ModalSize.LARGE : ModalSize.FULL} + size={isLargeScreen ? ModalSize.LARGE : ModalSize.FULL} aria-modal="true" onClose={onClose} title={ @@ -289,9 +289,11 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { /> )} {showMemberSection && isRootDoc && ( - + + + )} diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/SearchUserRow.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/SearchUserRow.tsx index 3ba97e5d..f908dee3 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/SearchUserRow.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/SearchUserRow.tsx @@ -1,3 +1,5 @@ +import { css } from 'styled-components'; + import { Box, Text } from '@/components'; import { QuickSearchItemContent, @@ -38,11 +40,24 @@ export const SearchUserRow = ({ background={isInvitation ? colorsTokens['gray-400'] : undefined} /> - + {hasFullName ? user.full_name : user.email} {hasFullName && ( - + {user.email} )} diff --git a/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx index 7da3133c..dd8d998d 100644 --- a/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx +++ b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx @@ -10,10 +10,12 @@ export interface UseResponsiveStore { screenWidth: number; setScreenSize: (size: ScreenSize) => void; isDesktop: boolean; + isLargeScreen: boolean; initializeResizeListener: () => () => void; } const initialState = { + isLargeScreen: false, isMobile: false, isSmallMobile: false, isTablet: false, @@ -24,6 +26,7 @@ const initialState = { export const useResponsiveStore = create((set) => ({ isDesktop: initialState.isDesktop, + isLargeScreen: initialState.isLargeScreen, isMobile: initialState.isMobile, isSmallMobile: initialState.isSmallMobile, isTablet: initialState.isTablet, @@ -40,6 +43,7 @@ export const useResponsiveStore = create((set) => ({ isMobile: true, isTablet: true, isSmallMobile: true, + isLargeScreen: false, }); } else if (width < 768) { set({ @@ -48,6 +52,7 @@ export const useResponsiveStore = create((set) => ({ isTablet: true, isMobile: true, isSmallMobile: false, + isLargeScreen: false, }); } else if (width >= 768 && width < 1024) { set({ @@ -56,6 +61,7 @@ export const useResponsiveStore = create((set) => ({ isTablet: true, isMobile: false, isSmallMobile: false, + isLargeScreen: true, }); } else { set({ @@ -64,6 +70,7 @@ export const useResponsiveStore = create((set) => ({ isTablet: false, isMobile: false, isSmallMobile: false, + isLargeScreen: true, }); }