diff --git a/src/Main.test.tsx b/src/Main.test.tsx index 0cf848f2..8e512dd6 100644 --- a/src/Main.test.tsx +++ b/src/Main.test.tsx @@ -23,9 +23,4 @@ describe('Main', () => { const { getByTestId } = renderWrapper(
); expect(getByTestId('authz-module')).toBeInTheDocument(); }); - - it('wraps the body in an xl container to align it with the header', () => { - const { getByTestId } = renderWrapper(
); - expect(getByTestId('authz-module').closest('.container-mw-xl')).toBeInTheDocument(); - }); }); diff --git a/src/Main.tsx b/src/Main.tsx index 44cdeff9..a668e205 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -1,5 +1,4 @@ import { CurrentAppProvider, PageWrap, getSiteConfig, useIntl } from '@openedx/frontend-base'; -import { Container } from '@openedx/paragon'; import { Helmet } from 'react-helmet'; import { appId } from './constants'; @@ -20,9 +19,7 @@ const Main = () => { - - - + ); diff --git a/src/authz-module/audit-user/index.tsx b/src/authz-module/audit-user/index.tsx index ce852441..7e35616f 100644 --- a/src/authz-module/audit-user/index.tsx +++ b/src/authz-module/audit-user/index.tsx @@ -3,9 +3,7 @@ import { useContext, useEffect, useMemo, useState, } from 'react'; import { SiteContext, useIntl } from '@openedx/frontend-base'; -import { - Container, DataTable, -} from '@openedx/paragon'; +import { DataTable } from '@openedx/paragon'; import TableFooter from '@src/authz-module/components/TableFooter/TableFooter'; import { AUTHZ_HOME_PATH, TABLE_DEFAULT_PAGE_SIZE, @@ -228,7 +226,7 @@ const AuditUserPage = () => { }; return ( -
+ <> { }} /> { ] } > - +
{ - - +
-
+ ); }; diff --git a/src/authz-module/authz-home/index.tsx b/src/authz-module/authz-home/index.tsx index 03fa3fc7..15250122 100644 --- a/src/authz-module/authz-home/index.tsx +++ b/src/authz-module/authz-home/index.tsx @@ -21,29 +21,25 @@ const AuthzHome = () => { const pageTitle = intl.formatMessage(messages['authz.manage.page.title']); return ( -
- ] - } + ] + } + > + - - - - - - - - - -
+ + + + + + + + ); }; diff --git a/src/authz-module/components/AuthZLayout.tsx b/src/authz-module/components/AuthZLayout.tsx index e657c493..4c714766 100644 --- a/src/authz-module/components/AuthZLayout.tsx +++ b/src/authz-module/components/AuthZLayout.tsx @@ -3,19 +3,21 @@ import AuthZTitle, { AuthZTitleProps } from './AuthZTitle'; interface AuthZLayoutProps extends AuthZTitleProps { children: ReactNode; - context: { - id: string; - org: string; - title: string; - }; } -const AuthZLayout = ({ children, ...props }: AuthZLayoutProps) => ( - <> - - {children} - - +/** + * Page chrome for the authz module: the title band, then the body below it. + * The body only paints its colour, edge to edge. Each page marks the parts of its + * content that should line up with the header using `page-band`, so anything meant + * to bleed across the full width -- a stepper header, a toolbar -- simply omits it. + */ +const AuthZLayout = ({ children, ...titleProps }: AuthZLayoutProps) => ( +
+ +
+ {children} +
+
); export default AuthZLayout; diff --git a/src/authz-module/components/AuthZTitle.test.tsx b/src/authz-module/components/AuthZTitle.test.tsx index 6b76f709..a9676830 100644 --- a/src/authz-module/components/AuthZTitle.test.tsx +++ b/src/authz-module/components/AuthZTitle.test.tsx @@ -12,14 +12,12 @@ describe('AuthZTitle', () => { const defaultProps = { activeLabel: 'Current Page', pageTitle: 'Page Title', - pageSubtitle: 'Page Subtitle', }; it('renders without optional fields', () => { render(); expect(screen.getByText(defaultProps.activeLabel)).toBeInTheDocument(); expect(screen.getByText(defaultProps.pageTitle)).toBeInTheDocument(); - expect(screen.getByText(defaultProps.pageSubtitle as string)).toBeInTheDocument(); }); it('renders breadcrumb with links and active label', () => { diff --git a/src/authz-module/components/AuthZTitle.tsx b/src/authz-module/components/AuthZTitle.tsx index 229c8cb6..e69fd876 100644 --- a/src/authz-module/components/AuthZTitle.tsx +++ b/src/authz-module/components/AuthZTitle.tsx @@ -3,7 +3,7 @@ import { } from 'react'; import { Link } from 'react-router-dom'; import { - Breadcrumb, Col, Container, Row, Button, + Breadcrumb, Col, Row, Button, Stack, useMediaQuery, breakpoints, @@ -23,7 +23,7 @@ interface Action { export interface AuthZTitleProps { activeLabel?: string; pageTitle: string; - pageSubtitle: string | ReactNode; + pageSubtitle?: string | ReactNode; navLinks?: BreadcrumbLink[]; actions?: (Action | ReactNode)[]; } @@ -42,7 +42,7 @@ const AuthZTitle = ({ }: AuthZTitleProps) => { const isDesktop = useMediaQuery({ minWidth: breakpoints.large.minWidth }); return ( - +

{pageTitle}

- {typeof pageSubtitle === 'string' - ? <> { pageSubtitle !== '' &&
}

{pageSubtitle}

- : <>{ pageSubtitle !== '' &&
}
{pageSubtitle}
} + {pageSubtitle && ( + <> +
+ {typeof pageSubtitle === 'string' + ?

{pageSubtitle}

+ :
{pageSubtitle}
} + + )}
@@ -72,7 +77,7 @@ const AuthZTitle = ({ {content} {(index === actions.length - 1) ? null - : (
)} + : (
)}
); }) @@ -80,7 +85,7 @@ const AuthZTitle = ({ - +
); }; diff --git a/src/authz-module/components/PermissionTable.tsx b/src/authz-module/components/PermissionTable.tsx index e2e7f619..4f1bb859 100644 --- a/src/authz-module/components/PermissionTable.tsx +++ b/src/authz-module/components/PermissionTable.tsx @@ -18,7 +18,10 @@ interface PermissionTableProps { const PermissionTable = ({ permissionsTable, roles, title }: PermissionTableProps) => { const { formatMessage } = useIntl(); return ( - + // Only the narrowest viewports are too small for the matrix, so the card scrolls there + // (see `.permission-table-scroll`). Above that it is not a scroll container, which is + // what lets the header row stick to the viewport as the page scrolls. + diff --git a/src/authz-module/index.scss b/src/authz-module/index.scss index 99586edd..856af828 100644 --- a/src/authz-module/index.scss +++ b/src/authz-module/index.scss @@ -24,16 +24,12 @@ min-height: 700px; } - hr { + .authz-action-divider { border-right: var(--pgn-size-border-width) solid var(--pgn-color-border); height: var(--height-action-divider); width: 0; } - .tab-content { - background-color: var(--pgn-color-light-200); - } - .collapsible-card { border: none; @@ -66,12 +62,23 @@ line-height: 24px; } } + + // Paragon's `.overflow-auto` lives in the `paragon` cascade layer, where its `!important` + // outranks anything this layer can say, so the card carries its own class instead. The + // matrix is 432px at min-content: only the narrowest screens need the card to scroll, and + // the cap is what gives the sticky header something to stick to while it is the scroller. + @media (--pgn-size-breakpoint-max-width-xs) { + .permission-table-scroll { + overflow: auto; + max-height: 80vh; + } + } @media(--pgn-size-breakpoint-max-width-sm){ .flex-column-sm { flex-direction: column; } - hr { + .authz-action-divider { border-top: var(--pgn-size-border-width) solid var(--pgn-color-border); border-right: none; width: 100%; @@ -126,6 +133,3 @@ max-height: 500px; } -.scope-search-input { - width: 18.75rem; // 300px -} diff --git a/src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx b/src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx index bcd1eecf..0b60a570 100644 --- a/src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx +++ b/src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx @@ -158,7 +158,7 @@ const AssignRoleWizard = ({ -
+
-
+