mirror of
https://github.com/apache/superset.git
synced 2026-07-05 14:25:32 +00:00
Compare commits
3 Commits
chore/ci/s
...
menu-caret
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3da6b37867 | ||
|
|
cd18390dd0 | ||
|
|
36880c088c |
@@ -41,6 +41,51 @@ export type AntdMenuItemType = ReactElement & {
|
|||||||
|
|
||||||
export type MenuItemChildType = AntdMenuItemType;
|
export type MenuItemChildType = AntdMenuItemType;
|
||||||
|
|
||||||
|
// Shared menu item styling for consistent underline animation
|
||||||
|
const sharedMenuItemStyles = (theme: any) => css`
|
||||||
|
&.ant-menu-horizontal > .ant-menu-item,
|
||||||
|
&.ant-menu-horizontal > .ant-menu-submenu {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: ${theme.sizeUnit * 2}px ${theme.sizeUnit * 4}px;
|
||||||
|
::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 98%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: ${theme.colorPrimaryBorderHover};
|
||||||
|
bottom: ${theme.sizeUnit / 4}px;
|
||||||
|
left: 0;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: 0.2s all ease-out;
|
||||||
|
}
|
||||||
|
:hover::after {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.ant-menu-horizontal > .ant-menu-item-selected::after,
|
||||||
|
&.ant-menu-horizontal > .ant-menu-submenu-selected::after {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
&.ant-menu-horizontal > .ant-menu-submenu .ant-menu-submenu-title {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.ant-menu-title-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the empty arrow element */
|
||||||
|
.ant-menu-submenu-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledMenuItem = styled(AntdMenu.Item)`
|
const StyledMenuItem = styled(AntdMenu.Item)`
|
||||||
${({ theme }) => css`
|
${({ theme }) => css`
|
||||||
a {
|
a {
|
||||||
@@ -76,10 +121,13 @@ const StyledMenuItem = styled(AntdMenu.Item)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledMenu = styled(AntdMenu)`
|
const StyledMenu = styled(AntdMenu)`
|
||||||
&.ant-menu-horizontal {
|
${({ theme }) => css`
|
||||||
background-color: inherit;
|
&.ant-menu-horizontal {
|
||||||
border-bottom: 1px solid transparent;
|
background-color: inherit;
|
||||||
}
|
border-bottom: 1px solid transparent;
|
||||||
|
}
|
||||||
|
${sharedMenuItemStyles(theme)}
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledNav = styled(AntdMenu)`
|
const StyledNav = styled(AntdMenu)`
|
||||||
@@ -90,60 +138,12 @@ const StyledNav = styled(AntdMenu)`
|
|||||||
gap: 0;
|
gap: 0;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
line-height: ${theme.lineHeight};
|
line-height: ${theme.lineHeight};
|
||||||
&.ant-menu-horizontal > .ant-menu-item {
|
${sharedMenuItemStyles(theme)}
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: ${theme.sizeUnit * 2}px ${theme.sizeUnit * 4}px;
|
|
||||||
::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
width: 98%;
|
|
||||||
height: 2px;
|
|
||||||
background-color: ${theme.colorPrimaryBorderHover};
|
|
||||||
bottom: ${theme.sizeUnit / 4}px;
|
|
||||||
left: 0;
|
|
||||||
transform: scale(0);
|
|
||||||
transition: 0.2s all ease-out;
|
|
||||||
}
|
|
||||||
:hover::after {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-menu-horizontal > .ant-menu-item-selected::after {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledSubMenu = styled(AntdMenu.SubMenu)`
|
const StyledSubMenu = styled(AntdMenu.SubMenu)`
|
||||||
${({ theme }) => css`
|
/* No custom styling - use shared styles from parent Menu component */
|
||||||
.ant-menu-submenu-open,
|
|
||||||
.ant-menu-submenu-active {
|
|
||||||
.ant-menu-submenu-title {
|
|
||||||
&:after {
|
|
||||||
opacity: 1;
|
|
||||||
width: calc(100% - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-menu-submenu-title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: -3px;
|
|
||||||
left: 50%;
|
|
||||||
width: 0;
|
|
||||||
height: 3px;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
transition: all ${theme.transitionTiming}s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export type MenuMode = AntdMenuProps['mode'];
|
export type MenuMode = AntdMenuProps['mode'];
|
||||||
|
|||||||
@@ -17,14 +17,13 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { styled, css, useTheme } from '@superset-ui/core';
|
import { styled, useTheme } from '@superset-ui/core';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { getUrlParam } from 'src/utils/urlUtils';
|
import { getUrlParam } from 'src/utils/urlUtils';
|
||||||
import { MainNav, MenuMode } from '@superset-ui/core/components/Menu';
|
import { MainNav, MenuMode } from '@superset-ui/core/components/Menu';
|
||||||
import { Tooltip, Grid, Row, Col, Image } from '@superset-ui/core/components';
|
import { Tooltip, Grid, Row, Col, Image } from '@superset-ui/core/components';
|
||||||
import { GenericLink } from 'src/components';
|
import { GenericLink } from 'src/components';
|
||||||
import { NavLink, useLocation } from 'react-router-dom';
|
import { NavLink, useLocation } from 'react-router-dom';
|
||||||
import { Icons } from '@superset-ui/core/components/Icons';
|
|
||||||
import { Typography } from '@superset-ui/core/components/Typography';
|
import { Typography } from '@superset-ui/core/components/Typography';
|
||||||
import { useUiConfig } from 'src/components/UiConfigContext';
|
import { useUiConfig } from 'src/components/UiConfigContext';
|
||||||
import { URL_PARAMS } from 'src/constants';
|
import { URL_PARAMS } from 'src/constants';
|
||||||
@@ -125,26 +124,6 @@ const StyledHeader = styled.header`
|
|||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
const { SubMenu } = MainNav;
|
|
||||||
|
|
||||||
const StyledSubMenu = styled(SubMenu)`
|
|
||||||
${({ theme }) => css`
|
|
||||||
[data-icon="caret-down"] {
|
|
||||||
color: ${theme.colors.grayscale.base};
|
|
||||||
font-size: ${theme.fontSizeXS}px;
|
|
||||||
margin-left: ${theme.sizeUnit}px;
|
|
||||||
}
|
|
||||||
&.ant-menu-submenu {
|
|
||||||
padding: ${theme.sizeUnit * 2}px ${theme.sizeUnit * 4}px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%; &.ant-menu-submenu-active {
|
|
||||||
.ant-menu-title-content {
|
|
||||||
color: ${theme.colorPrimary};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
export function Menu({
|
export function Menu({
|
||||||
@@ -179,6 +158,8 @@ export function Menu({
|
|||||||
Dashboard = '/dashboard',
|
Dashboard = '/dashboard',
|
||||||
Chart = '/chart',
|
Chart = '/chart',
|
||||||
Datasets = '/tablemodelview',
|
Datasets = '/tablemodelview',
|
||||||
|
SqlLab = '/sqllab',
|
||||||
|
SavedQueries = '/savedqueryview',
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultTabSelection: string[] = [];
|
const defaultTabSelection: string[] = [];
|
||||||
@@ -196,6 +177,10 @@ export function Menu({
|
|||||||
case path.startsWith(Paths.Datasets):
|
case path.startsWith(Paths.Datasets):
|
||||||
setActiveTabs(['Datasets']);
|
setActiveTabs(['Datasets']);
|
||||||
break;
|
break;
|
||||||
|
case path.startsWith(Paths.SqlLab):
|
||||||
|
case path.startsWith(Paths.SavedQueries):
|
||||||
|
setActiveTabs(['SQL Lab']);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
setActiveTabs(defaultTabSelection);
|
setActiveTabs(defaultTabSelection);
|
||||||
}
|
}
|
||||||
@@ -228,17 +213,7 @@ export function Menu({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<StyledSubMenu
|
<MainNav.SubMenu key={index} title={label}>
|
||||||
key={index}
|
|
||||||
title={label}
|
|
||||||
icon={
|
|
||||||
showMenu === 'inline' ? (
|
|
||||||
<></>
|
|
||||||
) : (
|
|
||||||
<Icons.CaretDownOutlined iconSize="xs" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
||||||
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
||||||
return <MainNav.Divider key={`$${index1}`} />;
|
return <MainNav.Divider key={`$${index1}`} />;
|
||||||
@@ -264,7 +239,7 @@ export function Menu({
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})}
|
})}
|
||||||
</StyledSubMenu>
|
</MainNav.SubMenu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const renderBrand = () => {
|
const renderBrand = () => {
|
||||||
|
|||||||
@@ -570,7 +570,6 @@ const RightMenu = ({
|
|||||||
data-test="new-dropdown-icon"
|
data-test="new-dropdown-icon"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
icon: <Icons.CaretDownOutlined iconSize="xs" />,
|
|
||||||
children: buildNewDropdownItems(),
|
children: buildNewDropdownItems(),
|
||||||
...{ 'data-test': 'new-dropdown' },
|
...{ 'data-test': 'new-dropdown' },
|
||||||
});
|
});
|
||||||
@@ -587,7 +586,6 @@ const RightMenu = ({
|
|||||||
items.push({
|
items.push({
|
||||||
key: 'settings',
|
key: 'settings',
|
||||||
label: t('Settings'),
|
label: t('Settings'),
|
||||||
icon: <Icons.CaretDownOutlined iconSize="xs" />,
|
|
||||||
children: buildSettingsMenuItems(),
|
children: buildSettingsMenuItems(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user