1818 */
1919import { useState , useEffect } from 'react' ;
2020import { styled , css , useTheme } from '@apache-superset/core/ui' ;
21- import { debounce } from 'lodash' ;
2221import { getUrlParam } from 'src/utils/urlUtils' ;
23- import { MainNav , MenuMode } from '@superset-ui/core/components/Menu' ;
22+ import { MainNav , MenuItem } from '@superset-ui/core/components/Menu' ;
2423import { Tooltip , Grid , Row , Col , Image } from '@superset-ui/core/components' ;
2524import { GenericLink } from 'src/components' ;
2625import { NavLink , useLocation } from 'react-router-dom' ;
@@ -34,6 +33,7 @@ import {
3433 MenuData ,
3534} from 'src/types/bootstrapTypes' ;
3635import RightMenu from './RightMenu' ;
36+ import { NAVBAR_MENU_POPUP_OFFSET } from './commonMenuData' ;
3737
3838interface MenuProps {
3939 data : MenuData ;
@@ -93,27 +93,7 @@ const StyledMainNav = styled(MainNav)`
9393 margin-inline-start : 0 ;
9494 }
9595
96- @media (max-width : 767px ) {
97- .ant-menu-item {
98- padding : 0 ${ theme . sizeUnit * 6 } px 0 ${ theme . sizeUnit * 3 } px !important ;
99- }
100-
101- .ant-menu > .ant-menu-item > span > a {
102- padding : 0 ;
103- }
104-
105- & .main-nav .ant-menu-submenu-title > svg : nth-of-type (1 ) {
106- display : none;
107- }
108- }
109- ` }
110- ` ;
111-
112- const { SubMenu } = MainNav ;
113-
114- const StyledSubMenu = styled ( SubMenu ) `
115- ${ ( { theme } ) => css `
116- & .ant-menu-submenu .ant-menu-submenu-horizontal {
96+ .ant-menu-submenu .ant-menu-submenu-horizontal {
11797 display : flex;
11898 align-items : center;
11999 height : 100% ;
@@ -156,7 +136,7 @@ const StyledSubMenu = styled(SubMenu)`
156136 }
157137 }
158138
159- & .ant-menu-submenu-selected .ant-menu-submenu-horizontal ::after {
139+ .ant-menu-submenu-selected .ant-menu-submenu-horizontal ::after {
160140 transform : scale (1 );
161141 }
162142 ` }
@@ -197,6 +177,10 @@ const StyledCol = styled(Col)`
197177 ` }
198178` ;
199179
180+ const StyledImage = styled ( Image ) `
181+ object-fit: contain;
182+ ` ;
183+
200184const { useBreakpoint } = Grid ;
201185
202186export function Menu ( {
@@ -209,23 +193,10 @@ export function Menu({
209193 } ,
210194 isFrontendRoute = ( ) => false ,
211195} : MenuProps ) {
212- const [ showMenu , setMenu ] = useState < MenuMode > ( 'horizontal' ) ;
213196 const screens = useBreakpoint ( ) ;
214197 const uiConfig = useUiConfig ( ) ;
215198 const theme = useTheme ( ) ;
216199
217- useEffect ( ( ) => {
218- function handleResize ( ) {
219- if ( window . innerWidth <= 767 ) {
220- setMenu ( 'inline' ) ;
221- } else setMenu ( 'horizontal' ) ;
222- }
223- handleResize ( ) ;
224- const windowResize = debounce ( ( ) => handleResize ( ) , 10 ) ;
225- window . addEventListener ( 'resize' , windowResize ) ;
226- return ( ) => window . removeEventListener ( 'resize' , windowResize ) ;
227- } , [ ] ) ;
228-
229200 enum Paths {
230201 Explore = '/explore' ,
231202 Dashboard = '/dashboard' ,
@@ -261,73 +232,63 @@ export function Menu({
261232 const standalone = getUrlParam ( URL_PARAMS . standalone ) ;
262233 if ( standalone || uiConfig . hideNav ) return < > </ > ;
263234
264- const renderSubMenu = ( {
235+ const buildMenuItem = ( {
265236 label,
266237 childs,
267238 url,
268- index,
269239 isFrontendRoute,
270- } : MenuObjectProps ) => {
240+ } : MenuObjectProps ) : MenuItem => {
271241 if ( url && isFrontendRoute ) {
272- return (
273- < MainNav . Item key = { label } role = "presentation" >
242+ return {
243+ key : label ,
244+ label : (
274245 < NavLink role = "button" to = { url } activeClassName = "is-active" >
275246 { label }
276247 </ NavLink >
277- </ MainNav . Item >
278- ) ;
248+ ) ,
249+ } ;
279250 }
251+
280252 if ( url ) {
281- return (
282- < MainNav . Item key = { label } >
283- < Typography . Link href = { url } > { label } </ Typography . Link >
284- </ MainNav . Item >
285- ) ;
253+ return {
254+ key : label ,
255+ label : < Typography . Link href = { url } > { label } </ Typography . Link > ,
256+ } ;
286257 }
287- return (
288- < StyledSubMenu
289- key = { label }
290- title = { label }
291- popupOffset = { [ 0 , - 8 ] }
292- icon = {
293- showMenu === 'inline' ? < > </ > : < Icons . DownOutlined iconSize = "xs" />
294- }
295- >
296- { childs ?. map ( ( child : MenuObjectChildProps | string , index1 : number ) => {
297- if ( typeof child === 'string' && child === '-' && label !== 'Data' ) {
298- return < MainNav . Divider key = { `$${ index1 } ` } /> ;
299- }
300- if ( typeof child !== 'string' ) {
301- return (
302- < MainNav . Item key = { `${ child . label } ` } >
303- { child . isFrontendRoute ? (
304- < NavLink
305- to = { child . url || '' }
306- exact
307- activeClassName = "is-active"
308- >
309- { child . label }
310- </ NavLink >
311- ) : (
312- < Typography . Link href = { child . url } >
313- { child . label }
314- </ Typography . Link >
315- ) }
316- </ MainNav . Item >
317- ) ;
318- }
319- return null ;
320- } ) }
321- </ StyledSubMenu >
322- ) ;
258+
259+ const childItems : MenuItem [ ] = [ ] ;
260+ childs ?. forEach ( ( child : MenuObjectChildProps | string , index1 : number ) => {
261+ if ( typeof child === 'string' && child === '-' && label !== 'Data' ) {
262+ childItems . push ( { type : 'divider' , key : `divider-${ index1 } ` } ) ;
263+ } else if ( typeof child !== 'string' ) {
264+ childItems . push ( {
265+ key : `${ child . label } ` ,
266+ label : child . isFrontendRoute ? (
267+ < NavLink to = { child . url || '' } exact activeClassName = "is-active" >
268+ { child . label }
269+ </ NavLink >
270+ ) : (
271+ < Typography . Link href = { child . url } > { child . label } </ Typography . Link >
272+ ) ,
273+ } ) ;
274+ }
275+ } ) ;
276+
277+ return {
278+ key : label ,
279+ label,
280+ icon : < Icons . DownOutlined iconSize = "xs" /> ,
281+ popupOffset : NAVBAR_MENU_POPUP_OFFSET ,
282+ children : childItems ,
283+ } ;
323284 } ;
324285 const renderBrand = ( ) => {
325286 let link ;
326287 if ( theme . brandLogoUrl ) {
327288 link = (
328289 < StyledBrandWrapper margin = { theme . brandLogoMargin } >
329290 < StyledBrandLink href = { theme . brandLogoHref } >
330- < Image
291+ < StyledImage
331292 preview = { false }
332293 src = { theme . brandLogoUrl }
333294 alt = { theme . brandLogoAlt || 'Apache Superset' }
@@ -342,7 +303,7 @@ export function Menu({
342303 // Kept as is for backwards compatibility with the old theme system / superset_config.py
343304 link = (
344305 < GenericLink className = "navbar-brand" to = { brand . path } >
345- < Image preview = { false } src = { brand . icon } alt = { brand . alt } />
306+ < StyledImage preview = { false } src = { brand . icon } alt = { brand . alt } />
346307 </ GenericLink >
347308 ) ;
348309 } else {
@@ -352,7 +313,7 @@ export function Menu({
352313 href = { brand . path }
353314 tabIndex = { - 1 }
354315 >
355- < Image preview = { false } src = { brand . icon } alt = { brand . alt } />
316+ < StyledImage preview = { false } src = { brand . icon } alt = { brand . alt } />
356317 </ Typography . Link >
357318 ) ;
358319 }
@@ -377,15 +338,13 @@ export function Menu({
377338 </ StyledBrandText >
378339 ) }
379340 < StyledMainNav
380- mode = { showMenu }
341+ mode = "horizontal"
381342 data-test = "navbar-top"
382343 className = "main-nav"
383344 selectedKeys = { activeTabs }
384345 disabledOverflow
385- >
386- { menu . map ( ( item , index ) => {
346+ items = { menu . map ( item => {
387347 const props = {
388- index,
389348 ...item ,
390349 isFrontendRoute : isFrontendRoute ( item . url ) ,
391350 childs : item . childs ?. map ( c => {
@@ -400,9 +359,9 @@ export function Menu({
400359 } ) ,
401360 } ;
402361
403- return renderSubMenu ( props ) ;
362+ return buildMenuItem ( props ) ;
404363 } ) }
405- </ StyledMainNav >
364+ / >
406365 </ StyledCol >
407366 < Col md = { 8 } xs = { 24 } >
408367 < RightMenu
0 commit comments