fix: studio dropdown hover styles (#433)

This commit is contained in:
Kristin Aoki
2023-11-16 11:18:00 -05:00
committed by GitHub
parent 665653e9a5
commit bace8286fd
10 changed files with 114 additions and 195 deletions

View File

@@ -7,6 +7,7 @@ import { AppContext, AppProvider } from '@edx/frontend-platform/react';
import Header from '@edx/frontend-component-header'; import Header from '@edx/frontend-component-header';
import './index.scss'; import './index.scss';
import StudioHeader from '../src/studio-header/StudioHeader';
subscribe(APP_READY, () => { subscribe(APP_READY, () => {
ReactDOM.render( ReactDOM.render(
@@ -32,7 +33,35 @@ subscribe(APP_READY, () => {
}}> }}>
<Header /> <Header />
</AppContext.Provider> </AppContext.Provider>
<h5 className="mt-2">Logged in state</h5> <h5 className="mt-2 mb-5">Logged in state</h5>
<AppContext.Provider value={{
authenticatedUser: {
userId: '123abc',
username: 'testuser',
roles: [],
administrator: false,
},
config: getConfig(),
}}>
<StudioHeader
number="run123"
org="testX"
title="Course Name"
isHiddenMainMenu={false}
mainMenuDropdowns={[
{
id: 'content-dropdown',
buttonTitle: 'Content',
items: [{
href: '#',
title: 'Outline',
}],
},
]}
outlineLink="#"
/>
</AppContext.Provider>
<h5 className="mt-2">Logged in state for Studio header</h5>
</AppProvider>, </AppProvider>,
document.getElementById('root'), document.getElementById('root'),
); );

View File

@@ -3,7 +3,7 @@ $blue: #007db8;
$white: #fff; $white: #fff;
@import './Menu/menu.scss'; @import './Menu/menu.scss';
@import './studio-header/header.scss'; @import './studio-header/StudioHeader.scss';
.dropdown-item a { .dropdown-item a {
text-decoration: none; text-decoration: none;
@@ -43,9 +43,9 @@ $white: #fff;
.user-dropdown { .user-dropdown {
.btn { .btn {
height: 3rem; height: 3rem;
@media (max-width: -1 + map-get($grid-breakpoints, "sm")) { // @media (max-width: -1 + map-get($grid-breakpoints, "sm")) {
padding: 0 0.5rem; // padding: 0 0.5rem;
} // }
} }
} }
} }

View File

@@ -24,7 +24,7 @@ const CourseLockUp = ({
)} )}
> >
<a <a
className="course-title-lockup w-25 mr-2" className="course-title-lockup mr-2"
href={outlineLink} href={outlineLink}
aria-label={intl.formatMessage(messages['header.label.courseOutline'])} aria-label={intl.formatMessage(messages['header.label.courseOutline'])}
data-testid="course-lock-up-block" data-testid="course-lock-up-block"

View File

@@ -44,7 +44,7 @@ const HeaderBody = ({
); );
return ( return (
<Container size="xl" className="px-4"> <Container size="xl" className="px-2.5">
<ActionRow as="header"> <ActionRow as="header">
{isHiddenMainMenu ? ( {isHiddenMainMenu ? (
<Row className="flex-nowrap ml-4"> <Row className="flex-nowrap ml-4">
@@ -64,17 +64,19 @@ const HeaderBody = ({
Menu Menu
</Button> </Button>
) : ( ) : (
<Row className="flex-nowrap m-0"> <div className="w-25">
{renderBrandNav} <Row className="m-0 flex-nowrap">
<CourseLockUp {renderBrandNav}
{...{ <CourseLockUp
outlineLink, {...{
number, outlineLink,
org, number,
title, org,
}} title,
/> }}
</Row> />
</Row>
</div>
)} )}
{isMobile ? ( {isMobile ? (
<> <>
@@ -82,11 +84,11 @@ const HeaderBody = ({
{renderBrandNav} {renderBrandNav}
</> </>
) : ( ) : (
<Nav data-testid="desktop-menu" className="ml-4"> <Nav data-testid="desktop-menu" className="ml-2">
{mainMenuDropdowns.map(dropdown => { {mainMenuDropdowns.map(dropdown => {
const { id, buttonTitle, items } = dropdown; const { id, buttonTitle, items } = dropdown;
return ( return (
<NavDropdownMenu {...{ id, buttonTitle, items }} /> <NavDropdownMenu key={id} {...{ id, buttonTitle, items }} />
); );
})} })}
</Nav> </Nav>
@@ -113,9 +115,9 @@ const HeaderBody = ({
HeaderBody.propTypes = { HeaderBody.propTypes = {
studioBaseUrl: PropTypes.string.isRequired, studioBaseUrl: PropTypes.string.isRequired,
logoutUrl: PropTypes.string.isRequired, logoutUrl: PropTypes.string.isRequired,
setModalPopupTarget: PropTypes.func.isRequired, setModalPopupTarget: PropTypes.func,
toggleModalPopup: PropTypes.func.isRequired, toggleModalPopup: PropTypes.func,
isModalPopupOpen: PropTypes.bool.isRequired, isModalPopupOpen: PropTypes.bool,
number: PropTypes.string, number: PropTypes.string,
org: PropTypes.string, org: PropTypes.string,
title: PropTypes.string, title: PropTypes.string,
@@ -138,6 +140,9 @@ HeaderBody.propTypes = {
}; };
HeaderBody.defaultProps = { HeaderBody.defaultProps = {
setModalPopupTarget: null,
toggleModalPopup: null,
isModalPopupOpen: false,
logo: null, logo: null,
logoAltText: null, logoAltText: null,
number: '', number: '',

View File

@@ -38,9 +38,6 @@ const MobileHeader = ({
MobileHeader.propTypes = { MobileHeader.propTypes = {
studioBaseUrl: PropTypes.string.isRequired, studioBaseUrl: PropTypes.string.isRequired,
logoutUrl: PropTypes.string.isRequired, logoutUrl: PropTypes.string.isRequired,
setModalPopupTarget: PropTypes.func.isRequired,
toggleModalPopup: PropTypes.func.isRequired,
isModalPopupOpen: PropTypes.bool.isRequired,
number: PropTypes.string, number: PropTypes.string,
org: PropTypes.string, org: PropTypes.string,
title: PropTypes.string, title: PropTypes.string,

View File

@@ -13,10 +13,12 @@ const NavDropdownMenu = ({
<DropdownButton <DropdownButton
id={id} id={id}
title={buttonTitle} title={buttonTitle}
variant="tertiary" variant="outline-primary"
className="mr-2"
> >
{items.map(item => ( {items.map(item => (
<Dropdown.Item <Dropdown.Item
key={`${item.title}-dropdown-item`}
href={item.href} href={item.href}
className="small" className="small"
> >

View File

@@ -36,14 +36,15 @@ const StudioHeader = ({
}; };
return ( return (
<> <div className="studio-header">
<Responsive maxWidth={768}> <a className="nav-skip sr-only sr-only-focusable" href="#main">Skip to content</a>
<Responsive maxWidth={841}>
<MobileHeader {...props} /> <MobileHeader {...props} />
</Responsive> </Responsive>
<Responsive minWidth={769}> <Responsive minWidth={842}>
<HeaderBody {...props} /> <HeaderBody {...props} />
</Responsive> </Responsive>
</> </div>
); );
}; };

View File

@@ -0,0 +1,49 @@
$spacer: 1rem;
$white: #FFFFFF;
.studio-header {
position: relative;
z-index: 1000;
height: 3.75rem;
box-shadow: 0 1px 0 0 rgb(0 0 0 / .1);
background: $white;
.btn-outline-primary {
border-color: $white;
}
.logo {
display: block;
box-sizing: content-box;
position: relative;
top: -.05em;
height: 1.75rem;
padding: $spacer 0;
margin-right: $spacer;
img {
display: block;
height: 100%;
}
}
.course-title-lockup {
@media only screen and (min-width: 769px) {
padding: .5rem;
padding-right: $spacer;
border-right: 1px solid #E5E5E5;
width: 70%;
}
overflow: hidden;
span {
color: #333333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.375rem;
}
}
}

View File

@@ -1,64 +0,0 @@
// This SCSS was partly copied from edx/frontend-app-support-tools/src/support-header/index.scss.
$spacer: 1rem;
$white: #FFFFFF;
.btn-tertiary:hover {
color: white;
background-color: #00262B;
}
.course-title-lockup {
@media only screen and (max-width: 768px) {
padding-left: .5rem;
max-width: 70%;
}
@media only screen and (min-width: 769px) {
padding: .5rem;
padding-right: $spacer;
border-right: 1px solid #E5E5E5;
min-width: 70%;
}
overflow: hidden;
span {
color: #333333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.375rem;
}
}
.site-header-mobile,
.site-header-desktop {
position: relative;
z-index: 1000;
}
.site-header-mobile {img {
height: 1.5rem;
}
}
.site-header-desktop {
height: 3.75rem;
box-shadow: 0 1px 0 0 rgb(0 0 0 / .1);
background: $white;
.logo {
display: block;
box-sizing: content-box;
position: relative;
top: -.05em;
height: 1.75rem;
padding: $spacer 0;
margin-right: $spacer;
img {
display: block;
height: 100%;
}
}
}

View File

@@ -1,106 +1,6 @@
import { defineMessages } from '@edx/frontend-platform/i18n'; import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({ const messages = defineMessages({
'header.links.content': {
id: 'header.links.content',
defaultMessage: 'Content',
description: 'Label for Content menu trigger',
},
'header.links.settings': {
id: 'header.links.settings',
defaultMessage: 'Settings',
description: 'Label for Settings menu trigger',
},
'header.links.tools': {
id: 'header.links.content.tools',
defaultMessage: 'Tools',
description: 'Label for Tools menu trigger',
},
'header.links.outline': {
id: 'header.links.outline',
defaultMessage: 'Outline',
description: 'Link to Studio Outline page',
},
'header.links.updates': {
id: 'header.links.updates',
defaultMessage: 'Updates',
description: 'Link to Studio Updates page',
},
'header.links.pages': {
id: 'header.links.pages',
defaultMessage: 'Pages & Resources',
description: 'Link to Studio Pages page',
},
'header.links.filesAndUploads': {
id: 'header.links.filesAndUploads',
defaultMessage: 'Files & Uploads',
description: 'Link to Studio Files & Uploads page',
},
'header.links.textbooks': {
id: 'header.links.textbooks',
defaultMessage: 'Textbooks',
description: 'Link to Studio Textbooks page',
},
'header.links.videoUploads': {
id: 'header.links.videoUploads',
defaultMessage: 'Video Uploads',
description: 'Link to Studio Video Uploads page',
},
'header.links.scheduleAndDetails': {
id: 'header.links.scheduleAndDetails',
defaultMessage: 'Schedule & Details',
description: 'Link to Studio Schedule & Details page',
},
'header.links.grading': {
id: 'header.links.grading',
defaultMessage: 'Grading',
description: 'Link to Studio Grading page',
},
'header.links.courseTeam': {
id: 'header.links.courseTeam',
defaultMessage: 'Course Team',
description: 'Link to Studio Course Team page',
},
'header.links.groupConfigurations': {
id: 'header.links.groupConfigurations',
defaultMessage: 'Group Configurations',
description: 'Link to Studio Group Configurations page',
},
'header.links.proctoredExamSettings': {
id: 'header.links.proctoredExamSettings',
defaultMessage: 'Proctored Exam Settings',
description: 'Link to Studio Proctored Exam Settings page',
},
'header.links.advancedSettings': {
id: 'header.links.advancedSettings',
defaultMessage: 'Advanced Settings',
description: 'Link to Studio Advanced Settings page',
},
'header.links.certificates': {
id: 'header.links.certificates',
defaultMessage: 'Certificates',
description: 'Link to Studio Certificates page',
},
'header.links.publisher': {
id: 'header.links.publisher',
defaultMessage: 'Publisher',
description: 'Link to Publisher',
},
'header.links.import': {
id: 'header.links.import',
defaultMessage: 'Import',
description: 'Link to Studio Import page',
},
'header.links.export': {
id: 'header.links.export',
defaultMessage: 'Export',
description: 'Link to Studio Export page',
},
'header.links.checklists': {
id: 'header.links.checklists',
defaultMessage: 'Checklists',
description: 'Link to Studio Checklists page',
},
'header.user.menu.studio': { 'header.user.menu.studio': {
id: 'header.user.menu.studio', id: 'header.user.menu.studio',
defaultMessage: 'Studio Home', defaultMessage: 'Studio Home',