Skip to content

Commit

Permalink
STRIPES-641: MainNav updates (#698)
Browse files Browse the repository at this point in the history
* Updated MainNav and NavButton styles

* Added 'innerClassName'-prop for <NavButton>. Updated <CurrentApp> label font-size.

* Added localized aria-label for 'My profile' dropdown toggle button.

* Various style updates and moved some CSS values into variables.

* Made some style adjustments for CurrentApp, MainNav and ProfileDown – including responsive updates.

* ProfileDropdown Avatar style update

* Updated border on AppIcon's that's used within a <NavButton>. Updated height of skeleton loading header.

* Fixed linting errors/warnings. Added the dist-folder to eslintignore because it can cause the eslint command to stall and never finish.

* Updated avatar class name to be more specific to ensure that it overwrites the default styling.

* Minor CurrentApp button tweak

* Updated font-weight for NavButton

* Updated list item in app list dropdown to use the --text-weight-bold CSS variable instead of a hardcoded font-weight value

* MainNav, CurrentApp and NavButton updates based on Filip's feedback.

* Fixed linting error

* Additional style tweaks for CurrentApp, MainNav and NavButton

* Minor

* Current app label margin tweak

* Force CurrentApp <NavButton> to always be opacity: 1;

* Updated system skeleton

* Fixed linting warning

* Updated changelog
  • Loading branch information
rasmuswoelk committed Aug 12, 2019
1 parent 6cf0ae7 commit f004e89
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 51 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1 +1,2 @@
examples/trivial/node_modules/*
dist/*
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
## 3.8.0 (IN PROGRESS)

* Receive React as a peerDependency (provide by `stripes`). One dep to rule them all. Refs UIIN-678.
* Updated MainNav design to improve color contrast (STCOR-378)
* Include React a devDependency since it no longer a direct dependency. Refs UIIN-678.

## [3.7.0](https://github.com/folio-org/stripes-core/tree/v3.7.0) (2019-07-22)
Expand Down
10 changes: 9 additions & 1 deletion src/components/MainNav/AppList/AppList.css
Expand Up @@ -71,7 +71,7 @@
.dropdownListItemLabel {
padding: 0 4px;
min-width: 200px;
font-weight: 600;
font-weight: var(--text-weight-bold);
}

[dir="rtl"] .dropdownListItemLabel {
Expand All @@ -94,6 +94,14 @@
display: none;
}

[dir=ltr] .navItem:not(:last-child) {
margin-right: var(--gutter-static-two-thirds);
}

[dir=rtl] .navItem:not(:last-child) {
margin-left: var(--gutter-static-two-thirds);
}

/**
* Responsive
*/
Expand Down
2 changes: 1 addition & 1 deletion src/components/MainNav/AppList/AppList.js
Expand Up @@ -84,7 +84,7 @@ class AppList extends Component {
label={app.displayName}
id={app.id}
selected={app.active}
href={app.active ? null : app.href}
href={app.href}
aria-label={app.displayName}
iconKey={app.name}
iconData={app.iconData}
Expand Down
26 changes: 26 additions & 0 deletions src/components/MainNav/CurrentApp/CurrentApp.css
@@ -0,0 +1,26 @@
/**
* CurrentApp
*/

@import "@folio/stripes-components/lib/variables.css";

.button {
opacity: 1 !important;
padding: 0 var(--gutter-static-two-thirds);
}

.button .button__inner {
padding: 0;
}

[dir="ltr"] .button .button__label {
margin-left: 0.6rem;
}

[dir="rtl"] .button .button__label {
margin-right: 0.6rem;
}

.button .button__label__inner {
font-size: 1.86rem;
}
15 changes: 14 additions & 1 deletion src/components/MainNav/CurrentApp/CurrentApp.js
Expand Up @@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
import { injectIntl, intlShape } from 'react-intl';
import Headline from '@folio/stripes-components/lib/Headline';
import NavButton from '../NavButton';
import css from './CurrentApp.css';

const propTypes = {
currentApp: PropTypes.shape(
Expand Down Expand Up @@ -37,11 +38,23 @@ const CurrentApp = ({ currentApp, id, intl, badge }) => {

return (
<NavButton
label={<Headline tag="h1" size="small" margin="none">{displayName}</Headline>}
label={
<Headline
tag="h1"
margin="none"
weight="black"
className={css.button__label__inner}
>
{displayName}
</Headline>
}
id={id}
ariaLabel={ariaLabel}
badge={badge}
iconKey={name}
className={css.button}
innerClassName={css.button__inner}
labelClassName={css.button__label}
href={href}
iconData={iconData}
/>
Expand Down
21 changes: 18 additions & 3 deletions src/components/MainNav/MainNav.css
@@ -1,14 +1,25 @@
@import '@folio/stripes-components/lib/variables.css';

:root {
--main-nav-min-height-desktop: 56px;
--main-nav-min-height-mobile: 48px;
--main-nav-border-bottom-color: rgba(0, 0, 0, 0.9);
--main-nav-background-color: rgba(0, 0, 0, 0.8);
--main-nav-text-color: #fff;
}

.navRoot {
background-color: var(--main-nav-background-color);
border-bottom: 1px solid var(--main-nav-border-bottom-color);
color: var(--main-nav-text-color);
display: flex;
justify-content: space-between;
align-content: stretch;
align-items: center;
width: 100%;
border-bottom: 1px solid var(--color-border);
background-color: #f7f7f7;
flex: 0 0 auto;
padding: 0 6px;
padding: 0 var(--gutter-static-one-third);
min-height: var(--main-nav-min-height-desktop);
z-index: 99999;
position: relative;
}
Expand All @@ -34,4 +45,8 @@
.brandingLabel {
display: none;
}

.navRoot {
min-height: var(--main-nav-min-height-mobile);
}
}
74 changes: 45 additions & 29 deletions src/components/MainNav/NavButton/NavButton.css
@@ -1,54 +1,54 @@
@import '@folio/stripes-components/lib/variables.css';

:root {
--main-nav-button-font-size: 1rem;
--main-nav-button-label-spacing: 6px;
--main-nav-button-padding: 0.53rem;
--main-nav-button-min-height: var(--control-min-size-touch);
--main-nav-button-color: #fff;
}

.navButton {
composes: interactionStylesControl from "@folio/stripes-components/lib/sharedStyles/interactionStyles.css"; /* stylelint-disable-line */
padding: 0 5px;
height: 44px;
padding: 0 var(--gutter-static-one-third);
min-height: var(--main-nav-button-min-height);
font-size: var(--main-nav-button-font-size);
outline: 0;
color: var(--color-text);
font-size: var(--font-size-small);
opacity: 0.75;

&::-moz-focus-inner {
border: 0;
}

/* Is selected */
&:hover,
&:focus {
opacity: 1;
}

&.selected {
&::before {
content: '';
position: absolute;
top: 0;
right: 5px;
left: 5px;
height: 4px;
opacity: 1;

& .inner::before {
background-color: var(--primary);
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}

.navButton:not(:active).selected .icon svg {
fill: var(--primary);
.isInteractable {
composes: interactionStyles from "@folio/stripes-components/lib/sharedStyles/interactionStyles.css"; /* stylelint-disable-line */
}

/* To make sure we overwrite default link colors */
a.navButton,
button.navButton {
color: var(--color-text);
}

/* No active bar - primarily used for popover icons with no label */
.navButton.noSelectedBar::before {
display: none;
color: var(--main-nav-button-color);
}

.icon {
margin: 0 4px;
display: flex;

& svg {
fill: var(--color-icon);
fill: currentColor;
}
}

Expand All @@ -66,19 +66,27 @@ button.navButton {
}

.label {
margin: 0 4px;
font-weight: 600;
font-weight: var(--text-weight-bold);
display: flex;
align-items: center;
}

[dir="ltr"] .label {
margin-left: var(--main-nav-button-label-spacing);
}

[dir="rtl"] .label {
margin-right: var(--main-nav-button-label-spacing);
}

.inner {
padding: 4px 0;
position: relative;
padding: var(--main-nav-button-padding) 0;
}

.isInteractable {
composes: interactionStyles from "@folio/stripes-components/lib/sharedStyles/interactionStyles.css"; /* stylelint-disable-line */
.navButton .inner::before {
left: calc(var(--main-nav-button-padding) * -1);
right: calc(var(--main-nav-button-padding) * -1);
}

/**
Expand All @@ -91,3 +99,11 @@ button.navButton {
right: -1px;
z-index: 5;
}

/**
* AppIcon
*/

.appIcon > span::after {
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
36 changes: 33 additions & 3 deletions src/components/MainNav/NavButton/NavButton.js
Expand Up @@ -20,6 +20,7 @@ const propTypes = {
icon: PropTypes.oneOfType([
PropTypes.element,
]),
innerClassName: PropTypes.string,
labelClassName: PropTypes.string,
badge: PropTypes.oneOfType([
PropTypes.string,
Expand All @@ -34,7 +35,24 @@ const defaultProps = {
noSelectedBar: false,
};

const NavButton = React.forwardRef(({ ariaLabel, label, title, selected, onClick, href, icon, noSelectedBar, className, labelClassName, badge, id, iconKey, iconData, ...rest }, ref) => {
const NavButton = React.forwardRef(({
ariaLabel,
label,
title,
selected,
onClick,
href,
icon,
innerClassName,
noSelectedBar,
className,
labelClassName,
badge,
id,
iconKey,
iconData,
...rest
}, ref) => {
/**
* Root classes
*/
Expand All @@ -48,7 +66,19 @@ const NavButton = React.forwardRef(({ ariaLabel, label, title, selected, onClick
/**
* Icon
*/
const renderedIcon = (<span className={css.icon}>{icon || <AppIcon alt="" app={iconKey} icon={iconData} focusable={false} />}</span>);
const renderedIcon = (
<span className={css.icon}>
{icon || (
<AppIcon
alt=""
app={iconKey}
icon={iconData}
focusable={false}
className={css.appIcon}
/>
)}
</span>
);

let Element = 'span';
let clickableProps = {};
Expand All @@ -75,7 +105,7 @@ const NavButton = React.forwardRef(({ ariaLabel, label, title, selected, onClick

return (
<Element ref={ref} id={id} aria-label={ariaLabel || title} className={rootClasses} {...rest} {...clickableProps}>
<span className={classNames(css.inner, { [css.isInteractable]: href || onClick })}>
<span className={classNames(css.inner, { [css.isInteractable]: href || onClick }, innerClassName)}>
{ badge && (<Badge color="red" className={css.badge}>{badge}</Badge>) }
{ renderedIcon }
{ label && <span className={classNames(css.label, labelClassName)}>{label}</span>}
Expand Down
2 changes: 1 addition & 1 deletion src/components/MainNav/NavDivider/NavDivider.css
@@ -1,7 +1,7 @@
@import '@folio/stripes-components/lib/variables.css';

.navDivider {
border-left: 1px solid var(--color-border-p2);
border-left: 1px solid rgba(255, 255, 255, 0.2);
height: 24px;
margin: 0 5px;
}
Expand Down
5 changes: 3 additions & 2 deletions src/components/MainNav/ProfileDropdown/ProfileDropdown.css
Expand Up @@ -16,7 +16,8 @@
}

/* Avatar */
.avatar {
.button .avatar {
border: 0;
box-shadow: inset 0 0 0 1px var(--color-border);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
background-color: rgba(255, 255, 255, 0.4);
}
28 changes: 19 additions & 9 deletions src/components/MainNav/ProfileDropdown/ProfileDropdown.js
Expand Up @@ -220,15 +220,25 @@ class ProfileDropdown extends Component {
const { dropdownOpen, HandlerComponent } = this.state;

return (
<Fragment>
{ HandlerComponent && <HandlerComponent stripes={this.props.stripes} /> }
<Dropdown open={dropdownOpen} id="profileDropdown" onToggle={this.toggleDropdown} pullRight hasPadding>
<NavButton data-role="toggle" ariaLabel="My Profile" selected={dropdownOpen} icon={this.getProfileImage()} noSelectedBar />
<NavDropdownMenu data-role="menu" onToggle={this.toggleDropdown}>
{this.getDropdownContent()}
</NavDropdownMenu>
</Dropdown>
</Fragment>
<IntlConsumer>
{intl => (
<Fragment>
{ HandlerComponent && <HandlerComponent stripes={this.props.stripes} /> }
<Dropdown open={dropdownOpen} id="profileDropdown" onToggle={this.toggleDropdown} pullRight hasPadding>
<NavButton
data-role="toggle"
ariaLabel={intl.formatMessage({ id: 'stripes-core.mainnav.myProfileAriaLabel' })}
selected={dropdownOpen}
className={css.button}
icon={this.getProfileImage()}
/>
<NavDropdownMenu data-role="menu" onToggle={this.toggleDropdown}>
{this.getDropdownContent()}
</NavDropdownMenu>
</Dropdown>
</Fragment>
)}
</IntlConsumer>
);
}
}
Expand Down

0 comments on commit f004e89

Please sign in to comment.