diff --git a/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx index ca692cf9dec..ef0e58a6ea1 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx @@ -105,6 +105,15 @@ const StyledTable = styled(Table)<{ white-space: nowrap; } + .ant-table-tbody > tr > td { + height: ${theme.sizeUnit * 12}px; + } + + .ant-table-tbody > tr > td.ant-table-cell:has(.ant-avatar-group) { + padding-top: ${theme.sizeUnit}px; + padding-bottom: ${theme.sizeUnit}px; + } + .ant-table-placeholder .ant-table-cell { border-bottom: 0; } diff --git a/superset-frontend/src/components/ListView/ListView.tsx b/superset-frontend/src/components/ListView/ListView.tsx index 67475f09937..100ac943777 100644 --- a/superset-frontend/src/components/ListView/ListView.tsx +++ b/superset-frontend/src/components/ListView/ListView.tsx @@ -60,7 +60,7 @@ const ListViewStyles = styled.div` & .controls { display: flex; flex-wrap: wrap; - column-gap: ${theme.sizeUnit * 6}px; + column-gap: ${theme.sizeUnit * 7}px; row-gap: ${theme.sizeUnit * 4}px; } } diff --git a/superset-frontend/src/components/ListView/utils.ts b/superset-frontend/src/components/ListView/utils.ts index 69a82f0d645..37b15e87805 100644 --- a/superset-frontend/src/components/ListView/utils.ts +++ b/superset-frontend/src/components/ListView/utils.ts @@ -70,7 +70,7 @@ const RisonParam: QueryParamConfig = { : rison.decode(dataStr), }; -export const SELECT_WIDTH = 175; +export const SELECT_WIDTH = 176; export const RANGE_WIDTH = 300; export const WIDER_DROPDOWN_WIDTH = '300px'; diff --git a/superset-frontend/src/explore/components/ControlHeader.tsx b/superset-frontend/src/explore/components/ControlHeader.tsx index aff629ff3fe..5de910e5d1f 100644 --- a/superset-frontend/src/explore/components/ControlHeader.tsx +++ b/superset-frontend/src/explore/components/ControlHeader.tsx @@ -167,7 +167,7 @@ const ControlHeader: FC = ({ placement="top" title={validationErrors?.join(' ')} > - + {' '} )} diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx index 8233b815403..2a0502a1763 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx @@ -627,7 +627,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => { id={`${kebabCase('validation-errors')}-tooltip`} title={t('This section contains validation errors')} > - + )} @@ -752,9 +752,9 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => { placement="right" title={props.errorMessage} > - @@ -813,9 +813,9 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => { placement="right" title={t('This section contains validation errors')} > - diff --git a/superset-frontend/src/features/home/Menu.tsx b/superset-frontend/src/features/home/Menu.tsx index b9705851e4c..92589f81f8c 100644 --- a/superset-frontend/src/features/home/Menu.tsx +++ b/superset-frontend/src/features/home/Menu.tsx @@ -41,110 +41,163 @@ interface MenuProps { } const StyledHeader = styled.header` - ${({ theme }) => ` - background-color: ${theme.colorBgContainer}; - border-bottom: 1px solid ${theme.colorBorderSecondary}; - z-index: 10; + ${({ theme }) => css` + background-color: ${theme.colorBgContainer}; + border-bottom: 1px solid ${theme.colorBorderSecondary}; + padding: 0 ${theme.sizeUnit * 4}px; + z-index: 10; - &:nth-last-of-type(2) nav { - margin-bottom: 2px; - } - .caret { - display: none; - } - & .ant-image{ - display: contents; - height: 100%; - padding: ${theme.sizeUnit}px - ${theme.sizeUnit * 2}px - ${theme.sizeUnit}px - ${theme.sizeUnit * 4}px; - } - .navbar-brand { - display: flex; - flex-direction: column; - justify-content: center; - /* must be exactly the height of the Antd navbar */ - min-height: 50px; - padding: ${theme.sizeUnit}px - ${theme.sizeUnit * 2}px - ${theme.sizeUnit}px - ${theme.sizeUnit * 4}px; - max-width: ${theme.sizeUnit * theme.brandIconMaxWidth}px; - img { - height: 100%; - object-fit: contain; - } - &:focus { - border-color: transparent; - } - &:focus-visible { - border-color: ${theme.colorPrimaryText}; - } - } - .navbar-brand-text { - border-left: 1px solid ${theme.colorBorderSecondary}; - border-right: 1px solid ${theme.colorBorderSecondary}; - height: 100%; - color: ${theme.colorText}; - padding-left: ${theme.sizeUnit * 4}px; - padding-right: ${theme.sizeUnit * 4}px; - margin-right: ${theme.sizeUnit * 6}px; - font-size: ${theme.fontSizeLG}px; - float: left; - display: flex; - flex-direction: column; - justify-content: center; + &:nth-last-of-type(2) nav { + margin-bottom: 2px; + } - span { - max-width: ${theme.sizeUnit * 58}px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - @media (max-width: 1127px) { - display: none; - } - } - @media (max-width: 767px) { - .navbar-brand { - float: none; - } - } - @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: 0px; - } - .main-nav .ant-menu-submenu-title > svg:nth-of-type(1) { - display: none; - } - } + .caret { + display: none; + } `} `; + +const StyledBrandText = styled.div` + ${({ theme }) => css` + border-left: 1px solid ${theme.colorBorderSecondary}; + border-right: 1px solid ${theme.colorBorderSecondary}; + height: 100%; + color: ${theme.colorText}; + padding-left: ${theme.sizeUnit * 4}px; + padding-right: ${theme.sizeUnit * 4}px; + margin-right: ${theme.sizeUnit * 6}px; + font-size: ${theme.fontSizeLG}px; + float: left; + display: flex; + flex-direction: column; + justify-content: center; + + span { + max-width: ${theme.sizeUnit * 58}px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + @media (max-width: 1127px) { + display: none; + } + `} +`; + +const StyledMainNav = styled(MainNav)` + ${({ theme }) => css` + .ant-menu-item .ant-menu-item-icon + span, + .ant-menu-submenu-title .ant-menu-item-icon + span, + .ant-menu-item .anticon + span, + .ant-menu-submenu-title .anticon + span { + 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` - [data-icon="caret-down"] { - color: ${theme.colorIcon}; - font-size: ${theme.fontSizeXS}px; - margin-left: ${theme.sizeUnit}px; - } - &.ant-menu-submenu { - padding: ${theme.sizeUnit * 2}px ${theme.sizeUnit * 4}px; + &.ant-menu-submenu.ant-menu-submenu-horizontal { + display: flex; + align-items: center; + height: 100%; + padding: 0; + + .ant-menu-submenu-title { display: flex; + gap: ${theme.sizeUnit * 2}px; + flex-direction: row-reverse; align-items: center; - height: 100%; &.ant-menu-submenu-active { - .ant-menu-title-content { - color: ${theme.colorPrimary}; + height: 100%; + padding: 0 ${theme.sizeUnit * 4}px; + } + + &:hover, + &.ant-menu-submenu-active { + .ant-menu-title-content { + color: ${theme.colorPrimary}; + } + } + + &::after { + content: ''; + position: absolute; + width: 98%; + height: 2px; + background-color: ${theme.colorPrimaryBorderHover}; + bottom: ${theme.sizeUnit / 8}px; + left: 1%; + right: auto; + inset-inline-start: 1%; + inset-inline-end: auto; + transform: scale(0); + transition: 0.2s all ease-out; + } + + &:hover::after, + &.ant-menu-submenu-open::after { + transform: scale(1); + } + } + + &.ant-menu-submenu-selected.ant-menu-submenu-horizontal::after { + transform: scale(1); } - } `} `; + +const StyledBrandWrapper = styled.div<{ margin?: string }>` + ${({ margin }) => css` + height: ${margin ? 'auto' : '100%'}; + margin: ${margin ?? 0}; + `} +`; + +const StyledBrandLink = styled(Typography.Link)` + ${({ theme }) => css` + align-items: center; + display: flex; + height: 100%; + justify-content: center; + + &:focus { + border-color: transparent; + } + + &:focus-visible { + border-color: ${theme.colorPrimaryText}; + } + `} +`; + +const StyledRow = styled(Row)` + height: 100%; +`; + +const StyledCol = styled(Col)` + ${({ theme }) => css` + display: flex; + gap: ${theme.sizeUnit * 4}px; + `} +`; + const { useBreakpoint } = Grid; export function Menu({ @@ -179,6 +232,8 @@ export function Menu({ Dashboard = '/dashboard', Chart = '/chart', Datasets = '/tablemodelview', + SqlLab = '/sqllab', + SavedQueries = '/savedqueryview', } const defaultTabSelection: string[] = []; @@ -196,6 +251,9 @@ export function Menu({ case path.startsWith(Paths.Datasets): setActiveTabs(['Datasets']); break; + case path.startsWith(Paths.SqlLab) || path.startsWith(Paths.SavedQueries): + setActiveTabs(['SQL']); + break; default: setActiveTabs(defaultTabSelection); } @@ -229,14 +287,11 @@ export function Menu({ } return ( - ) : ( - - ) + showMenu === 'inline' ? <> : } > {childs?.map((child: MenuObjectChildProps | string, index1: number) => { @@ -270,25 +325,17 @@ export function Menu({ const renderBrand = () => { let link; if (theme.brandLogoUrl) { - let style = { padding: '0px', margin: '0px' } as React.CSSProperties; - if (theme.brandLogoHeight) { - style = { ...style, height: theme.brandLogoHeight, minHeight: '0px' }; - } - if (theme.brandLogoMargin) { - style = { ...style, margin: theme.brandLogoMargin }; - } link = ( - - {theme.brandLogoAlt - + + + {theme.brandLogoAlt + + ); } else if (isFrontendRoute(window.location.pathname)) { // --------------------------------------------------------------------------------- @@ -315,8 +362,8 @@ export function Menu({ }; return ( - - + + {brand.text && ( -
+ {brand.text} -
+ )} - - + +
-
+
); } diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx index e59be8e4c48..315ad304e5a 100644 --- a/superset-frontend/src/features/home/RightMenu.tsx +++ b/superset-frontend/src/features/home/RightMenu.tsx @@ -69,7 +69,6 @@ const StyledDiv = styled.div<{ align: string }>` flex-direction: row; justify-content: ${({ align }) => align}; align-items: center; - margin-right: ${({ theme }) => theme.sizeUnit}px; `; const StyledMenuItemWithIcon = styled.div` @@ -565,7 +564,7 @@ const RightMenu = ({ key: 'new-dropdown', label: , className: 'submenu-with-caret', - icon: , + icon: , children: buildNewDropdownItems(), }); } @@ -581,7 +580,7 @@ const RightMenu = ({ items.push({ key: 'settings', label: t('Settings'), - icon: , + icon: , children: buildSettingsMenuItems(), className: 'submenu-with-caret', }); @@ -676,7 +675,7 @@ const RightMenu = ({ } .submenu-with-caret { - padding: 0 ${theme.sizeUnit}px; + padding: 0; .ant-menu-submenu-title { display: flex; gap: ${theme.sizeUnit * 2}px; @@ -685,6 +684,12 @@ const RightMenu = ({ &.ant-menu-submenu::after { inset-inline: ${theme.sizeUnit}px; } + &.ant-menu-submenu:hover, + &.ant-menu-submenu-active { + .ant-menu-title-content { + color: ${theme.colorPrimary}; + } + } } `} selectable={false} diff --git a/superset-frontend/src/features/home/SubMenu.tsx b/superset-frontend/src/features/home/SubMenu.tsx index 79da4e47a22..1d39f8ef64d 100644 --- a/superset-frontend/src/features/home/SubMenu.tsx +++ b/superset-frontend/src/features/home/SubMenu.tsx @@ -40,7 +40,7 @@ const StyledHeader = styled.div<{ backgroundColor?: string }>` align-items: center; position: relative; padding: ${({ theme }) => theme.sizeUnit * 2}px - ${({ theme }) => theme.sizeUnit * 5}px; + ${({ theme }) => theme.sizeUnit * 4}px; margin-bottom: ${({ theme }) => theme.sizeUnit * 4}px; .header { font-weight: ${({ theme }) => theme.fontWeightStrong}; @@ -53,10 +53,10 @@ const StyledHeader = styled.div<{ backgroundColor?: string }>` .nav-right { display: flex; align-items: center; - margin-right: ${({ theme }) => theme.sizeUnit * 3}px; + /* margin-right: ${({ theme }) => theme.sizeUnit * 3}px; */ float: right; position: absolute; - right: 0; + right: ${({ theme }) => theme.sizeUnit * 4}px; ul.ant-menu-root { padding: 0px; } diff --git a/superset-frontend/src/hooks/useThemeMenuItems.tsx b/superset-frontend/src/hooks/useThemeMenuItems.tsx index 145a448a221..25c5e56068d 100644 --- a/superset-frontend/src/hooks/useThemeMenuItems.tsx +++ b/superset-frontend/src/hooks/useThemeMenuItems.tsx @@ -134,7 +134,7 @@ export const useThemeMenuItems = ({ return { key: 'theme-sub-menu', label: selectedThemeModeIcon, - icon: , + icon: , className: 'submenu-with-caret', children, }; diff --git a/superset/config.py b/superset/config.py index 0e69ebf00e8..4912fc4d954 100644 --- a/superset/config.py +++ b/superset/config.py @@ -752,7 +752,7 @@ THEME_DEFAULT: Theme = { # Brand "brandLogoAlt": "Apache Superset", "brandLogoUrl": APP_ICON, - "brandLogoMargin": "18px", + "brandLogoMargin": "18px 0", "brandLogoHref": "/", "brandLogoHeight": "24px", # Spinner