mirror of
https://github.com/apache/superset.git
synced 2026-05-01 14:04:21 +00:00
Compare commits
3 Commits
docs/testi
...
menu-caret
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3da6b37867 | ||
|
|
cd18390dd0 | ||
|
|
36880c088c |
@@ -41,6 +41,51 @@ export type AntdMenuItemType = ReactElement & {
|
||||
|
||||
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)`
|
||||
${({ theme }) => css`
|
||||
a {
|
||||
@@ -76,10 +121,13 @@ const StyledMenuItem = styled(AntdMenu.Item)`
|
||||
`;
|
||||
|
||||
const StyledMenu = styled(AntdMenu)`
|
||||
&.ant-menu-horizontal {
|
||||
background-color: inherit;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
${({ theme }) => css`
|
||||
&.ant-menu-horizontal {
|
||||
background-color: inherit;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
${sharedMenuItemStyles(theme)}
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledNav = styled(AntdMenu)`
|
||||
@@ -90,60 +138,12 @@ const StyledNav = styled(AntdMenu)`
|
||||
gap: 0;
|
||||
border-bottom: 0;
|
||||
line-height: ${theme.lineHeight};
|
||||
&.ant-menu-horizontal > .ant-menu-item {
|
||||
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);
|
||||
}
|
||||
${sharedMenuItemStyles(theme)}
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledSubMenu = styled(AntdMenu.SubMenu)`
|
||||
${({ theme }) => css`
|
||||
.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;
|
||||
}
|
||||
}
|
||||
`}
|
||||
/* No custom styling - use shared styles from parent Menu component */
|
||||
`;
|
||||
|
||||
export type MenuMode = AntdMenuProps['mode'];
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
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 { getUrlParam } from 'src/utils/urlUtils';
|
||||
import { MainNav, MenuMode } 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';
|
||||
import { Icons } from '@superset-ui/core/components/Icons';
|
||||
import { Typography } from '@superset-ui/core/components/Typography';
|
||||
import { useUiConfig } from 'src/components/UiConfigContext';
|
||||
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;
|
||||
|
||||
export function Menu({
|
||||
@@ -179,6 +158,8 @@ export function Menu({
|
||||
Dashboard = '/dashboard',
|
||||
Chart = '/chart',
|
||||
Datasets = '/tablemodelview',
|
||||
SqlLab = '/sqllab',
|
||||
SavedQueries = '/savedqueryview',
|
||||
}
|
||||
|
||||
const defaultTabSelection: string[] = [];
|
||||
@@ -196,6 +177,10 @@ export function Menu({
|
||||
case path.startsWith(Paths.Datasets):
|
||||
setActiveTabs(['Datasets']);
|
||||
break;
|
||||
case path.startsWith(Paths.SqlLab):
|
||||
case path.startsWith(Paths.SavedQueries):
|
||||
setActiveTabs(['SQL Lab']);
|
||||
break;
|
||||
default:
|
||||
setActiveTabs(defaultTabSelection);
|
||||
}
|
||||
@@ -228,17 +213,7 @@ export function Menu({
|
||||
);
|
||||
}
|
||||
return (
|
||||
<StyledSubMenu
|
||||
key={index}
|
||||
title={label}
|
||||
icon={
|
||||
showMenu === 'inline' ? (
|
||||
<></>
|
||||
) : (
|
||||
<Icons.CaretDownOutlined iconSize="xs" />
|
||||
)
|
||||
}
|
||||
>
|
||||
<MainNav.SubMenu key={index} title={label}>
|
||||
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
||||
if (typeof child === 'string' && child === '-' && label !== 'Data') {
|
||||
return <MainNav.Divider key={`$${index1}`} />;
|
||||
@@ -264,7 +239,7 @@ export function Menu({
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</StyledSubMenu>
|
||||
</MainNav.SubMenu>
|
||||
);
|
||||
};
|
||||
const renderBrand = () => {
|
||||
|
||||
@@ -570,7 +570,6 @@ const RightMenu = ({
|
||||
data-test="new-dropdown-icon"
|
||||
/>
|
||||
),
|
||||
icon: <Icons.CaretDownOutlined iconSize="xs" />,
|
||||
children: buildNewDropdownItems(),
|
||||
...{ 'data-test': 'new-dropdown' },
|
||||
});
|
||||
@@ -587,7 +586,6 @@ const RightMenu = ({
|
||||
items.push({
|
||||
key: 'settings',
|
||||
label: t('Settings'),
|
||||
icon: <Icons.CaretDownOutlined iconSize="xs" />,
|
||||
children: buildSettingsMenuItems(),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user