fix: Nits on UX/UI in the new sidebars in course outline and unit page [FC-0114] (#2871)
- Fixes the open nits/issues listed in https://github.com/openedx/frontend-app-authoring/issues/2868 - Fixes the small nit in the back button in the import workflow: https://github.com/openedx/frontend-app-authoring/issues/2524#issuecomment-3849649651 - Fixes the small nit in the unsupported text in the import workflow: https://github.com/openedx/frontend-app-authoring/issues/2525#issuecomment-3862737018. This fix depends on https://github.com/openedx/openedx-platform/pull/38005
This commit is contained in:
@@ -327,7 +327,7 @@ const AddTabs = () => {
|
||||
return (
|
||||
<Tabs
|
||||
variant="tabs"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="mb-4 mx-n4.5"
|
||||
id="add-content-tabs"
|
||||
activeKey={key}
|
||||
onSelect={setKey}
|
||||
|
||||
@@ -48,7 +48,7 @@ export const SectionSidebar = ({ sectionId }: Props) => {
|
||||
{sectionData?.hasChanges && <PublishButon onClick={handlePublish} />}
|
||||
<Tabs
|
||||
variant="tabs"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="my-2 mx-n3.5"
|
||||
id="add-content-tabs"
|
||||
activeKey={tab}
|
||||
onSelect={setTab}
|
||||
|
||||
@@ -49,7 +49,7 @@ export const SubsectionSidebar = ({ subsectionId }: Props) => {
|
||||
{subsectionData?.hasChanges && <PublishButon onClick={handlePublish} />}
|
||||
<Tabs
|
||||
variant="tabs"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="my-2 mx-n3.5"
|
||||
id="add-content-tabs"
|
||||
activeKey={tab}
|
||||
onSelect={setTab}
|
||||
|
||||
@@ -70,7 +70,7 @@ export const UnitSidebar = ({ unitId }: Props) => {
|
||||
</Stack>
|
||||
<Tabs
|
||||
variant="tabs"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="my-2 mx-n3.5"
|
||||
id="add-content-tabs"
|
||||
activeKey={tab}
|
||||
onSelect={setTab}
|
||||
|
||||
@@ -339,7 +339,7 @@ export const AddSidebar = () => {
|
||||
<SidebarSection>
|
||||
<Tabs
|
||||
id="unit-add-sidebar"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="mb-2 mx-n4.5 mx-n3.5"
|
||||
activeKey={currentTabKey}
|
||||
onSelect={setCurrentTabKey}
|
||||
>
|
||||
|
||||
@@ -212,7 +212,7 @@ export const UnitInfoSidebar = () => {
|
||||
/>
|
||||
<Tabs
|
||||
id="unit-info-sidebar-tabs"
|
||||
className="my-2 d-flex justify-content-around"
|
||||
className="my-2 mx-n3.5"
|
||||
activeKey={currentTabKey}
|
||||
onSelect={setCurrentTabKey}
|
||||
>
|
||||
|
||||
@@ -7,14 +7,12 @@ import {
|
||||
IconButtonToggle,
|
||||
Stack,
|
||||
} from '@openedx/paragon';
|
||||
import {
|
||||
FormatIndentDecrease,
|
||||
FormatIndentIncrease,
|
||||
} from '@openedx/paragon/icons';
|
||||
import { ResizableBox } from '@src/generic/resizable/Resizable';
|
||||
import type { MessageDescriptor } from 'react-intl';
|
||||
|
||||
import messages from './messages';
|
||||
import { CollapsedIcon } from './icons/CollapsedIcon';
|
||||
import { ExpandedIcon } from './icons/ExpandedIcon';
|
||||
|
||||
export interface SidebarPage {
|
||||
component: React.ComponentType;
|
||||
@@ -88,10 +86,11 @@ export function Sidebar<T extends SidebarPages>({
|
||||
const intl = useIntl();
|
||||
|
||||
const SidebarComponent = pages[currentPageKey].component;
|
||||
const activeKey = isOpen ? currentPageKey : undefined;
|
||||
|
||||
return (
|
||||
<Stack direction="horizontal" className="sidebar align-items-baseline ml-3" gap={2}>
|
||||
{isOpen && !!currentPageKey && (
|
||||
{(isOpen && !!currentPageKey) ? (
|
||||
<ResizableBox>
|
||||
<div className="sidebar-content p-3 bg-white border-right">
|
||||
<Dropdown data-testid="sidebar-dropdown">
|
||||
@@ -121,16 +120,18 @@ export function Sidebar<T extends SidebarPages>({
|
||||
<SidebarComponent />
|
||||
</div>
|
||||
</ResizableBox>
|
||||
) : (
|
||||
<div className="min-vh-100 border" />
|
||||
)}
|
||||
<div className="sidebar-toggle" data-testid="sidebar-toggle">
|
||||
<div className="sidebar-toggle p-1" data-testid="sidebar-toggle">
|
||||
<IconButton
|
||||
src={isOpen ? FormatIndentIncrease : FormatIndentDecrease}
|
||||
src={isOpen ? ExpandedIcon : CollapsedIcon}
|
||||
alt={intl.formatMessage(messages.toggle)}
|
||||
onClick={toggle}
|
||||
variant="primary"
|
||||
/>
|
||||
<IconButtonToggle
|
||||
activeValue={currentPageKey}
|
||||
activeValue={activeKey}
|
||||
onChange={setCurrentPageKey}
|
||||
>
|
||||
{Object.entries(pages).map(([key, page]) => (
|
||||
@@ -142,7 +143,7 @@ export function Sidebar<T extends SidebarPages>({
|
||||
value={key}
|
||||
src={page.icon}
|
||||
alt={intl.formatMessage(page.title)}
|
||||
className="rounded-iconbutton"
|
||||
className="rounded-iconbutton my-2"
|
||||
/>
|
||||
))}
|
||||
</IconButtonToggle>
|
||||
|
||||
@@ -27,17 +27,20 @@ export const SidebarTitle = ({
|
||||
}: SidebarTitleProps) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Stack direction="horizontal" gap={2} className="mb-3">
|
||||
{onBackBtnClick && (
|
||||
<IconButton
|
||||
onClick={onBackBtnClick}
|
||||
alt={intl.formatMessage(messages.backBtnText)}
|
||||
src={ArrowBack}
|
||||
size="inline"
|
||||
/>
|
||||
)}
|
||||
<Icon src={icon} className="mr-2 text-primary" />
|
||||
<h2 className="text-primary h3 mb-0">{title}</h2>
|
||||
</Stack>
|
||||
<>
|
||||
<Stack direction="horizontal" gap={2} className="mb-3">
|
||||
{onBackBtnClick && (
|
||||
<IconButton
|
||||
onClick={onBackBtnClick}
|
||||
alt={intl.formatMessage(messages.backBtnText)}
|
||||
src={ArrowBack}
|
||||
size="inline"
|
||||
/>
|
||||
)}
|
||||
<Icon src={icon} className="mr-2 text-primary" />
|
||||
<h2 className="text-primary h3 mb-0">{title}</h2>
|
||||
</Stack>
|
||||
<hr className="border" style={{ marginLeft: '-1rem', marginRight: '-1rem' }} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
14
src/generic/sidebar/icons/CollapsedIcon.tsx
Normal file
14
src/generic/sidebar/icons/CollapsedIcon.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
export const CollapsedIcon = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M3 18H16V16H3V18ZM3 13H13V11H3V13ZM3 6V8H16V6H3ZM21 15.59L17.42 12L21 8.41L19.59 7L14.59 12L19.59 17L21 15.59Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
14
src/generic/sidebar/icons/ExpandedIcon.tsx
Normal file
14
src/generic/sidebar/icons/ExpandedIcon.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
export const ExpandedIcon = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M21 6L8 6V8L21 8V6ZM21 11H11V13H21V11ZM21 18V16L8 16V18H21ZM3 8.41L6.58 12L3 15.59L4.41 17L9.41 12L4.41 7L3 8.41Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@@ -6,6 +6,25 @@
|
||||
min-height: 100vh;
|
||||
height: 100%;
|
||||
max-height: 300vh;
|
||||
|
||||
/*
|
||||
* Change the styles for tabs in all sidebars.
|
||||
*
|
||||
* The tabs occupy the entire width of the sidebar,
|
||||
* and each tab shares the space equally.
|
||||
* The clickable area of the tab is the entire
|
||||
* area it occupies, not just the label.
|
||||
*/
|
||||
.pgn__tabs {
|
||||
.nav-item {
|
||||
flex: 1 1 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pgn__tab_more {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
|
||||
@@ -120,12 +120,12 @@ describe('<LibraryHome />', () => {
|
||||
{
|
||||
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@library_content+block@test_lib_content',
|
||||
targetKey: null,
|
||||
unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it not supported in content libraries. It has 2 children blocks.',
|
||||
unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
|
||||
},
|
||||
{
|
||||
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@conditional+block@test_conditional',
|
||||
targetKey: null,
|
||||
unsupportedReason: 'The "conditional" XBlock (ID: "test_conditional") has children, so it not supported in content libraries. It has 2 children blocks.',
|
||||
unsupportedReason: 'The "conditional" XBlock (ID: "test_conditional") has children, so it is not supported in content libraries. It has 2 children blocks.',
|
||||
},
|
||||
]);
|
||||
(useGetContentHits as jest.Mock).mockReturnValue({
|
||||
|
||||
@@ -68,7 +68,7 @@ export const mockGetModulestoreMigratedBlocksInfo = {
|
||||
{
|
||||
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@library_content+block@test_lib_content',
|
||||
targetKey: null,
|
||||
unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it not supported in content libraries. It has 2 children blocks.',
|
||||
unsupportedReason: 'The "library_content" XBlock (ID: "test_lib_content") has children, so it is not supported in content libraries. It has 2 children blocks.',
|
||||
},
|
||||
{
|
||||
sourceKey: 'block-v1:UNIX+UX2+2025_T2+type@html+block@1',
|
||||
|
||||
@@ -159,7 +159,7 @@ describe('<ImportDetailsPage />', () => {
|
||||
name: 'library_content',
|
||||
})).toBeInTheDocument();
|
||||
expect(await screen.findByRole('cell', {
|
||||
name: /has children, so it not supported in content libraries/i,
|
||||
name: /has children, so it is not supported in content libraries/i,
|
||||
})).toBeInTheDocument();
|
||||
|
||||
const viewImportedContentBtn = screen.getByRole('button', {
|
||||
|
||||
@@ -163,7 +163,7 @@ export const ImportStepperPage = () => {
|
||||
</ActionRow>
|
||||
) : (
|
||||
<ActionRow className="d-flex justify-content-between">
|
||||
<Button onClick={() => setCurrentStep('select-course')} variant="tertiary">
|
||||
<Button variant="outline-primary" onClick={() => setCurrentStep('select-course')}>
|
||||
<FormattedMessage {...messages.importCourseBack} />
|
||||
</Button>
|
||||
{importIsBlocked ? (
|
||||
|
||||
Reference in New Issue
Block a user