mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
fix(navbar): some styling + components inconsistencies (#36120)
This commit is contained in:
committed by
GitHub
parent
6723a58780
commit
9bff64824b
@@ -18,9 +18,8 @@
|
||||
*/
|
||||
import { useState, useEffect } from 'react';
|
||||
import { styled, css, useTheme } from '@apache-superset/core/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { getUrlParam } from 'src/utils/urlUtils';
|
||||
import { MainNav, MenuMode } from '@superset-ui/core/components/Menu';
|
||||
import { MainNav, MenuItem } from '@superset-ui/core/components/Menu';
|
||||
import { Tooltip, Grid, Row, Col, Image } from '@superset-ui/core/components';
|
||||
import { GenericLink } from 'src/components';
|
||||
import { NavLink, useLocation } from 'react-router-dom';
|
||||
@@ -34,6 +33,7 @@ import {
|
||||
MenuData,
|
||||
} from 'src/types/bootstrapTypes';
|
||||
import RightMenu from './RightMenu';
|
||||
import { NAVBAR_MENU_POPUP_OFFSET } from './commonMenuData';
|
||||
|
||||
interface MenuProps {
|
||||
data: MenuData;
|
||||
@@ -93,27 +93,7 @@ const StyledMainNav = styled(MainNav)`
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.ant-menu-item {
|
||||
padding: 0 ${theme.sizeUnit * 6}px 0 ${theme.sizeUnit * 3}px !important;
|
||||
}
|
||||
|
||||
.ant-menu > .ant-menu-item > span > a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.main-nav .ant-menu-submenu-title > svg:nth-of-type(1) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const { SubMenu } = MainNav;
|
||||
|
||||
const StyledSubMenu = styled(SubMenu)`
|
||||
${({ theme }) => css`
|
||||
&.ant-menu-submenu.ant-menu-submenu-horizontal {
|
||||
.ant-menu-submenu.ant-menu-submenu-horizontal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
@@ -156,7 +136,7 @@ const StyledSubMenu = styled(SubMenu)`
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-menu-submenu-selected.ant-menu-submenu-horizontal::after {
|
||||
.ant-menu-submenu-selected.ant-menu-submenu-horizontal::after {
|
||||
transform: scale(1);
|
||||
}
|
||||
`}
|
||||
@@ -197,6 +177,10 @@ const StyledCol = styled(Col)`
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledImage = styled(Image)`
|
||||
object-fit: contain;
|
||||
`;
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
export function Menu({
|
||||
@@ -209,23 +193,10 @@ export function Menu({
|
||||
},
|
||||
isFrontendRoute = () => false,
|
||||
}: MenuProps) {
|
||||
const [showMenu, setMenu] = useState<MenuMode>('horizontal');
|
||||
const screens = useBreakpoint();
|
||||
const uiConfig = useUiConfig();
|
||||
const theme = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
if (window.innerWidth <= 767) {
|
||||
setMenu('inline');
|
||||
} else setMenu('horizontal');
|
||||
}
|
||||
handleResize();
|
||||
const windowResize = debounce(() => handleResize(), 10);
|
||||
window.addEventListener('resize', windowResize);
|
||||
return () => window.removeEventListener('resize', windowResize);
|
||||
}, []);
|
||||
|
||||
enum Paths {
|
||||
Explore = '/explore',
|
||||
Dashboard = '/dashboard',
|
||||
@@ -261,65 +232,55 @@ export function Menu({
|
||||
const standalone = getUrlParam(URL_PARAMS.standalone);
|
||||
if (standalone || uiConfig.hideNav) return <></>;
|
||||
|
||||
const renderSubMenu = ({
|
||||
const buildMenuItem = ({
|
||||
label,
|
||||
childs,
|
||||
url,
|
||||
index,
|
||||
isFrontendRoute,
|
||||
}: MenuObjectProps) => {
|
||||
}: MenuObjectProps): MenuItem => {
|
||||
if (url && isFrontendRoute) {
|
||||
return (
|
||||
<MainNav.Item key={label} role="presentation">
|
||||
return {
|
||||
key: label,
|
||||
label: (
|
||||
<NavLink role="button" to={url} activeClassName="is-active">
|
||||
{label}
|
||||
</NavLink>
|
||||
</MainNav.Item>
|
||||
);
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if (url) {
|
||||
return (
|
||||
<MainNav.Item key={label}>
|
||||
<Typography.Link href={url}>{label}</Typography.Link>
|
||||
</MainNav.Item>
|
||||
);
|
||||
return {
|
||||
key: label,
|
||||
label: <Typography.Link href={url}>{label}</Typography.Link>,
|
||||
};
|
||||
}
|
||||
return (
|
||||
<StyledSubMenu
|
||||
key={label}
|
||||
title={label}
|
||||
popupOffset={[0, -8]}
|
||||
icon={
|
||||
showMenu === 'inline' ? <></> : <Icons.DownOutlined iconSize="xs" />
|
||||
}
|
||||
>
|
||||
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
||||
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
||||
return <MainNav.Divider key={`$${index1}`} />;
|
||||
}
|
||||
if (typeof child !== 'string') {
|
||||
return (
|
||||
<MainNav.Item key={`${child.label}`}>
|
||||
{child.isFrontendRoute ? (
|
||||
<NavLink
|
||||
to={child.url || ''}
|
||||
exact
|
||||
activeClassName="is-active"
|
||||
>
|
||||
{child.label}
|
||||
</NavLink>
|
||||
) : (
|
||||
<Typography.Link href={child.url}>
|
||||
{child.label}
|
||||
</Typography.Link>
|
||||
)}
|
||||
</MainNav.Item>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</StyledSubMenu>
|
||||
);
|
||||
|
||||
const childItems: MenuItem[] = [];
|
||||
childs?.forEach((child: MenuObjectChildProps | string, index1: number) => {
|
||||
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
||||
childItems.push({ type: 'divider', key: `divider-${index1}` });
|
||||
} else if (typeof child !== 'string') {
|
||||
childItems.push({
|
||||
key: `${child.label}`,
|
||||
label: child.isFrontendRoute ? (
|
||||
<NavLink to={child.url || ''} exact activeClassName="is-active">
|
||||
{child.label}
|
||||
</NavLink>
|
||||
) : (
|
||||
<Typography.Link href={child.url}>{child.label}</Typography.Link>
|
||||
),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
key: label,
|
||||
label,
|
||||
icon: <Icons.DownOutlined iconSize="xs" />,
|
||||
popupOffset: NAVBAR_MENU_POPUP_OFFSET,
|
||||
children: childItems,
|
||||
};
|
||||
};
|
||||
const renderBrand = () => {
|
||||
let link;
|
||||
@@ -327,7 +288,7 @@ export function Menu({
|
||||
link = (
|
||||
<StyledBrandWrapper margin={theme.brandLogoMargin}>
|
||||
<StyledBrandLink href={theme.brandLogoHref}>
|
||||
<Image
|
||||
<StyledImage
|
||||
preview={false}
|
||||
src={theme.brandLogoUrl}
|
||||
alt={theme.brandLogoAlt || 'Apache Superset'}
|
||||
@@ -342,7 +303,7 @@ export function Menu({
|
||||
// Kept as is for backwards compatibility with the old theme system / superset_config.py
|
||||
link = (
|
||||
<GenericLink className="navbar-brand" to={brand.path}>
|
||||
<Image preview={false} src={brand.icon} alt={brand.alt} />
|
||||
<StyledImage preview={false} src={brand.icon} alt={brand.alt} />
|
||||
</GenericLink>
|
||||
);
|
||||
} else {
|
||||
@@ -352,7 +313,7 @@ export function Menu({
|
||||
href={brand.path}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<Image preview={false} src={brand.icon} alt={brand.alt} />
|
||||
<StyledImage preview={false} src={brand.icon} alt={brand.alt} />
|
||||
</Typography.Link>
|
||||
);
|
||||
}
|
||||
@@ -377,15 +338,13 @@ export function Menu({
|
||||
</StyledBrandText>
|
||||
)}
|
||||
<StyledMainNav
|
||||
mode={showMenu}
|
||||
mode="horizontal"
|
||||
data-test="navbar-top"
|
||||
className="main-nav"
|
||||
selectedKeys={activeTabs}
|
||||
disabledOverflow
|
||||
>
|
||||
{menu.map((item, index) => {
|
||||
items={menu.map(item => {
|
||||
const props = {
|
||||
index,
|
||||
...item,
|
||||
isFrontendRoute: isFrontendRoute(item.url),
|
||||
childs: item.childs?.map(c => {
|
||||
@@ -400,9 +359,9 @@ export function Menu({
|
||||
}),
|
||||
};
|
||||
|
||||
return renderSubMenu(props);
|
||||
return buildMenuItem(props);
|
||||
})}
|
||||
</StyledMainNav>
|
||||
/>
|
||||
</StyledCol>
|
||||
<Col md={8} xs={24}>
|
||||
<RightMenu
|
||||
|
||||
@@ -53,6 +53,7 @@ import {
|
||||
GlobalMenuDataOptions,
|
||||
RightMenuProps,
|
||||
} from './types';
|
||||
import { NAVBAR_MENU_POPUP_OFFSET } from './commonMenuData';
|
||||
|
||||
const extensionsRegistry = getExtensionsRegistry();
|
||||
|
||||
@@ -379,6 +380,7 @@ const RightMenu = ({
|
||||
label: menu.label,
|
||||
icon: menu.icon,
|
||||
children: childItems,
|
||||
popupOffset: NAVBAR_MENU_POPUP_OFFSET,
|
||||
});
|
||||
} else if (menu.url) {
|
||||
if (
|
||||
@@ -559,6 +561,7 @@ const RightMenu = ({
|
||||
className: 'submenu-with-caret',
|
||||
icon: <Icons.DownOutlined iconSize="xs" />,
|
||||
children: buildNewDropdownItems(),
|
||||
popupOffset: NAVBAR_MENU_POPUP_OFFSET,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -576,6 +579,7 @@ const RightMenu = ({
|
||||
icon: <Icons.DownOutlined iconSize="xs" />,
|
||||
children: buildSettingsMenuItems(),
|
||||
className: 'submenu-with-caret',
|
||||
popupOffset: NAVBAR_MENU_POPUP_OFFSET,
|
||||
});
|
||||
|
||||
return items;
|
||||
@@ -660,6 +664,8 @@ const RightMenu = ({
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
border-bottom: none !important;
|
||||
|
||||
/* Remove the underline from menu items */
|
||||
.ant-menu-item:after,
|
||||
@@ -668,11 +674,14 @@ const RightMenu = ({
|
||||
}
|
||||
|
||||
.submenu-with-caret {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
.ant-menu-submenu-title {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${theme.sizeUnit * 2}px;
|
||||
flex-direction: row-reverse;
|
||||
height: 100%;
|
||||
}
|
||||
&.ant-menu-submenu::after {
|
||||
inset-inline: ${theme.sizeUnit}px;
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
*/
|
||||
import { t } from '@superset-ui/core';
|
||||
|
||||
/**
|
||||
* Shared popup offset configuration for navbar menu dropdowns.
|
||||
*/
|
||||
export const NAVBAR_MENU_POPUP_OFFSET: [number, number] = [0, -8];
|
||||
|
||||
export const commonMenuData = {
|
||||
name: t('SQL'),
|
||||
tabs: [
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Icons, Tooltip } from '@superset-ui/core/components';
|
||||
import type { MenuItem } from '@superset-ui/core/components/Menu';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { ThemeMode, ThemeAlgorithm } from '@apache-superset/core/ui';
|
||||
import { NAVBAR_MENU_POPUP_OFFSET } from 'src/features/home/commonMenuData';
|
||||
|
||||
export interface ThemeSubMenuOption {
|
||||
key: ThemeMode;
|
||||
@@ -138,5 +139,6 @@ export const useThemeMenuItems = ({
|
||||
icon: <Icons.DownOutlined iconSize="xs" />,
|
||||
className: 'submenu-with-caret',
|
||||
children,
|
||||
popupOffset: NAVBAR_MENU_POPUP_OFFSET,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user