diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index 44e60356a8d..6f33a446753 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -59,7 +59,7 @@ import { } from 'src/dashboard/util/constants'; import FilterBar from 'src/dashboard/components/nativeFilters/FilterBar'; import { useUiConfig } from 'src/components/UiConfigContext'; -import { useIsMobile } from 'src/hooks/useIsMobile'; +import { isMobileConsumptionEnabled, useIsMobile } from 'src/hooks/useIsMobile'; import ResizableSidebar from 'src/components/ResizableSidebar'; import { BUILDER_SIDEPANEL_WIDTH, @@ -102,6 +102,19 @@ const StyledHeader = styled.div<{ filterBarWidth: number }>` z-index: 99; max-width: calc(100vw - ${filterBarWidth}px); + /* Mobile consumption mode: let the dashboard title scroll away and keep + only the tab bar sticky. A pinned title would sit underneath the + higher-z sticky tabs, leaving its bottom edge (kebab button) peeking + out below the tab bar. */ + ${ + isMobileConsumptionEnabled() && + css` + @media (max-width: ${theme.screenSMMax}px) { + position: relative; + } + ` + } + .empty-droptarget { min-height: ${theme.sizeUnit * 4}px; } @@ -143,8 +156,9 @@ const DashboardContentWrapper = styled.div` & .dashboard-component-tabs { box-shadow: 0 ${theme.sizeUnit}px ${theme.sizeUnit}px 0 ${addAlpha(theme.colorBorderSecondary, 0.1)}; - padding-left: ${theme.sizeUnit * - 2}px; /* note this is added to tab-level padding, to match header */ + padding-left: ${ + theme.sizeUnit * 2 + }px; /* note this is added to tab-level padding, to match header */ } .dropdown-toggle.btn.btn-primary .caret { @@ -297,12 +311,14 @@ const StyledDashboardContent = styled.div<{ margin: ${theme.sizeUnit * 4}px; margin-left: ${marginLeft}px; - ${editMode && - ` + ${ + editMode && + ` max-width: calc(100% - ${ BUILDER_SIDEPANEL_WIDTH + theme.sizeUnit * 16 }px); - `} + ` + } /* this is the ParentSize wrapper */ & > div:first-of-type { @@ -339,8 +355,10 @@ const StyledDashboardContent = styled.div<{ } &.fade-out { - box-shadow: ${theme.dashboardTileBoxShadow ?? - `0 0 0 1px ${addAlpha(theme.colorBorder, 0.5)}`}; + box-shadow: ${ + theme.dashboardTileBoxShadow ?? + `0 0 0 1px ${addAlpha(theme.colorBorder, 0.5)}` + }; } & .missing-chart-container { diff --git a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx index 38dba59f45c..b62e889ef52 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx @@ -93,6 +93,36 @@ const StyledTabsContainer = styled.div<{ isDragging?: boolean }>` top: 0; z-index: 100; background-color: ${theme.colorBgContainer}; + /* breathing room between the tab bar and the first card; padding + (not margin) so the gap is part of the opaque sticky bar */ + padding-bottom: ${theme.sizeUnit * 2}px; + } + + /* Scrollability affordance: fade the clipped edge with a + theme-colored gradient. antd toggles the ping classes when tabs + overflow on that side; restyle its shadow elements as gradients, + which read much better than the default shadows on dark themes. */ + .ant-tabs-nav-wrap:before, + .ant-tabs-nav-wrap:after { + width: ${theme.sizeUnit * 10}px; + box-shadow: none !important; + pointer-events: none; + } + .ant-tabs-nav-wrap-ping-right:after { + background: linear-gradient( + to right, + transparent, + ${theme.colorBgContainer} + ); + opacity: 1; + } + .ant-tabs-nav-wrap-ping-left:before { + background: linear-gradient( + to left, + transparent, + ${theme.colorBgContainer} + ); + opacity: 1; } /* Swipeable tab bar instead of the overflow dropdown: the "more" diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx index 755969a6f59..a90362d7e2c 100644 --- a/superset-frontend/src/features/home/RightMenu.tsx +++ b/superset-frontend/src/features/home/RightMenu.tsx @@ -107,10 +107,12 @@ const StyledMenuItem = styled.div<{ disabled?: boolean }>` color: ${!disabled && theme.colorPrimary}; cursor: ${!disabled ? 'pointer' : 'not-allowed'}; } - ${disabled && - css` - color: ${theme.colorTextDisabled}; - `} + ${ + disabled && + css` + color: ${theme.colorTextDisabled}; + ` + } `} `; @@ -794,6 +796,21 @@ const RightMenu = ({ selectable={false} onClick={info => { handleMenuSelection(info); + // The reused desktop items navigate via anchors that only + // span their label text, but the drawer's tap target is the + // full menu row — navigate explicitly so row taps work. + if (info.key === 'info' && navbarRight.user_info_url) { + window.location.assign( + ensureAppRoot(navbarRight.user_info_url), + ); + return; + } + if (info.key === 'logout' && navbarRight.user_logout_url) { + window.location.assign( + ensureAppRoot(navbarRight.user_logout_url), + ); + return; + } setMobileMenuOpen(false); }} items={mobileMenuItems}