Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions shell/header/anonymous-menu/LoginButton.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Button } from '@openedx/paragon';
import classNames from 'classnames';

import { getLinkProps, getUrlByRouteRole, useSiteConfig, useIntl } from '../../../runtime';
import { loginRole } from '../../constants';
import messages from '../../Shell.messages';

export default function LoginButton({ ...props }) {
export default function LoginButton({ className, ...props }: { className?: string } & Record<string, unknown>) {
const config = useSiteConfig();
const intl = useIntl();

Expand All @@ -12,7 +14,7 @@ export default function LoginButton({ ...props }) {
const url = getUrlByRouteRole(loginRole) ?? config.loginUrl;

return (
<Button variant="primary" {...getLinkProps(url)} {...props}>
<Button variant="primary" {...getLinkProps(url)} className={classNames('btn-login', className)} {...props}>
{intl.formatMessage(messages['header.user.menu.login'])}
</Button>
);
Expand Down
5 changes: 3 additions & 2 deletions shell/header/anonymous-menu/RegisterButton.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Button } from '@openedx/paragon';
import classNames from 'classnames';

import { getLinkProps, getUrlByRouteRole, useSiteConfig, useIntl } from '../../../runtime';
import { registerRole } from '../../constants';
import messages from '../../Shell.messages';

export default function RegisterButton({ ...props }) {
export default function RegisterButton({ className, ...props }: { className?: string } & Record<string, unknown>) {
const config = useSiteConfig();
const intl = useIntl();

Expand All @@ -13,7 +14,7 @@ export default function RegisterButton({ ...props }) {
const url = getUrlByRouteRole(registerRole) ?? `${config.lmsBaseUrl}/register`;

return (
<Button variant="outline-primary" {...getLinkProps(url)} {...props}>
<Button variant="primary" {...getLinkProps(url)} className={classNames('btn-register', className)} {...props}>
{intl.formatMessage(messages['header.user.menu.register'])}
</Button>
);
Expand Down
120 changes: 116 additions & 4 deletions shell/header/app.scss
Original file line number Diff line number Diff line change
@@ -1,14 +1,126 @@
// Header chrome for the Open edX shell, styled after the marketing site's navbar
// (lab/components/navbar.tsx) without pulling Tailwind into the theme.
$header-fg: #0a0a0a;
$header-muted: #737373;
$header-active: linear-gradient(to top, #8252fe, #e173ff);
$header-active-stacked: linear-gradient(to bottom, #8252fe, #e173ff);
$header-cta: linear-gradient(155deg, #d6e4ff -25%, #000 22%, #000 76%, #d4e4ff 128%);

header {
background: #fff;

.container-fluid {
min-height: 65px;
min-height: 4rem;
max-width: 80rem;
margin-inline: auto;
}

// Mobile pins the bar to the top; the desktop bar scrolls away with the page.
@media (max-width: 768px) {
position: sticky;
top: 0;
z-index: 300;
}

.nav-link {
padding: 1.125rem 1rem;
padding: .5rem .75rem;
border-radius: .375rem;
font-weight: 500;
color: $header-muted;
transition: color .2s ease-out, background-color .2s ease-out;

&:hover,
&:focus-visible {
color: $header-fg;
}

// Active is a short underline rather than Paragon's filled pill.
&.active {
background: var(--pgn-color-bg-active, #0A3055);
color: var(--pgn-color-active, #fff);
position: relative;
background: none;
color: $header-fg;

&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 1.5rem;
height: 2px;
border-radius: 50rem;
background: $header-active;
transform: translateX(-50%);
}
}
}

// Stacked links (mobile menu) take a leading bar instead, and the menu is a
// plain white sheet below the bar.
.flex-column {
background: #fff;
padding: .5rem .5rem .75rem;

.nav-link.active::after {
top: 50%;
bottom: auto;
left: .25rem;
width: 3px;
height: 1.5rem;
background: $header-active-stacked;
transform: translateY(-50%);
}
}

// Anonymous menu: Login is a quiet text link, Register the filled pill.
.btn-login {
border: 0;
padding: .5rem .75rem;
border-radius: .375rem;
background: transparent;
font-weight: 500;
color: $header-muted;

&:hover,
&:focus,
&:active {
background: transparent;
color: $header-fg;
}
}

.btn-register {
border: 0;
border-radius: 50rem;
padding: .75rem 1.25rem;
background: $header-cta;
box-shadow: 0 .25rem .5rem rgb(0 0 0 / 20%);
font-weight: 500;
color: #fff;

&:hover,
&:focus,
&:active {
background: $header-cta;
color: #fff;
}
}

// Mobile menu toggle: borderless square button on the trailing edge.
.btn-mobile-menu {
flex-shrink: 0;
width: 2.5rem;
height: 2.5rem;
padding: 0;
border: 0;
border-radius: .375rem;
background: transparent;
color: $header-muted;

&:hover,
&:focus,
&:active {
background: transparent;
color: $header-fg;
}
}

Expand Down
10 changes: 5 additions & 5 deletions shell/header/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,20 @@ const config: App = {
},
{
slotId: 'org.openedx.frontend.slot.header.anonymousMenu.v1',
id: 'org.openedx.frontend.widget.header.anonymousMenuRegister.v1',
id: 'org.openedx.frontend.widget.header.anonymousMenuLogin.v1',
op: WidgetOperationTypes.APPEND,
component: RegisterButton,
component: LoginButton,
},
{
slotId: 'org.openedx.frontend.slot.header.anonymousMenu.v1',
id: 'org.openedx.frontend.widget.header.anonymousMenuLogin.v1',
id: 'org.openedx.frontend.widget.header.anonymousMenuRegister.v1',
op: WidgetOperationTypes.APPEND,
component: LoginButton,
component: RegisterButton,
},

// Mobile
{
slotId: 'org.openedx.frontend.slot.header.mobileCenter.v1',
slotId: 'org.openedx.frontend.slot.header.mobileLeft.v1',
id: 'org.openedx.frontend.widget.header.mobileLogo.v1',
op: WidgetOperationTypes.APPEND,
element: <Logo />,
Expand Down
2 changes: 1 addition & 1 deletion shell/header/desktop/PrimaryNavLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Slot } from '../../../runtime';

export default function PrimaryNavLinks() {
return (
<Nav className="flex-nowrap align-items-center ml-3">
<Nav className="flex-nowrap align-items-center mx-auto">
<Slot id="org.openedx.frontend.slot.header.primaryLinks.v1" />
</Nav>
);
Expand Down
6 changes: 3 additions & 3 deletions shell/header/mobile/MobileLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ export default function MobileLayout() {
)}
>
<div className="d-flex flex-grow-1 flex-basis-0 justify-content-start align-items-center">
<Button onClick={handleMobileButtonClick} variant="outline">
<MenuIcon />
</Button>
<Slot id="org.openedx.frontend.slot.header.mobileLeft.v1" />
</div>
<div className="d-flex flex-grow-1 flex-basis-0 justify-content-center align-items-center">
<Slot id="org.openedx.frontend.slot.header.mobileCenter.v1" />
</div>
<div className="d-flex flex-grow-1 flex-basis-0 justify-content-end align-items-center">
<Slot id="org.openedx.frontend.slot.header.mobileRight.v1" />
<Button className="btn-mobile-menu" onClick={handleMobileButtonClick} variant="outline">
<MenuIcon />
</Button>
</div>
</Container>
{/* scrollLock would put data-scroll-locked on <body>, whose scrollbar compensation
Expand Down