mirror of
https://github.com/apache/superset.git
synced 2026-07-18 12:45:44 +00:00
fix(mobile): tab bar scroll affordance, sticky behavior, spacing; drawer nav row taps
- Fade the clipped edge of the swipeable tab bar with a theme-colored gradient (restyling antd's ping-edge shadow elements, which are hard to see on dark themes) so scrollability is visible - Let the dashboard title header scroll away on mobile instead of pinning underneath the higher-z sticky tab bar, where its bottom edge (kebab button) peeked out below the tabs - Add padding below the tab bar so the first card doesn't butt against it; padding rather than margin so the gap is part of the opaque sticky bar when stuck - Fix dead User Info / Logout taps in the mobile nav drawer: the reused desktop items navigate via anchors that only span their label text, but the drawer's tap target is the full row — navigate explicitly on row tap Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user