fix(sidebar): fix various styling

Signed-off-by: Phil Kuang <pkuang@factset.com>
This commit is contained in:
Phil Kuang
2022-05-05 20:56:08 -04:00
parent 8386a32644
commit 2025d7c123
6 changed files with 93 additions and 61 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Properly highlight `SidebarSubmenuItem` dropdown items on hover, use ellipsis styling on long labels in `SidebarSubmenu`, allow `icon` and `to` properties to be optional on `SidebarSubmenuItem`, and fix `SidebarPage` padding to be responsive to pinned state
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-org': patch
---
Include namespace in `MyGroupSidebarItem` if not default and remove root item routing if there are multiple groups
+2 -2
View File
@@ -1084,8 +1084,8 @@ export type SidebarSubmenuItemDropdownItem = {
// @public
export type SidebarSubmenuItemProps = {
title: string;
to: string;
icon: IconComponent;
to?: string;
icon?: IconComponent;
dropdownItems?: SidebarSubmenuItemDropdownItem[];
};
@@ -37,20 +37,20 @@ const useStyles = makeStyles<
{ sidebarConfig: SidebarConfig; isPinned: boolean }
>(
theme => ({
root: props => ({
root: {
width: '100%',
transition: 'padding-left 0.1s ease-out',
isolation: 'isolate',
[theme.breakpoints.up('sm')]: {
paddingLeft: () =>
paddingLeft: props =>
props.isPinned
? props.sidebarConfig.drawerWidthOpen
: props.sidebarConfig.drawerWidthClosed,
},
[theme.breakpoints.down('xs')]: {
paddingBottom: props.sidebarConfig.mobileSidebarHeight,
paddingBottom: props => props.sidebarConfig.mobileSidebarHeight,
},
}),
},
content: {
zIndex: 0,
isolation: 'isolate',
@@ -16,6 +16,7 @@
import React, { useContext, useState } from 'react';
import { resolvePath, useLocation, useResolvedPath } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import { Link } from '../../components/Link';
import { IconComponent } from '@backstage/core-plugin-api';
@@ -55,6 +56,9 @@ const useStyles = makeStyles<BackstageTheme>(
margin: 14,
marginLeft: 7,
fontSize: 14,
whiteSpace: 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis',
},
dropdownArrow: {
position: 'absolute',
@@ -68,16 +72,19 @@ const useStyles = makeStyles<BackstageTheme>(
dropdownItem: {
width: '100%',
padding: '10px 0 10px 0',
'&:hover': {
background: '#6f6f6f',
color: theme.palette.navigation.selectedColor,
},
},
textContent: {
color: theme.palette.navigation.color,
display: 'flex',
justifyContent: 'center',
[theme.breakpoints.down('xs')]: {
display: 'block',
paddingLeft: theme.spacing(4),
},
paddingLeft: theme.spacing(4),
paddingRight: theme.spacing(1),
fontSize: '14px',
whiteSpace: 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis',
},
}),
{ name: 'BackstageSidebarSubmenuItem' },
@@ -106,8 +113,8 @@ export type SidebarSubmenuItemDropdownItem = {
*/
export type SidebarSubmenuItemProps = {
title: string;
to: string;
icon: IconComponent;
to?: string;
icon?: IconComponent;
dropdownItems?: SidebarSubmenuItemDropdownItem[];
};
@@ -123,7 +130,7 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => {
const closeSubmenu = () => {
setIsHoveredOn(false);
};
const toLocation = useResolvedPath(to);
const toLocation = useResolvedPath(to ?? '');
const currentLocation = useLocation();
let isActive = isLocationMatch(currentLocation, toLocation);
@@ -139,39 +146,47 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => {
});
return (
<div className={classes.itemContainer}>
<button
onClick={handleClickDropdown}
onTouchStart={e => e.stopPropagation()}
className={classnames(
classes.item,
isActive ? classes.selected : undefined,
)}
>
<Icon fontSize="small" />
<Typography variant="subtitle1" className={classes.label}>
{title}
</Typography>
{showDropDown ? (
<ArrowDropUpIcon className={classes.dropdownArrow} />
) : (
<ArrowDropDownIcon className={classes.dropdownArrow} />
)}
</button>
<Tooltip title={title} enterDelay={500} enterNextDelay={500}>
<button
onClick={handleClickDropdown}
onTouchStart={e => e.stopPropagation()}
className={classnames(
classes.item,
isActive ? classes.selected : undefined,
)}
>
{Icon && <Icon fontSize="small" />}
<Typography variant="subtitle1" className={classes.label}>
{title}
</Typography>
{showDropDown ? (
<ArrowDropUpIcon className={classes.dropdownArrow} />
) : (
<ArrowDropDownIcon className={classes.dropdownArrow} />
)}
</button>
</Tooltip>
{dropdownItems && showDropDown && (
<div className={classes.dropdown}>
{dropdownItems.map((object, key) => (
<Link
to={object.to}
underline="none"
className={classes.dropdownItem}
onClick={closeSubmenu}
onTouchStart={e => e.stopPropagation()}
<Tooltip
key={key}
title={object.title}
enterDelay={500}
enterNextDelay={500}
>
<Typography className={classes.textContent}>
{object.title}
</Typography>
</Link>
<Link
to={object.to}
underline="none"
className={classes.dropdownItem}
onClick={closeSubmenu}
onTouchStart={e => e.stopPropagation()}
>
<Typography className={classes.textContent}>
{object.title}
</Typography>
</Link>
</Tooltip>
))}
</div>
)}
@@ -181,21 +196,23 @@ export const SidebarSubmenuItem = (props: SidebarSubmenuItemProps) => {
return (
<div className={classes.itemContainer}>
<Link
to={to}
underline="none"
className={classnames(
classes.item,
isActive ? classes.selected : undefined,
)}
onClick={closeSubmenu}
onTouchStart={e => e.stopPropagation()}
>
<Icon fontSize="small" />
<Typography variant="subtitle1" className={classes.label}>
{title}
</Typography>
</Link>
<Tooltip title={title} enterDelay={500} enterNextDelay={500}>
<Link
to={to!}
underline="none"
className={classnames(
classes.item,
isActive ? classes.selected : undefined,
)}
onClick={closeSubmenu}
onTouchStart={e => e.stopPropagation()}
>
{Icon && <Icon fontSize="small" />}
<Typography variant="subtitle1" className={classes.label}>
{title}
</Typography>
</Link>
</Tooltip>
</div>
);
};
@@ -15,6 +15,7 @@
*/
import React from 'react';
import { stringifyEntityRef } from '@backstage/catalog-model';
import {
SidebarItem,
SidebarSubmenu,
@@ -31,6 +32,7 @@ import {
catalogApiRef,
CatalogApi,
entityRouteRef,
humanizeEntityRef,
} from '@backstage/plugin-catalog-react';
import { getCompoundEntityRef } from '@backstage/catalog-model';
@@ -80,15 +82,18 @@ export const MyGroupsSidebarItem = (props: {
// Member of more than one group
return (
<SidebarItem icon={icon} to="catalog" text={pluralTitle}>
<SidebarItem icon={icon} text={pluralTitle}>
<SidebarSubmenu title={pluralTitle}>
{groups?.map(function groupsMap(group) {
return (
<SidebarSubmenuItem
title={group.metadata.title || group.metadata.name}
title={
group.metadata.title ||
humanizeEntityRef(group, { defaultKind: 'group' })
}
to={catalogEntityRoute(getCompoundEntityRef(group))}
icon={icon}
key={group.metadata.name}
key={stringifyEntityRef(group)}
/>
);
})}