This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch mobile-dashboard-support in repository https://gitbox.apache.org/repos/asf/superset.git
commit 4989fddc83fcdb95a6af760ed391c5cb9d959454 Author: Evan Rusackas <[email protected]> AuthorDate: Thu Jan 8 15:35:39 2026 -0800 feat(dashboard): add mobile-friendly dashboard consumption mode - Filter global nav to show only Dashboards on mobile (<768px) - Stack dashboard charts vertically instead of row layout on mobile - Make dashboard tabs sticky for easier navigation on mobile - Hide native filters on mobile for simplified viewing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]> --- .../DashboardBuilder/DashboardBuilder.tsx | 5 +-- .../components/gridComponents/Row/Row.tsx | 9 +++++ .../gridComponents/TabsRenderer/TabsRenderer.tsx | 10 ++++++ superset-frontend/src/features/home/Menu.tsx | 38 ++++++++++++---------- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index 38f0dcac2b..0afe5222e5 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -22,7 +22,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { addAlpha, JsonObject, t, useElementOnScreen } from '@superset-ui/core'; import { css, styled, useTheme } from '@apache-superset/core/ui'; import { useDispatch, useSelector } from 'react-redux'; -import { EmptyState, Loading } from '@superset-ui/core/components'; +import { EmptyState, Grid, Loading } from '@superset-ui/core/components'; import { ErrorBoundary, BasicErrorAlert } from 'src/components'; import BuilderComponentPane from 'src/dashboard/components/BuilderComponentPane'; import DashboardHeader from 'src/dashboard/components/Header'; @@ -363,6 +363,7 @@ const DashboardBuilder = () => { const dispatch = useDispatch(); const uiConfig = useUiConfig(); const theme = useTheme(); + const { md: isNotMobile } = Grid.useBreakpoint(); const dashboardId = useSelector<RootState, string>( ({ dashboardInfo }) => `${dashboardInfo.id}`, @@ -459,7 +460,7 @@ const DashboardBuilder = () => { ELEMENT_ON_SCREEN_OPTIONS, ); - const showFilterBar = !editMode && nativeFiltersEnabled; + const showFilterBar = isNotMobile && !editMode && nativeFiltersEnabled; const offset = FILTER_BAR_HEADER_HEIGHT + diff --git a/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx b/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx index e4a6915ba1..4c7b37efe3 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx @@ -124,6 +124,15 @@ const GridRow = styled.div<{ editMode: boolean }>` &.grid-row--empty { min-height: ${theme.sizeUnit * 25}px; } + + @media (max-width: 767px) { + flex-direction: column; + + & > :not(.hover-menu) { + width: 100% !important; + margin-right: 0 !important; + } + } `} `; diff --git a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx index 906150a5f3..a51195bb56 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx @@ -81,6 +81,16 @@ const StyledTabsContainer = styled.div<{ isDragging?: boolean }>` display: none !important; } `} + + /* Sticky tabs on mobile */ + @media (max-width: 767px) { + .ant-tabs-nav { + position: sticky; + top: 0; + z-index: 100; + background-color: ${({ theme }) => theme.colorBgContainer}; + } + } `; export interface TabItem { diff --git a/superset-frontend/src/features/home/Menu.tsx b/superset-frontend/src/features/home/Menu.tsx index 9d8c35341b..feaabd3e4f 100644 --- a/superset-frontend/src/features/home/Menu.tsx +++ b/superset-frontend/src/features/home/Menu.tsx @@ -343,24 +343,26 @@ export function Menu({ className="main-nav" selectedKeys={activeTabs} disabledOverflow - items={menu.map(item => { - const props = { - ...item, - isFrontendRoute: isFrontendRoute(item.url), - childs: item.childs?.map(c => { - if (typeof c === 'string') { - return c; - } - - return { - ...c, - isFrontendRoute: isFrontendRoute(c.url), - }; - }), - }; - - return buildMenuItem(props); - })} + items={menu + .filter(item => screens.md || item.label === 'Dashboards') + .map(item => { + const props = { + ...item, + isFrontendRoute: isFrontendRoute(item.url), + childs: item.childs?.map(c => { + if (typeof c === 'string') { + return c; + } + + return { + ...c, + isFrontendRoute: isFrontendRoute(c.url), + }; + }), + }; + + return buildMenuItem(props); + })} /> </StyledCol> <Col md={8} xs={24}>
