From a162929fd7d0419bde9599a18b997baf2154d1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B4mulo=20Penido?= Date: Mon, 12 May 2025 14:05:28 -0300 Subject: [PATCH] fix: improve focus/selected style on library authoring (#1918) (#1930) Improves the focus and selected styles from the LibraryPage and UnitPage. --- src/generic/DraggableList/SortableItem.jsx | 4 +- .../components/BaseCard.scss | 58 ++++++++++++++----- src/library-authoring/components/BaseCard.tsx | 7 ++- .../components/CollectionCard.tsx | 8 ++- .../components/ComponentCard.tsx | 8 ++- .../components/ContainerCard.tsx | 8 ++- .../units/LibraryUnitBlocks.tsx | 8 ++- src/library-authoring/units/index.scss | 17 ++++++ 8 files changed, 94 insertions(+), 24 deletions(-) diff --git a/src/generic/DraggableList/SortableItem.jsx b/src/generic/DraggableList/SortableItem.jsx index 57ee5d00c..cf488d8b5 100644 --- a/src/generic/DraggableList/SortableItem.jsx +++ b/src/generic/DraggableList/SortableItem.jsx @@ -18,6 +18,7 @@ const SortableItem = ({ isClickable, onClick, disabled, + cardClassName = '', // injected intl, }) => { @@ -52,7 +53,7 @@ const SortableItem = ({ > @@ -94,6 +95,7 @@ SortableItem.propTypes = { isClickable: PropTypes.bool, onClick: PropTypes.func, disabled: PropTypes.bool, + cardClassName: PropTypes.string, // injected intl: intlShape.isRequired, }; diff --git a/src/library-authoring/components/BaseCard.scss b/src/library-authoring/components/BaseCard.scss index 3a13bd14c..84f0453c8 100644 --- a/src/library-authoring/components/BaseCard.scss +++ b/src/library-authoring/components/BaseCard.scss @@ -2,24 +2,56 @@ .pgn__card { height: 100%; min-width: 15rem; - } - .library-item-header { - border-top-left-radius: .375rem; - border-top-right-radius: .375rem; - padding: 0 .5rem 0 1.25rem; - - .library-item-header-icon { - width: 2.3rem; - height: 2.3rem; + &::before { + border: none !important; // Remove default focus } - .pgn__card-header-content { - margin-top: .55rem; + &.selected:not(:focus) { + border: 2px $gray-700 solid; + + .library-item-header { + border-top-left-radius: calc(.375rem - 2px); + border-top-right-radius: calc(.375rem - 2px); + } } - .pgn__card-header-actions { - margin: .25rem 0 .25rem 1rem; + &.selected:focus { + border: 3px $gray-700 solid; + + .library-item-header { + border-top-left-radius: calc(.375rem - 3px); + border-top-right-radius: calc(.375rem - 3px); + } + } + + &:not(.selected):focus { + outline: 1px $gray-200 solid; + outline-offset: 2px; + } + + &:not(.selected) { + .library-item-header { + border-top-left-radius: .375rem; + border-top-right-radius: .375rem; + } + } + + .library-item-header { + padding: 0 .5rem 0 1.25rem; + + .library-item-header-icon { + width: 2.3rem; + height: 2.3rem; + } + + .pgn__card-header-content { + margin-top: .55rem; + } + + .pgn__card-header-actions { + margin: .25rem 0 .25rem 1rem; + } } } diff --git a/src/library-authoring/components/BaseCard.tsx b/src/library-authoring/components/BaseCard.tsx index 2b1593789..591fc3be6 100644 --- a/src/library-authoring/components/BaseCard.tsx +++ b/src/library-authoring/components/BaseCard.tsx @@ -22,7 +22,8 @@ type BaseCardProps = { tags: ContentHitTags; actions: React.ReactNode; hasUnpublishedChanges?: boolean; - onSelect: () => void + onSelect: () => void; + selected?: boolean; }; const BaseCard = ({ @@ -33,6 +34,7 @@ const BaseCard = ({ tags, actions, onSelect, + selected = false, ...props } : BaseCardProps) => { const tagCount = useMemo(() => { @@ -47,7 +49,7 @@ const BaseCard = ({ const intl = useIntl(); return ( - + { const { componentPickerMode } = useComponentPickerContext(); const { showOnlyPublished } = useLibraryContext(); - const { openCollectionInfoSidebar } = useSidebarContext(); + const { openCollectionInfoSidebar, sidebarComponentInfo } = useSidebarContext(); const { type: itemType, @@ -132,6 +132,9 @@ const CollectionCard = ({ hit } : CollectionCardProps) => { const { displayName = '', description = '' } = formatted; + const selected = sidebarComponentInfo?.type === SidebarBodyComponentId.CollectionInfo + && sidebarComponentInfo.id === collectionId; + const { navigateTo } = useLibraryRoutes(); const openCollection = useCallback(() => { openCollectionInfoSidebar(collectionId); @@ -154,6 +157,7 @@ const CollectionCard = ({ hit } : CollectionCardProps) => { )} onSelect={openCollection} + selected={selected} /> ); }; diff --git a/src/library-authoring/components/ComponentCard.tsx b/src/library-authoring/components/ComponentCard.tsx index 86dccbfd4..4b58147fb 100644 --- a/src/library-authoring/components/ComponentCard.tsx +++ b/src/library-authoring/components/ComponentCard.tsx @@ -6,7 +6,7 @@ import { import { type ContentHit, PublishStatus } from '../../search-manager'; import { useComponentPickerContext } from '../common/context/ComponentPickerContext'; import { useLibraryContext } from '../common/context/LibraryContext'; -import { useSidebarContext } from '../common/context/SidebarContext'; +import { SidebarBodyComponentId, useSidebarContext } from '../common/context/SidebarContext'; import { useLibraryRoutes } from '../routes'; import AddComponentWidget from './AddComponentWidget'; import BaseCard from './BaseCard'; @@ -18,7 +18,7 @@ type ComponentCardProps = { const ComponentCard = ({ hit }: ComponentCardProps) => { const { showOnlyPublished } = useLibraryContext(); - const { openComponentInfoSidebar } = useSidebarContext(); + const { openComponentInfoSidebar, sidebarComponentInfo } = useSidebarContext(); const { componentPickerMode } = useComponentPickerContext(); const { @@ -44,6 +44,9 @@ const ComponentCard = ({ hit }: ComponentCardProps) => { } }, [usageKey, navigateTo, openComponentInfoSidebar]); + const selected = sidebarComponentInfo?.type === SidebarBodyComponentId.ComponentInfo + && sidebarComponentInfo.id === usageKey; + return ( { )} hasUnpublishedChanges={publishStatus !== PublishStatus.Published} onSelect={openComponent} + selected={selected} /> ); }; diff --git a/src/library-authoring/components/ContainerCard.tsx b/src/library-authoring/components/ContainerCard.tsx index 97e30e382..1617c9d1f 100644 --- a/src/library-authoring/components/ContainerCard.tsx +++ b/src/library-authoring/components/ContainerCard.tsx @@ -17,7 +17,7 @@ import { ToastContext } from '../../generic/toast-context'; import { type ContainerHit, PublishStatus } from '../../search-manager'; import { useComponentPickerContext } from '../common/context/ComponentPickerContext'; import { useLibraryContext } from '../common/context/LibraryContext'; -import { SidebarActions, useSidebarContext } from '../common/context/SidebarContext'; +import { SidebarActions, SidebarBodyComponentId, useSidebarContext } from '../common/context/SidebarContext'; import { useRemoveItemsFromCollection } from '../data/apiHooks'; import { useLibraryRoutes } from '../routes'; import AddComponentWidget from './AddComponentWidget'; @@ -174,7 +174,7 @@ type ContainerCardProps = { const ContainerCard = ({ hit } : ContainerCardProps) => { const { componentPickerMode } = useComponentPickerContext(); const { setUnitId, showOnlyPublished } = useLibraryContext(); - const { openUnitInfoSidebar } = useSidebarContext(); + const { openUnitInfoSidebar, sidebarComponentInfo } = useSidebarContext(); const { blockType: itemType, @@ -199,6 +199,9 @@ const ContainerCard = ({ hit } : ContainerCardProps) => { showOnlyPublished ? published?.content?.childUsageKeys : content?.childUsageKeys ) ?? []; + const selected = sidebarComponentInfo?.type === SidebarBodyComponentId.UnitInfo + && sidebarComponentInfo.id === unitId; + const { navigateTo } = useLibraryRoutes(); const openContainer = useCallback(() => { @@ -227,6 +230,7 @@ const ContainerCard = ({ hit } : ContainerCardProps) => { )} hasUnpublishedChanges={publishStatus !== PublishStatus.Published} onSelect={openContainer} + selected={selected} /> ); }; diff --git a/src/library-authoring/units/LibraryUnitBlocks.tsx b/src/library-authoring/units/LibraryUnitBlocks.tsx index aa2b01c88..f518e976d 100644 --- a/src/library-authoring/units/LibraryUnitBlocks.tsx +++ b/src/library-authoring/units/LibraryUnitBlocks.tsx @@ -29,7 +29,7 @@ import { import { LibraryBlock } from '../LibraryBlock'; import { useLibraryRoutes, ContentType } from '../routes'; import messages from './messages'; -import { SidebarActions, useSidebarContext } from '../common/context/SidebarContext'; +import { SidebarActions, SidebarBodyComponentId, useSidebarContext } from '../common/context/SidebarContext'; import { ToastContext } from '../../generic/toast-context'; import { canEditComponent } from '../components/ComponentEditorModal'; import { useRunOnNextRender } from '../../utils'; @@ -139,7 +139,7 @@ const ComponentBlock = ({ block, preview, isDragging }: ComponentBlockProps) => unitId, collectionId, componentId, openComponentEditor, } = useLibraryContext(); - const { openInfoSidebar } = useSidebarContext(); + const { openInfoSidebar, sidebarComponentInfo } = useSidebarContext(); const handleComponentSelection = useCallback((numberOfClicks: number) => { navigateTo({ componentId: block.originalId }); @@ -182,6 +182,9 @@ const ComponentBlock = ({ block, preview, isDragging }: ComponentBlockProps) => return {}; }, [isDragging, componentId, block]); + const selected = sidebarComponentInfo?.type === SidebarBodyComponentId.ComponentInfo + && sidebarComponentInfo?.id === block.id; + return ( isClickable onClick={(e: { detail: number; }) => handleComponentSelection(e.detail)} disabled={preview} + cardClassName={selected ? 'selected' : undefined} > {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}