style: Fancier menus, more SIP-34-ish (#10423)

* style: shinier menus

* fixing mouseover glitch

* unused import

* rm emotion-reset

* restoring default config values

* lint fixes 

* a bit more pizzaz to the underlines (max's idea), fading active background

* simplifying navtitle -> label

* RBNavDropdown  -> ReactBootstrapNavDropdown

* nixing whitespace

* replacing !importants with better selector specificity

* moving Menu LESS into Emotion

* no more border!

* fixing border issue

* language picker, account dropdown now use new dropdown component

* nixing whitespace in comment

* nixing duplicate styling

* removing borders on FAB navbar

* explicit font coloring

* linting
This commit is contained in:
Evan Rusackas 2020-08-24 23:16:44 -07:00 committed by GitHub
parent fdfb7cdfd2
commit 4b40d44b5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 144 additions and 75 deletions

View File

@ -0,0 +1,21 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<svg width="6" height="4" viewBox="0 0 6 4" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.41421 0C0.523309 0 0.0771424 1.07714 0.707107 1.70711L2.29289 3.29289C2.68342 3.68342 3.31658 3.68342 3.70711 3.29289L5.29289 1.70711C5.92286 1.07714 5.47669 0 4.58579 0H1.41421Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -30,6 +30,7 @@ import { ReactComponent as CloseIcon } from 'images/icons/close.svg';
import { ReactComponent as CompassIcon } from 'images/icons/compass.svg'; import { ReactComponent as CompassIcon } from 'images/icons/compass.svg';
import { ReactComponent as DatasetPhysicalIcon } from 'images/icons/dataset_physical.svg'; import { ReactComponent as DatasetPhysicalIcon } from 'images/icons/dataset_physical.svg';
import { ReactComponent as DatasetVirtualIcon } from 'images/icons/dataset_virtual.svg'; import { ReactComponent as DatasetVirtualIcon } from 'images/icons/dataset_virtual.svg';
import { ReactComponent as DropdownArrowIcon } from 'images/icons/dropdown-arrow.svg';
import { ReactComponent as ErrorIcon } from 'images/icons/error.svg'; import { ReactComponent as ErrorIcon } from 'images/icons/error.svg';
import { ReactComponent as FavoriteSelectedIcon } from 'images/icons/favorite-selected.svg'; import { ReactComponent as FavoriteSelectedIcon } from 'images/icons/favorite-selected.svg';
import { ReactComponent as FavoriteUnselectedIcon } from 'images/icons/favorite-unselected.svg'; import { ReactComponent as FavoriteUnselectedIcon } from 'images/icons/favorite-unselected.svg';
@ -58,6 +59,7 @@ type IconName =
| 'compass' | 'compass'
| 'dataset-physical' | 'dataset-physical'
| 'dataset-virtual' | 'dataset-virtual'
| 'dropdown-arrow'
| 'error' | 'error'
| 'favorite-selected' | 'favorite-selected'
| 'favorite-unselected' | 'favorite-unselected'
@ -88,6 +90,7 @@ export const iconsRegistry: Record<
'favorite-selected': FavoriteSelectedIcon, 'favorite-selected': FavoriteSelectedIcon,
'favorite-unselected': FavoriteUnselectedIcon, 'favorite-unselected': FavoriteUnselectedIcon,
'list-view': ListViewIcon, 'list-view': ListViewIcon,
'dropdown-arrow': DropdownArrowIcon,
'sort-asc': SortAscIcon, 'sort-asc': SortAscIcon,
'sort-desc': SortDescIcon, 'sort-desc': SortDescIcon,
certified: CertifiedIcon, certified: CertifiedIcon,

View File

@ -17,7 +17,8 @@
* under the License. * under the License.
*/ */
import React from 'react'; import React from 'react';
import { NavDropdown, MenuItem } from 'react-bootstrap'; import { MenuItem } from 'react-bootstrap';
import NavDropdown from 'src/components/NavDropdown';
export interface Languages { export interface Languages {
[key: string]: { [key: string]: {

View File

@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@import '../../../stylesheets/less/variables.less';
#main-menu {
.navbar .caret {
width: 1rem;
padding: 0 0 18px 0;
&:before {
position: relative;
top: -2px;
}
}
.navbar-inverse {
border-bottom: 2px solid @gray-bg;
}
.version-info {
padding: 5px 20px;
color: @gray-heading;
font-size: @font-size-xs;
div {
white-space: nowrap;
}
}
}

View File

@ -24,7 +24,6 @@ import MenuObject, { MenuObjectProps } from './MenuObject';
import NewMenu from './NewMenu'; import NewMenu from './NewMenu';
import UserMenu from './UserMenu'; import UserMenu from './UserMenu';
import LanguagePicker, { Languages } from './LanguagePicker'; import LanguagePicker, { Languages } from './LanguagePicker';
import './Menu.less';
interface BrandProps { interface BrandProps {
path: string; path: string;
@ -56,32 +55,65 @@ export interface MenuProps {
} }
const StyledHeader = styled.header` const StyledHeader = styled.header`
.caret {
display: none;
}
.navbar-inverse {
border: none;
}
.version-info {
padding: 5px 20px;
color: ${({ theme }) => theme.colors.grayscale.base};
font-size: ${({ theme }) => theme.typography.sizes.xs}px;
div {
white-space: nowrap;
}
}
.navbar-brand { .navbar-brand {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
} }
.nav > li > a {
padding: ${({ theme }) => theme.gridUnit * 4}px;
}
.navbar-nav > li > a { .navbar-nav > li > a {
color: ${({ theme }) => theme.colors.grayscale.dark1};
border-bottom: none;
&:focus {
border-bottom: none;
}
&:after { &:after {
content: ''; content: '';
position: absolute; position: absolute;
bottom: -3px; bottom: -3px;
left: 0; left: 50%;
width: 100%; width: 0;
height: 3px; height: 3px;
background-color: ${({ theme }) => theme.colors.primary.base}; background-color: ${({ theme }) => theme.colors.primary.base};
opacity: 0; opacity: 0;
transition: opacity ${({ theme }) => theme.transitionTiming * 2}s; transform: translateX(-50%);
transition: all ${({ theme }) => theme.transitionTiming}s;
} }
&:hover { &:hover {
color: ${({ theme }) => theme.colors.grayscale.dark1};
border-bottom: none; border-bottom: none;
&:after { &:after {
opacity: 1; opacity: 1;
width: 100%;
} }
} }
&:hover,
&:focus {
margin: 0;
}
} }
`; `;

View File

@ -17,7 +17,8 @@
* under the License. * under the License.
*/ */
import React from 'react'; import React from 'react';
import { NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; import { NavItem, MenuItem } from 'react-bootstrap';
import NavDropdown from '../NavDropdown';
interface MenuObjectChildProps { interface MenuObjectChildProps {
label: string; label: string;
@ -44,23 +45,13 @@ export default function MenuObject({
if (url) { if (url) {
return ( return (
<NavItem eventKey={index} href={url}> <NavItem eventKey={index} href={url}>
<i className={`fa ${icon}`} /> &nbsp; {label} {label}
</NavItem> </NavItem>
); );
} }
const navTitle = (
<>
<i className={`fa ${icon}`} />
&nbsp; {label}
</>
);
return ( return (
<NavDropdown <NavDropdown id={`menu-dropdown-${label}`} eventKey={index} title={label}>
id={`menu-dropdown-${label}`}
eventKey={index}
title={navTitle}
>
{childs?.map((child: MenuObjectChildProps | string, index1: number) => { {childs?.map((child: MenuObjectChildProps | string, index1: number) => {
if (typeof child === 'string' && child === '-') { if (typeof child === 'string' && child === '-') {
return <MenuItem key={`$${index1}`} divider />; return <MenuItem key={`$${index1}`} divider />;
@ -71,7 +62,6 @@ export default function MenuObject({
href={child.url} href={child.url}
eventKey={parseFloat(`${index}.${index1}`)} eventKey={parseFloat(`${index}.${index1}`)}
> >
<i className={`fa ${child.icon}`} />
&nbsp; {child.label} &nbsp; {child.label}
</MenuItem> </MenuItem>
); );

View File

@ -17,7 +17,8 @@
* under the License. * under the License.
*/ */
import React from 'react'; import React from 'react';
import { NavDropdown, MenuItem } from 'react-bootstrap'; import { MenuItem } from 'react-bootstrap';
import NavDropdown from 'src/components/NavDropdown';
import { t } from '@superset-ui/translation'; import { t } from '@superset-ui/translation';
interface UserMenuProps { interface UserMenuProps {
@ -42,14 +43,8 @@ export default function UserMenu({
</> </>
} }
> >
<MenuItem href={userInfoUrl}> <MenuItem href={userInfoUrl}>{t('Profile')}</MenuItem>
<span className="fa fa-fw fa-user" /> <MenuItem href={userLogoutUrl}>{t('Logout')}</MenuItem>
{t('Profile')}
</MenuItem>
<MenuItem href={userLogoutUrl}>
<span className="fa fa-fw fa-sign-out" />
{t('Logout')}
</MenuItem>
{(versionString || versionSha) && ( {(versionString || versionSha) && (
<li className="version-info"> <li className="version-info">
{versionString && <div>Version: {versionString}</div>} {versionString && <div>Version: {versionString}</div>}

View File

@ -0,0 +1,72 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import styled from '@superset-ui/style';
import { NavDropdown as ReactBootstrapNavDropdown } from 'react-bootstrap';
const NavDropdown = styled(ReactBootstrapNavDropdown)`
&.dropdown > a.dropdown-toggle {
padding-right: ${({ theme }) => theme.gridUnit * 6}px;
}
& > a {
transition: background-color ${({ theme }) => theme.transitionTiming}s;
}
&.dropdown.open > a.dropdown-toggle {
background: ${({ theme }) => theme.colors.primary.light4};
}
:after {
content: '';
height: ${({ theme }) => theme.gridUnit}px;
width: ${({ theme }) => theme.gridUnit * 2}px;
background: url('/static/assets/images/icons/dropdown-arrow.svg');
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: ${({ theme }) => theme.gridUnit * 2}px;
transition: opacity ${({ theme }) => theme.transitionTiming}s;
opacity: ${({ theme }) => theme.opacity.mediumLight};
pointer-events: none;
}
&:hover,
&.active {
&:after {
opacity: ${({ theme }) => theme.opacity.mediumHeavy};
}
}
.dropdown-menu {
padding: ${({ theme }) => theme.gridUnit}px 0;
top: 100%;
border: none;
& li a {
padding: ${({ theme }) => theme.gridUnit}px
${({ theme }) => theme.gridUnit * 4}px;
transition: all ${({ theme }) => theme.transitionTiming}s;
&:hover {
background: ${({ theme }) => theme.colors.primary.light4};
color: ${({ theme }) => theme.colors.grayscale.dark1};
}
}
}
`;
export default NavDropdown;

View File

@ -43,7 +43,7 @@
} }
.navbar-inverse { .navbar-inverse {
border: 3px solid @navbar-inverse-bg; border: none;
} }
.navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:hover,