From fc0c63b0a3e04e8bd6af1189529dc5e04f6da11a Mon Sep 17 00:00:00 2001 From: Superset Dev Date: Mon, 20 Jul 2026 08:54:16 -0700 Subject: [PATCH] feat(mobile): consumption-only mobile experience behind MOBILE_CONSUMPTION_MODE Adds an opt-in, consumption-only mobile experience (feature flag MOBILE_CONSUMPTION_MODE, default off, @lifecycle: development): - Dashboards: charts stacked full-width with real plugin dimensions (ChartHolder reports full column count on mobile; heights capped to the viewport minus chrome), sticky swipeable tab bars with gradient overflow affordances, filter bar in a drawer (FilterBar mobileMode), compact header (title scrolls away; edit/publish/fave/refresh controls hidden; dashboard info moved into the kebab menu) - Dashboard list: forced card view, full-width cards, search/filters and sort in a drawer (single FilterControls instance) - Home: dashboards-only Recents, compact empty states, desktop-only sections hidden - Navigation: hamburger drawer (dashboards, theme/language, user info/logout with row-tap navigation) - Route guarding: routes declare mobileSupported in routes.tsx; everything else renders a MobileUnsupported screen; viewport growth unblocks automatically (useIsMobile subscribes to matchMedia only when the flag is on, so flag-off deployments have zero render delta) - Serves a viewport meta tag (flag-gated) so mobile browsers lay out at device width instead of the ~980px legacy viewport; exposes is_feature_enabled to Jinja via the common context processor - User docs (using-superset/mobile-experience.mdx) with a Playwright screenshot generator following the docs:screenshots pattern - Docker dev config enables the flag; jest + Playwright coverage throughout Squashed from the iterative mobile-dashboard-support history (preserved at backup/mobile-pre-rebase-2). Co-Authored-By: Claude Fable 5 --- .github/workflows/superset-playwright.yml | 11 + docker/pythonpath_dev/superset_config.py | 1 + .../docs/using-superset/mobile-experience.mdx | 89 +++++ docs/static/feature-flags.json | 6 + .../screenshots/mobile/mobile_dashboard.jpg | Bin 0 -> 68479 bytes .../mobile/mobile_dashboard_list.jpg | Bin 0 -> 82502 bytes .../mobile/mobile_filter_drawer.jpg | Bin 0 -> 58074 bytes .../img/screenshots/mobile/mobile_home.jpg | Bin 0 -> 35338 bytes .../screenshots/mobile/mobile_nav_drawer.jpg | Bin 0 -> 35385 bytes .../screenshots/mobile/mobile_unsupported.jpg | Bin 0 -> 42668 bytes .../components/DynamicEditableTitle/index.tsx | 16 + .../PageHeaderWithActions/index.tsx | 18 + .../src/utils/featureFlags.ts | 1 + superset-frontend/playwright.config.ts | 18 + .../docs/mobile-screenshots.spec.ts | 167 +++++++++ .../tests/mobile/mobile-dashboard.spec.ts | 325 ++++++++++++++++++ .../tests/mobile/mobile-navigation.spec.ts | 192 +++++++++++ .../spec/helpers/mobileTestUtils.ts | 150 ++++++++ .../components/ListView/CardCollection.tsx | 13 + .../src/components/ListView/ListView.test.tsx | 224 ++++++++++++ .../src/components/ListView/ListView.tsx | 97 +++++- .../src/components/ListView/utils.ts | 13 +- .../MobileRouteGuard.test.tsx | 64 ++++ .../src/components/MobileRouteGuard/index.tsx | 52 +++ .../DashboardBuilder.test.tsx | 97 ++++++ .../DashboardBuilder/DashboardBuilder.tsx | 69 +++- .../DashboardBuilder/DashboardWrapper.tsx | 17 + .../components/DashboardBuilder/state.ts | 1 + .../components/Header/Header.test.tsx | 9 + .../src/dashboard/components/Header/index.tsx | 48 ++- .../src/dashboard/components/Header/types.ts | 4 + .../Header/useHeaderActionsDropdownMenu.tsx | 73 +++- .../components/SliceHeader/index.tsx | 7 +- .../ChartHolder/ChartHolder.tsx | 43 ++- .../components/gridComponents/Row/Row.tsx | 22 ++ .../TabsRenderer/TabsRenderer.tsx | 55 ++- .../nativeFilters/FilterBar/Vertical.tsx | 74 ++-- .../nativeFilters/FilterBar/index.tsx | 1 + .../nativeFilters/FilterBar/types.ts | 5 + .../resizable/ResizableContainer.tsx | 16 + .../src/features/dashboards/DashboardCard.tsx | 12 +- .../src/features/home/ActivityTable.tsx | 28 +- .../src/features/home/EmptyState.tsx | 10 +- superset-frontend/src/features/home/Menu.tsx | 71 ++-- .../src/features/home/RightMenu.test.tsx | 9 + .../src/features/home/RightMenu.tsx | 196 ++++++++--- .../src/features/home/SubMenu.test.tsx | 32 ++ .../src/features/home/SubMenu.tsx | 66 +++- superset-frontend/src/features/home/types.ts | 1 + superset-frontend/src/hooks/useIsMobile.ts | 71 ++++ .../DashboardList/DashboardList.test.tsx | 9 + .../src/pages/DashboardList/index.tsx | 33 +- .../src/pages/Home/Home.mobile.test.tsx | 179 ++++++++++ .../src/pages/Home/Home.test.tsx | 9 + superset-frontend/src/pages/Home/index.tsx | 43 ++- .../MobileUnsupported.test.tsx | 95 +++++ .../src/pages/MobileUnsupported/index.tsx | 143 ++++++++ superset-frontend/src/views/App.tsx | 37 +- superset-frontend/src/views/CRUD/utils.tsx | 12 + superset-frontend/src/views/routes.tsx | 36 +- superset/config.py | 5 + superset/initialization/__init__.py | 6 +- superset/templates/superset/spa.html | 7 + 63 files changed, 2915 insertions(+), 193 deletions(-) create mode 100644 docs/docs/using-superset/mobile-experience.mdx create mode 100644 docs/static/img/screenshots/mobile/mobile_dashboard.jpg create mode 100644 docs/static/img/screenshots/mobile/mobile_dashboard_list.jpg create mode 100644 docs/static/img/screenshots/mobile/mobile_filter_drawer.jpg create mode 100644 docs/static/img/screenshots/mobile/mobile_home.jpg create mode 100644 docs/static/img/screenshots/mobile/mobile_nav_drawer.jpg create mode 100644 docs/static/img/screenshots/mobile/mobile_unsupported.jpg create mode 100644 superset-frontend/playwright/generators/docs/mobile-screenshots.spec.ts create mode 100644 superset-frontend/playwright/tests/mobile/mobile-dashboard.spec.ts create mode 100644 superset-frontend/playwright/tests/mobile/mobile-navigation.spec.ts create mode 100644 superset-frontend/spec/helpers/mobileTestUtils.ts create mode 100644 superset-frontend/src/components/MobileRouteGuard/MobileRouteGuard.test.tsx create mode 100644 superset-frontend/src/components/MobileRouteGuard/index.tsx create mode 100644 superset-frontend/src/hooks/useIsMobile.ts create mode 100644 superset-frontend/src/pages/Home/Home.mobile.test.tsx create mode 100644 superset-frontend/src/pages/MobileUnsupported/MobileUnsupported.test.tsx create mode 100644 superset-frontend/src/pages/MobileUnsupported/index.tsx diff --git a/.github/workflows/superset-playwright.yml b/.github/workflows/superset-playwright.yml index fcdeff265a4..6aa5ea5b226 100644 --- a/.github/workflows/superset-playwright.yml +++ b/.github/workflows/superset-playwright.yml @@ -155,6 +155,17 @@ jobs: INCLUDE_EMBEDDED: "true" with: run: playwright-run "${{ matrix.app_root }}" embedded + - name: Run Playwright (Mobile Tests) + uses: ./.github/actions/cached-dependencies + env: + NODE_OPTIONS: "--max-old-space-size=4096" + # Scoped to this step for the same reason as the embedded flags + # above: the mobile consumption mode should not alter Flask's + # configuration for the required desktop test steps. + SUPERSET_FEATURE_MOBILE_CONSUMPTION_MODE: "true" + INCLUDE_MOBILE: "true" + with: + run: playwright-run "${{ matrix.app_root }}" mobile/ - name: Set safe app root if: failure() id: set-safe-app-root diff --git a/docker/pythonpath_dev/superset_config.py b/docker/pythonpath_dev/superset_config.py index bb76329eb91..68b0c08bd78 100644 --- a/docker/pythonpath_dev/superset_config.py +++ b/docker/pythonpath_dev/superset_config.py @@ -118,6 +118,7 @@ FEATURE_FLAGS = { "ALERT_REPORTS": True, "DATASET_FOLDERS": True, "ENABLE_EXTENSIONS": True, + "MOBILE_CONSUMPTION_MODE": True, "SEMANTIC_LAYERS": True, } EXTENSIONS_PATH = "/app/docker/extensions" diff --git a/docs/docs/using-superset/mobile-experience.mdx b/docs/docs/using-superset/mobile-experience.mdx new file mode 100644 index 00000000000..e62a9adb85f --- /dev/null +++ b/docs/docs/using-superset/mobile-experience.mdx @@ -0,0 +1,89 @@ +--- +title: Mobile Experience +sidebar_position: 7 +version: 1 +--- + +import useBaseUrl from "@docusaurus/useBaseUrl"; + +# Mobile Experience + +Superset ships an optional, consumption-only mobile experience for viewing +dashboards on phones and other small screens. When enabled, screens below +768px wide get a layout built for touch: dashboards render their charts +stacked full-width, navigation collapses into a drawer, and dashboard +filters open in a slide-out panel. + +The mobile experience is **read-only by design**. It is aimed at consumers +of analytics — people checking a dashboard from a phone — not at dashboard +authors. Authoring surfaces (chart builder, SQL Lab, dataset management, +and administrative screens) remain desktop-only. + +## Enabling the mobile experience + +The mobile experience is gated behind the `MOBILE_CONSUMPTION_MODE` feature +flag, which is off by default. Enable it in your `superset_config.py`: + +```python +FEATURE_FLAGS = { + "MOBILE_CONSUMPTION_MODE": True, +} +``` + +With the flag disabled, Superset renders identically at every screen size, +and phones display the desktop layout scaled down (the pre-existing +behavior). The flag also controls whether Superset serves a viewport meta +tag, which is required for mobile browsers to apply the responsive layout +at their native width. + +## What works on mobile + +| Area | Mobile behavior | +| --- | --- | +| **Dashboards** | Charts stack vertically at full width, sized to the screen. Tab bars are sticky and swipeable. Native filters open in a drawer via the filter icon in the header. | +| **Dashboard list** | Card view with full-width cards; search and filters open in a drawer. | +| **Home** | Recents (dashboards only) and dashboard cards; desktop-only sections are hidden. | +| **Navigation** | A hamburger menu opens a drawer with links to dashboards, theme and language selection, and user info/logout. | + +
+ A dashboard on mobile with charts stacked full width + The dashboard filter drawer on mobile + The dashboard list in card view on mobile +
+ +
+ The Superset home page on mobile + The mobile navigation drawer + The screen shown for views that are not available on mobile +
+ +## What doesn't work on mobile + +Everything not listed above shows a friendly "This view isn't available on +mobile" screen with shortcuts back to dashboards and the home page. That +includes: + +- Chart builder (Explore) and chart-level links — chart titles on + dashboards are plain text on mobile, and chart entries are filtered out + of the home page's Recents feed +- SQL Lab and query history +- Creating or editing dashboards, charts, datasets, and databases +- List views other than dashboards (charts, datasets, saved queries, etc.) +- Administrative and settings screens + +Editing controls are also removed from the screens that *are* supported: +the dashboard header hides the edit, publish, and favorite controls, and +dashboard/chart kebab menus are reduced to view-oriented actions. + +If a device crosses the 768px threshold — for example, rotating a tablet +to landscape or resizing a window — the full desktop experience becomes +available immediately. + +## Notes for operators + +- The flag is deployment-wide; there is no per-role or per-user targeting. +- Dashboard permalinks and links shared from desktop resolve normally on + mobile as long as they point at dashboards. +- Embedded dashboards are unaffected: the embedded SDK controls its own + layout, and the viewport meta tag is only interpreted by the top-level + page. diff --git a/docs/static/feature-flags.json b/docs/static/feature-flags.json index 1cf3c7fd0dd..c05660f7cb2 100644 --- a/docs/static/feature-flags.json +++ b/docs/static/feature-flags.json @@ -69,6 +69,12 @@ "lifecycle": "development", "description": "Enable Matrixify feature for matrix-style chart layouts" }, + { + "name": "MOBILE_CONSUMPTION_MODE", + "default": false, + "lifecycle": "development", + "description": "Serve a consumption-only mobile experience (dashboards, dashboard list, and home page) on small screens; other views show a \"not supported on mobile\" screen. Authoring features are hidden on mobile when enabled." + }, { "name": "OPTIMIZE_SQL", "default": false, diff --git a/docs/static/img/screenshots/mobile/mobile_dashboard.jpg b/docs/static/img/screenshots/mobile/mobile_dashboard.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dda0c671d62e25eb8e95aefc3ba1f6fb8653bced GIT binary patch literal 68479 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%0Dx>-$q`Q!k}*%Y zpW3ESv-XS!I~(cxdN953Bg-}au>XHRSC1a^Zs76jmx?vBcCo{%cf_Eg1I-3VhW#2@ z8Iu^GB_6IHq^c*%4D2OZ+?*oRApG5i+tqv&)GfmaJ(iNwV(=jJ3msWUN3p-riPb?6xe3c&%E& zr>jx3o;>C;h`bE5GcdEFGW9)y^`W0@+`Vw)F2yGH38DAD?%b{kT^+hf4T=_etuhoI zPD&1-&#kVh47Q~l+Ik4}8y0OuOK$YcGU!_U#>P*yiuet z8613j220$u*RpX2V3Fod{ahAcN=r(y7qNKH;Lgz1H^|BC$5G4LVve}>`~}nd?^k@xh%Z_Muk$hX-{{<%ue~M{fJGv!7zWNrX50}j1TV! zYcmR=4z3JtpubpO-?Up6tL)WUL5u3{y-wzNRnr5l{4(a83Mra|TT~zzelE+C(qrVQVtd6=c!$x&j+? zw%d|_w&(bHMM5_0Xi&I-$A?A@@nW7c5b0mQ!MsDh6;o99S&a>cK6?d0TP=*U9n(tN zse2y%ar^uI(p_!dOk1Ct-c}1W&YX2 z^V{vyIT4+1Zk=JN9V1hTub#rUy^L)|`~=XEzVAyw47AKLM=mxiY5oX&c3OLH_;Qwv+hv3UjsvprNl;{0J#NIhk(cYS}JLrv^OQ|SH_uy1Hq*r%bOG~DA zTx~usoZ^*26A%cX8(=f}@0jry#O-+?4DIvQ0Bg6$lo)YvKjvKy)#0Pyykd7VpI z6{TQpQ@1CsDJsrDg?B@x5JtlLl3wVhXlF&0mzrkxd8+ur%CD9zZCTCqYGAToM%ZQK zMxO)EN)GKb^Qn1+2$s)Y!WcYRrD$W8sfo(q? zmb&H}9v#ke<~&K?DoA_enyy8yMm!C^lHl9`(`>OYjo9h?AN$Z%)@>O7~A+) zF$1`WX9KwK_aB;p+%2wJjQ{|ZDQNr42nN8XJ8Z?WJZ!}P(seI<0M8OW@U-La^=LVU zsoQ!laufarVs}%i;lis>c?Ixj5)GlD zXE@p}RH&5`(y?Fnij5#*E2w07Os>u)`IP0fH(Y{LS<5aTWT2&;UTQuljTRt~<}jQ{ znvHXVr!vP_dN{$MonA|d81XRVpIT}cW$9#ZfGI)EyBaXnhaZKUUVC}~ihnZcu@?s4 zsN6!iWwojq5P@eU4lBm~5G$EaT|MPABKghOjW-UB$|jT;2VRz(u7ssX5$U1n5z|kq zf{Y-S)w3U@6`$N1uf(&rZlfO={rGv_k`!1HaB?@0&_qrHT)-wEuo_)@nTy(L+xc1> z;uR`NLZP*O=|5&fMx>;GnG`fOL>N`OJaRQsY2hofhx4;f`c+@OCglc&fG0QZ)|kjT z=D6F*#agaq!m!qvKfMa$wn&_tH4E+RkXr;;N`;H+*M=WW}qt1gZZx$z4m|Omxb?Iw9rLcB6AkcrG;?X^OWv zr+$+gmolzAzPm;bxfnq854je#)9T`FrHg|WRKjnqk5!9gn$*kXErzwEsnx|@RqMLu zG%gi<3YY&>KZT0*snXnQc|3Fbnp&gL9)DyVJz?PhbZ>;IVQ=bAzqTZJ%u#jV%WX+t z@n9m~yS3QYg8C*- zE|zD50Ji);5&&emxoa$W;V$ggaBfMk6Cd!*fNzR;JXEskFHzM`aLY!L=AS^9&H>UV5DZ!HY>*&m{Lfw@<(&$D_= zPunF>>aLS_6ID%?v=Topq&b>Il=1)?%I#w}*t_`QD_gRA48C=%xL1e3B*RqR+pP_T zans>pv(ro=$-NcHbM8jf5~St{;yCu2)m7d!10^%qcvOWIZ(6^C`~j#Y8#%`q!q1zN zIR{e;Zu+Z^g?YWbXSOlfG4ON4Xb!o+B!T%JQgGZIVSYj2^BOfTXrIF~eqY|qob+z$ z0HlQv{3h8-@gf3daPsdr^k|2}D6#T5#dlFBAXOvLpSCu9$t7x`kG2u{U3V}8PJk;) zi;?>B%y>kX%%=e3eh9?KtLpHh?0P-O0f;{^ikL7~Q0Cgc^Mi&IZuRlD*<@qInvc9c z8PQYc1GTY33N5|&JlnKA!T*egBsx;|qWh5{Ww7Eda@9|78DI0`sWd-=YP0@;MVz+m zDL(VK>4KA&aW+fh`Ya-k3nbtcWSsXPHWOkNHIg&v{Q6!%|8eaj6arFoM>kBU(7He5 zllNe5nghERkC!)8%}r!3J9+G4LG+Wu!`97Yj?SR>n5jkmb(oSO#ZhfEQ;*6Fk$KlI z7MFo^+>C{Nb=Z^m>hU2w@5!A^YInC_Ty$JoDqnjEjw`)4?wqgCYPVs#XA(XA5@~V1 zkq!w`)PAU6cH8m@k@Ar_n-xg2QFcSVYaMXa`3}Oy9Uh(>d%6WsU!532MLQ+xY&Vw) zmkhAVlT~3W7KE(*Jqir?B|wYu{i?-$0c{xF=n7~t6i*xaLXm(0LYYi%?}~9^V@r=nfeQQFMgqxK+C3%v z3MljLpLI$MxPLGk8Rki=YntAnAMYaLYZA9}_fAD^)Rg}S_5KLKJ z?~S%FHO%^|n$r&>7xt8^91lPnX9sV{z`f;?eGKPwuBmkhptPTUgGYTAe0-sXf3e>G zrsaNYl4>GLrbnqooub2}M&@_jSi#X4^=dHy|K0Hm{#z<-BU@YX^4(ergqgqScL4Iv zm2B4QvZa<|g3$FT{SAcR60!c@5a3F0^bbG^h39v!J}>N*8%?%zby@T{yf>c}#G~&; z%8!>or?+PVSxWp)TRsmhzs9w#qPl@O03|W+P8Yd2mU?d>epam!e!3H`eoXl$ag+Xn zEJfi{DOqk=zKA8zGOn>ghtn-cx#cK`w`w>VW?aE880!x+)!w0>SR&L%7}>=u^K@m@LZ2cY6SEBElb1Ob5$ouo7> zF=YSSs|TeaQ{Sl3tN;X@pXD42$HaM5wBAkC)~+;d(E&CM-7PTGG-zIKOkpEz-#OaossjMKe*l($h5)Gh2C%)k3jn%-m0vsn<~|Jw zLka-oerT&8^wH7f5wJ8A1<>Ia0cp7kAjALnFRb4*Pd&Z&JsTGY^z45k4D%rlul4>; zjhNq_S|`6wMQ|=j-T!A>t3RLi`>_yf8gzO9R>+E3l%N zEKhyfK7=Y)s1f?zDa^Yvg591#%jx(03gn;_8Z?VdOad z#!L0*=eK{oBx^Gm!hwthfiq1Ya7{G@0B{{ytSubWsfjHSk999vNI+8W=8$$axHt{Q${z~|(OWyxA82%E2e-r~j*L>_$zlhTy3$!4Q?jxQM zW7L7@I2#@56HDsPF?64Xe)r+m+3FCV(fi70e{-yDDGrldEi7mQ7*M_cS3B1pM33fb zPIYiD>A!FNuTt&)>+|ftp7YNdJs!%pUfpLeW=IP6pSC2<6KKl9c#aO6X#q##kW2ax zi%yo0ixMC#iQ4acs@sa7LjIWpjhg+Y2O#lD!0*1q)=z~GyiYtXVB89Q^c(|ZY4p)7 z(O<)$Y6@&2CfGn^z}Mxe!^A-kh2d##g!#f8hDgT_nY6`d+SpFF)Iz_#zxVa^-my$w$2#`%T`B&T)m=IeA65H~NcqPt^s#qX zl~A(K%3;6ny}xFyt?Gv7#X)$(>+*Z$^t-K}&B;f&739Bqm4+)T$ue~9)D}-Lxz>A8 z@h(<;Ii&!;K}xpfEw%FGfXb2`gHQT5(V?waR04us3RS`cC-dXVk{z34NI4nNIgxX> z@Lf=NpDRxPD?&dhKwt`>pd;Zk9PfKvpLvm~e-0({bitJ~!2gr3h5MQL=UxcPCZVON z0w5yK5H)|A)yqScx?y1;1%j_r_Qnc^C>IKdn14-8*5QVg+%~_RMRtJtFkV42GP2Q1Ti~h4#Vt1E zHQ>(dzQ@by^Ckx6QPk}dkokU3fM}G1=P<@RUIqpghq35qS~k7IF^=|ojXIakpHX7DpE0SX5oi))_S&+9*#{5%VCej#{k z?L{WX_?538;6I@Xbn}?{Q@-8Ydq{EYy1@Ja$mN7Gta*)FwWJq0A~sF((VYAKuI7}s z)HK3sKdZeKH1gDkxrJ$1b0gRG_kQSAn&WXuooyl~aKPkjtZ&udaU6yTTU90II9~vG zc@?y8u6J~kGQiY;-e;3GCt^NzKG_%N+%*2VzEtO)@Um8pSm{jNP>w(_DW@BXG_o?_ zGvLsKoc$`|n#h?sG&K(&$(1Z}_Bu3D1o);+{yxxuP9XNHY=$Wfl@CRXte^>okK%$Z z2GgT+T0(B~X?EumS~q zJTL^nHk@CV4IhsaDC{Pj{%9p*UJO~4@F@fMdfV&V2~@lrr^Ht%bJ?mbBAt9i*;!sU zRj>y(ck?8N+d_>7J<4udL0(Rfz7RcX1RQa1*F?pSlnZkM`BGr%}N5G5<@ zh>>$d_Q~n5RD=>j)j2PUDP_(J%~IAAiIo`8wcwg2(wYXjR8Zkf0<@)8lcaB)ONafA zvhsYod^e4w(gu7xE`wWv+8GJa^eV+F`iAPPJ}Op~5_r@1BI10Rw^!p_f(SN5vH$@^ zN{h~reojAju3+=JMXKdb?dLAkj9n)7i(xLthzJD26e%`6bmeoPCZ?;8lTUE86G>~z z{)6tQ`6X^P;-NU~kl0h9mum0LT%&is@-hWLm|prDQZDuRO>-xH_{r|6w231PTwDl`<09az zxY(y^)#y+o3-GJPPo;AYj}JOF$P5+SOM5%ZNQ0!dtljGOrEC<>;scW8jf|HMi+>^3 zd_X!gnufT;N%w-iM030``7yZSdPPy@P-^ytM;-EI78l>bsa#7h(|$-#mnwA`iy8}i z_@F4&kfX=+d`8c6h0*1t!Nh$i_ug$C>+sRfEaIcxPqwH z4N%C)Ybei$c+`BzUye&FeFVXEU^|eL0@E}_u)x<9H`Xbc9sJf*xd6k|u2>fn(5>8kW= zz_Ewa#sTQ`0cfeLR}z`Lpmy4N%E zS*R6aJI{R6Sedx3^k%tIrkjzEGas1luoP*Y6kyIcS&vFj>f!3RtM1(mF8T3{&b-)X zXq(_=le`2taIUs!4OaLmW2d?Dp7D;&1ULwpH@D*S41 zpIfGHb;1{t2uTT*{9+kycpWk-q`munFO%mTET?nSzb&!YB;Ha8*H&vT;l5x>+=({d zRo~P!zw%Y2r~ft%jE+yJ8s}Js&fC0`TT(Q76divCur}X3IRVR%D5J%LmnBfq1 z<&h~z&8J-!9gl{xAlc%C)y`RFevF6^R)FFGH$;jSGLAtiTXO>WV{EHs*KfR&U-P{6 zG$&F~zs1Kyc>DrUw!>>3oNV(ZhQ)F-G4s6ggmBx27xEoUD5VIjqA25qKwwFbHgX%@ zcfFeByLXS>7(0(7kqVJlMI#246lJ()3W+8Or;IXOIV0ABv&89j+??>+RiDKth!br4 zVlX*dGRM&16zN^7B1z!uMc#fW=c3Ljr6$E>g|qq^SVE>)w)av*U(4qfQeRi!Vl9dg z?pT(flO=({mY^)}3zhc|O%KUtfOAv@B zph`9e1sqA?q$BE&)=3%BNvw7lJ0DCwU0;W9_c2x}vi8MYOZ`YBw zVgmU#Q%!l{9q#!f(>AkwrJMs3jg{7Oj>J~Mf}guF;GiUM5YkslZ@`o9m~;QxVHuq2 zFb^zCX2{tzaU|**mg4S3gYeP>1jpNx+Kg_q1%b^QUmQMRR?t#Bj92JFsK#pHY^9kA zfhX4$z|CdM@TI%684APrQ*XpJy&wwy4&+1>o~JJ9ip13e&=0K`b4w$0_MQOq6nv(T zCcJg576FCZRD@`&R9FFUj&g;zO7ytRHHkqe)_ZX*950xf5*}HT0-$`muNQy0*H9UC za!3Xta*=A_mW}U7OH^#>7eV)DcFQ8BH1FUxFZ^UuamvR1NA`P`^TXe@Ca&3;MYnPe zCMQ+S5fqASRTS9LPMZ5CF8Ss$0v6QGi!v&_03I;E&xEgmiXwX+AIBd_zfd`WnqB2% zJ)B3V!0;&K$1BW3g zpVbjjyXLruJRcXAk@dBWXDj3+cm&R@v`i4n0lJuB7^$x>RAg^h~oc$lJR_Mu?KY0fBXz^D?NM zlh~X!qin@|$)D}>Kj1`8H-0FPSjqM_rcy8r(It)!tT+OO;6(Ue|KRNuQA~|LY;k!} z`Km5~<)OWUp19fAX^K7rs!u}}#>e+re0cZp>~L9Oa1H89U!tBtPwKL_WCA5x$!BP) zT^Mlu?OPH%QMp!~xqY@_O+h^5V)<**kZuB=heWq(p#hdKeZ*?Oi;iGWw`vl1PY1SY zvYpflvsnC8-n143C#GSNz@kJpHUygz0^xTI`d?kn{C?N*UuTaxHaXBgO<`0^qa8!; z|FPj?f<64WVl9PwV3ihiRpcywwL0n(4lxK}mtPkkk-#emO;m-ua&UCNj(utOuw-`@ z+&fm`eDb2Ee#H)wL0&MP{bO~1GX7^*YJal1e_HI&pSCFEPK))Fe}Nrj{a&lUK`)`0 zoJ@eQDOS&orMm?B&P>CgD$@x&Yi1RSm{FD@e*X}eMrka~oqCzP2-nV39AKf{A)Jw1Xy0DbPetD4iv;>7Z4R%(OG zEx{X-Se@@W^aWjRU+CzMkumX#mt6|mpyqIXsr$Cyt$xuFDuEhPHCh8{0h2>%V@PLt(|^ z8P%wjvz|9MN8M5{2BzfYt;4(I09x4--p6A;U$I>XFIVC5d8NtYIG`yc!AI4X2}eSG-BBMHm>0}y3@ zuuzbkZ7s`RckEf{4`vm62Oz7x;?0}y>Q}Z`mZG(hI!zk=ufK&w%aa42oQ8GVpcz#U zaZ-@zMqm zBhp3Nf9sLz@r-gC*Yeg&fm5_9)8Zv~D*>l16>50f@kUsMO-4au1xD^tphJa%s2UVb z59zLIP5R(?9rRQE2;Q-TG2(#h(bi+n_Tr|A$Fg60cH$!$o$uDvuWivp<}x`UqE!eM zBt*sSWxoXNLZJvvt67@ZHt4&8rn(bBCnPmW0G}_Y+Upiaskf_)u(fR^Qu#W^=e1HI zR+E{;lKY@SPfB+AhYoWam5bSrtGZ$r;vk?R7QG)QBT;((q*pnw$hodRWi2N9&M%pf z*P zZ&C*S3%s$27AJ!>r3{80)>1agZ4~1uUz?qy0LJ1mQx4kQi+;#L`r`Gummm;Z-}|9^ z7X)eCDQR>jDDB=y$Ff4LT=G!1JEzJQ=G&}G&vqvuI<mqrmw zC9dK{W#-}%PoCqdGWj$j>0Sdp@zKFvN8SyaQ{%t>Dn0|hjBHTv(r&AnTEBemzF=NL z(ao(3Eqz^chpw%@?r^cj8Tng=>F<5%ZkgFZ<&AWaEc}#41ac?!mo?XARKxESm5V<- zJ-W(LciiPpFoFD_WrGC1MFY>^11b)^nBYi%xj%U9hy1-`%oY^Lc*3hRs1FONV<_>O zKe+eVvCL3gv~cLrW8Eqr#&B5pfPflEE2IvzKeLkwz0#pDx{y~r}@J?OP^!>xLsjR(t|ZRMB9k`S(9kp8LEwH|JECT{E&!Ku>VZ$bT@Q+>ux>ghN$; z9qNaWO_h;xWNrhyDw~-Si`iH9aguWMxV~FcP^|?4DFZE%`}$|5O7(f zj6qd4HBNAzOYU<*x-gO4GP;mnRuM|Iax~Q`|to#$cf@k$6w@OrMgCgsi~SjCcaOx$HQ-x=_7F(W9Ul1|KJTBw2v{ zMT5NM*Eo1Yw0V#S-s&Xtw!HeSkz@s~q|>IT&!nnhF*nmG92bj1sXg8*ZG+Y^5|OxA z|F!ajfr7}J5{AW6qSlxsR)32q>}GPwjG6?o>mJKOZRD=B9{#5Jo*cdURIsvbkTi&5 z=!jdA%i!poa_jtVwm`#Z=WWH}F-eYr$iM}=VI)Gqx0NT>Vz(PHL`-uIC&xL(Ei2wv zs(5>BvpQ-0MeV%*{q<=0K38rcq5r!Yb2eP#y(g~s{!%pfhHbbb2D9n~oJRqKWAFSn za!w!N=Br%yQ>&}PgA?L8=w?VzLP6|#`m`ye`dfQ!=x&MuSBim$L-h%h55p_^4a`m6 zfpL}5n@YyzrausXkY z8U`MDW)>|&Re2lko1F;g0jP7TZB$Azh%0jkhhUV5AvY6Vrp&Tg!gA6&khfQ4r`4w`MDW<>%-F#H{s0BJe< zAim5>O3bg3AXk|QOA#x5UjXewSe-za6#KE4S941qw;X;vJLsu-i}7hbQG&lCC%0|! z0QALvg@M7DUVcM;8W9imFlSIq#myMxOiid3>2n-OYO3p^3=oxVGuN`PoV?CXNgDC6ajWX2czgGis$C_TK(s25(zw=Iukm!34+W;m<&!B$b91AF zs!5h>p6XWQGI|VRE>6m2DC}IvDUr9&dG(I+My?xuM-vk_H{rE-kLWm~RUH6!YCix? z9e@5}enKs>XYy>U-aVh2mUsn`yje6da8RzC)!*3p)8W`7qG zaizl{LtmZa`>w~v=*MKcVc85PGEcBYTR7kxFr0LB>0!N)YkJ&G?LEVwaSF~KK?3p;=?$RNfxnYt3O3B_J|A zZ)5wY@MF4e`=0LJOfoV1_TQs<-*FG=2F&{bg2($s31+IqlZ=4DfCDGkkN3Ixa((e0 z_|WQ0J1s`Q@msccfoI-ySl7)q(;bBpN_B$rI_xwdy5C$cE2?(pUTor^vmmZie7Lp) zj?gddkky=SiGu2TGr6l93*d<>mJr8%xNS8eV$FW+i|j@}-P}2g*ie3+JpVb_!Z{=M z`TSzHS8OMIvz;Ii=tr1|5_W*PUm_J?--YDmVHTW6xl12r2xM~OceC2naSIY%3ev@+ zWahcG#&c~ErWQdY^OMiF4nU<=_G5kP?6=z`JCcUWFV#1*Kz!bCv5Q>_snXzK7h?Dc zrc~E;);v=@4dONh_FPeVUEQ3U@2?d_=H=zlz*sPUZm;^Pi~ldq;JBW=knDpX!2`~- z7vlo(R-~2zJSmSa20CPlRX(A0ITpAUjXq8vt7~*k8=niV>#a-~*0PYzX>g04@Vzx( zcpP8BXbZ{NvDz&x9jX;NWLQ1f*WFkz+=Z03LalH{zNYSJH=|N zcEiNvV8%2QINW?5lOGGtwRellfdd}rxJ)1z1ZDpH;wcn?6i#WCYgKgucP~fZCgoOJ z%l~}mC2(saK27vS=tpNhY);e10rR`LNMKT|iQ09652|g6iJ9yZ+!ifh;u3^H2)pH= zbAH|&X`UAunO8+3r&~t8Fqv|RUvG=~0&l0^_L~?LnOImpS=xKUJ&w!S{X@^<1jY`P z(hBj?r}MSPfv5V^ikO@=#)>*FFl}Nphn$YaCPQkF5@8WV3z6FQz3#9kx(mM((>J_g zg3jAaQbvk?roQ*1nn$pN| z8H=N}r(P%b%10T54r=iG! ziGX72-4aB!W}pdnCOjIorI^a2>5JYuipwu2*YNV!rHLw-QHS;rNSa9?0_F$Cis8D? zageFb(NU*t1LVW}08LKt3A9-iid{%_Ll`V!1NLqk_oU7QR^LtJZ%F8Uqi~62-$~4l zHDh)cpV6lA0xxB{r}ANLNfRv~D&Vek^hptPzblkbdQNMkK;Ff+|WJW}_EO3(aZ$RKrp1aae^hwX= zXzY&Ii=}(n^e#kjV6AhW(+#vZ0USvjKe;@Vv&0VdOwo&M&Dfc=&TDnH9yiX4HrmPU z`q;GB1@Qh7>eo_>`08S7zxb=&e;X8pGWuc{^0_;-!)9Cik6Bo6jcp2kIByga6|sNP zV`N);iwx{Ns&8LA{leFeVcNmFPI1pPmbWtN?T;%2Q&x<5isY(s)!0-y6`qOB3oK74 zQYP$je6pZZ+Ib+*`Fw5L?E3Bo1BUXzknWcFB2^C*H7L242VI#1f+kaXMb_rre^ zHlPXLvgj9(@x=jtA{_|JQ)6N9U(W|Xhj5LFXw(h6d}_ZyK8FMyVQ5+iR#NVUaTa|< zY@ckDfh(0E%I9CmZ5Dc^@+2q^lW4)DfNR{twTRm1WckJw|MV|{kyUz5yBncB>fc=@ zXO)L``R$439Lg21#GU@8{!yF5JF#nP8Q?|^`Q8($<9Yx}TiG_!Kh(C&eW^*_=hfh1 ze;bB!k(7h)>(sfF`_R0Vk^(TQvd8*OMYJa#fIOT)P19`@Lmx>two1_1TfhD9-@_oI zlU|LpIkswwBD(bT^xG$eN$<;tYvLN0&`ym7`db#XoaIRcApeCJjCC_)NgD!~Zs$1X zg=n0;+c+>`XNM!kTQs(^sfIuK)eh;fWe+3`V9tApS$h7%J7S(0VbssQugw%pDlBH> z2t2-d?C|j2;B)ZV_z@v@6NIXoTvc+12XYu+4zzLXeZDK;@KS$hs`aOB&`*&_7+AxE z(3p&uCQI8U5oT%u1SM9wfKzV0B^s(N0G0-e!5G^P2-9M-`WEcVb8n2IUVYZvqyFfg zySwBkTHN)MT5i6kRjRU^qcyO_TR^DI&M{9S0;zz%Hq|k@P~_za_k4W}JCU{M*!!oh zPrdl@)YiCHYoJ$WDX-v>nUE*3aXah-*)vLoXr*Xvf$eTDbp#s>1~@?K%htA>OCjaG z16Uj`wcWQoq9*kuRhrr7>3wZ3wEU%|7lA>d!Pr#M*<6l3w)yh3EIr!S?GolCLASM* zJc?~?XyUZ-FpN7KrwRPC>uR>ZX)r@Z76T9u0rChs`u`5-|Mzk6$Jn3tb@O{AEL@%l z=8`39MBFi#^eO}2w~|N78(hlrXv46v)0eE80)MdmVU;f%J$!gBHxg;mXHx5BmhI8z z9#Wrma^Om3&swG5N#v*{kAsgKn?_T+w=b{J#>-GR4 zfS`^UBlB2Y|C?EJ)1mAHdnh)8ny*D7`GWVtKI>icfp^2NuK_oPLU!@79q8iOY6(tJd2rG{l2gsr|)6Dg?8 ze}Sfycto(zTPZIJuFC*p4;|=_EDT6aO_dQWpyFz)dfKL;x=t{mC~o%=iuTGhGvIy{ z|A27grehBMh@M!g+zZkM6@`biES7W;S!~XTfZv`K53xJ|@fg3JDX=IAF z@GlY-C=YF)$a|UPG`rwnWzvHFW~o`fM2R&V+F^nXc->!AfM-g0J|c>Cpi?nv=*QNG zgk_|Pdgit2Q&k&+JjqEykg5e1gqC`_4VRFZj)9I4t1W4PoB}L991^W^+P+5#Ncmx- z**H~bI@j6mhSNsdu4Ey|RX=}zi1UZ2)RD|b(9UJ!pZ+THZ}r#( z7JM{T(27t9`#VqDzpE)SON8%h#7e5fzFv6WHGTy6Nd}YO}{BU z7HX zjPw)B0b6e>){DI_t)9wKc<#=2kdaexd3gruxF3yz?N#Oe>@bh&Hj&D&y@mNQyY#HF z<<+};C07UfFlNIK1R(6OY!JnZ7tT-QEr$MVF$G1pn?^=07{nWxC+R*FzWwgJHJ?L% z*ed~Qh3c|{?k?QJ(hIvMs!wU?qgJR$27QC)GYfp4Oo|vGA>5?hUdTvVe&mL}uq*9T zpwD)8$(NyX^G!H-pC34bCfk8UAoLSJy-Um&ix!%1OYSc z-m_nW=l}mo;2pn}Krh>P!E;2vZ^^J#D6sO8(Flxr}}xxsQ#b+Ya6 zmAv>pil?k52XO3|I0oiCZzIQp(vuf#Vdk3StsEY-Ip2f6xmN2FNEgxCt2jwY99 z^e1JkUi>AvbXlV0*P<-Hls|J{;14O^{bvb>Cny0lw(j}d3QM`adno*GSmypwIRCZy zq_XpFZq}YbeeleEkL};%!BXr4J-Zu^)fK(UKzvfi?sjud1%?)eE-RYo{vMr?u?EfgKEQ6ncPV&9{herQfW|@De^FMwbQ>mTQOJy0OB%Yr$y_#hTLA^t?s#bS~`^(+x zk9u@KB96$r6~!_+9RZGf_pU*sIP}Le;VP_OwwJnL2cUMpJ&ny^ z-`Tta&~){FW>=8E_nva-(y41zA*t%jr@^ez3w4DWJt-IZg83iqU$CkIt8W2_{=7NU z!Bi9X>@-cypkkTj_IQY340_W`-UU*t>K98oaT~8?^@9nLC{Pq8cp{{iI{t zhHHB_a}lsb{#ynT~ zGPl5PjK})QUemmb#eYPDn#6|@LwoEG>%~1vK!+awjr8;PZ~5<7zx`gze;WH^pJsMe z4u7p$*>2zaockuEhtk}+FUXYl-G6@(#2ml)$L`5r%i-BgrS6kCM>N_dj7*byLU@=- zDwlvBl3Td`4~_lRL;pwgP;^=bcOscM6K$F?MQRp|sZOD#SlWgoh8g-M!Qd?+j9b^96p(o* z&RGaos-)@$Tupn~RP-H#5psUuZR(QuB=?JCjzr|wntzQ;$u$7jlsHi`8sE`GW5v%& zB3gZhc~E0(8oqA^9*8qoGpgS+ORsw6Ax54CDypkHt|7KT9baBt)oO6#AD3VTv=$_F zx9NJGJUK^Rd!-Rf(iU7^MZmTCLtHOc#pVu-dk(+;hmj8aFU16$*bAx+WagO5P`!&8TQUU+=o@JjybikJd;cFA_~%Oq5WD#v535J5-v7Or(*Dz&=v0~f z-de7+er*-C?JbNPT@r|kTn;X;_)&73AZjJ)pHtq7Cn;JYtVmPq(qj28x?8rjAL$w8 z^j?%Z!WjDcPELRtJlTqTh_|XvxxE1+~8xGC5;f4 z5X|WpAZ?(hICFZt7t?C4fsP}z(b=pNp=^78O-(ER|7Q?f=M*9*n4h9}M~!DlWWOL&`BAf2_V zxFqGPaq0KgS-IA8{=5Fx|M0@6lycx$TeOuEM*6V(ZprQj;q``;PeAY0b++uE6*_b};yV E0lbN9tN;K2 literal 0 HcmV?d00001 diff --git a/docs/static/img/screenshots/mobile/mobile_dashboard_list.jpg b/docs/static/img/screenshots/mobile/mobile_dashboard_list.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e7d16911b87bcdaee0d44cfbf0a62659ee1735d6 GIT binary patch literal 82502 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

}y1qqBZ6#As{D;^%`%w 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

eRBR7P!aic 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/screenshots/mobile/mobile_nav_drawer.jpg b/docs/static/img/screenshots/mobile/mobile_nav_drawer.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e987c39876ca90eccac365a5b4c9a47c9ac4c717 GIT binary patch literal 35385 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%0D0yN1+IQu8q1E5>aWYv*eQb4OMUTd_T7kE> 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�br5c;$m`j3rzC^m~l--tVQJ8-K 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 Y;LjQOa|ZsLfj?*9e}@@(>&@8z1w@Vt(*OVf literal 0 HcmV?d00001 diff --git a/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx index 70fa0d41e68..ddb3a4d5bb1 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/DynamicEditableTitle/index.tsx @@ -49,6 +49,7 @@ const titleStyles = (theme: SupersetTheme) => css` text-overflow: ellipsis; white-space: nowrap; padding: 0; + font-weight: inherit; color: ${theme.colorText}; background-color: ${theme.colorBgContainer}; @@ -127,6 +128,21 @@ export const DynamicEditableTitle = memo( } }, [currentTitle, placeholder]); + // Webfont metrics differ from the fallback font's, so a measurement + // taken before fonts finish loading under- or over-sizes the input. + // Re-measure once all fonts are ready. + useEffect(() => { + let cancelled = false; + document.fonts?.ready?.then(() => { + if (!cancelled && sizerRef.current) { + setInputWidth(sizerRef.current.offsetWidth); + } + }); + return () => { + cancelled = true; + }; + }, []); + useEffect(() => { const inputElement = inputRef.current?.input; diff --git a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx index d536f292bea..cd1ef78f834 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/PageHeaderWithActions/index.tsx @@ -20,6 +20,7 @@ import { ReactNode, ReactElement, memo } from 'react'; import { t } from '@apache-superset/core/translation'; import { css, SupersetTheme, useTheme } from '@apache-superset/core/theme'; import { Icons } from '@superset-ui/core/components/Icons'; +import { FeatureFlag, isFeatureEnabled } from '../../utils/featureFlags'; import type { DropdownProps } from '../Dropdown/types'; import type { TooltipPlacement } from '../Tooltip/types'; import type { CertifiedBadgeProps } from '../CertifiedBadge/types'; @@ -82,6 +83,20 @@ const headerStyles = (theme: SupersetTheme) => css` display: flex; align-items: center; } + + /* Mobile consumption mode: center the title between left/right panels */ + ${ + isFeatureEnabled(FeatureFlag.MobileConsumptionMode) && + css` + @media (max-width: ${theme.screenSMMax}px) { + .title-panel { + flex: 1; + justify-content: center; + margin-right: 0; + } + } + ` + } `; const buttonsStyles = (theme: SupersetTheme) => css` @@ -109,6 +124,7 @@ export type PageHeaderWithActionsProps = { showFaveStar: boolean; showMenuDropdown?: boolean; faveStarProps: FaveStarProps; + leftPanelItems?: ReactNode; titlePanelAdditionalItems: ReactNode; rightPanelAdditionalItems: ReactNode; additionalActionsMenu: ReactElement; @@ -126,6 +142,7 @@ export const PageHeaderWithActions = memo( certificatiedBadgeProps, showFaveStar, faveStarProps, + leftPanelItems, titlePanelAdditionalItems, rightPanelAdditionalItems, additionalActionsMenu, @@ -136,6 +153,7 @@ export const PageHeaderWithActions = memo( const theme = useTheme(); return (

+ {leftPanelItems}
{showTitlePanelItems && ( diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index ebc5ed9a532..c2fd991f754 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -57,6 +57,7 @@ export enum FeatureFlag { GranularExportControls = 'GRANULAR_EXPORT_CONTROLS', ListviewsDefaultCardView = 'LISTVIEWS_DEFAULT_CARD_VIEW', Matrixify = 'MATRIXIFY', + MobileConsumptionMode = 'MOBILE_CONSUMPTION_MODE', ScheduledQueries = 'SCHEDULED_QUERIES', SemanticLayers = 'SEMANTIC_LAYERS', SoftDelete = 'SOFT_DELETE', diff --git a/superset-frontend/playwright.config.ts b/superset-frontend/playwright.config.ts index dccb1d65141..6b67bb3975b 100644 --- a/superset-frontend/playwright.config.ts +++ b/superset-frontend/playwright.config.ts @@ -96,6 +96,7 @@ export default defineConfig({ '**/tests/auth/**/*.spec.ts', '**/tests/sqllab/**/*.spec.ts', '**/tests/embedded/**/*.spec.ts', + '**/tests/mobile/**/*.spec.ts', ...(process.env.INCLUDE_EXPERIMENTAL ? [] : ['**/experimental/**']), ], use: { @@ -156,6 +157,23 @@ export default defineConfig({ }, ] : []), + // Mobile consumption-mode tests need the MOBILE_CONSUMPTION_MODE feature + // flag enabled in the Flask backend (the workflow's mobile step sets + // SUPERSET_FEATURE_MOBILE_CONSUMPTION_MODE), so they only run when the + // environment opts in. Same strict 'true' check as INCLUDE_EMBEDDED. + ...(process.env.INCLUDE_MOBILE?.toLowerCase() === 'true' + ? [ + { + name: 'chromium-mobile', + testMatch: '**/tests/mobile/**/*.spec.ts', + use: { + browserName: 'chromium' as const, + testIdAttribute: 'data-test', + storageState: 'playwright/.auth/user.json', + }, + }, + ] + : []), ], // Web server setup - disabled in CI (Flask started separately in workflow) diff --git a/superset-frontend/playwright/generators/docs/mobile-screenshots.spec.ts b/superset-frontend/playwright/generators/docs/mobile-screenshots.spec.ts new file mode 100644 index 00000000000..119d3a1a5e5 --- /dev/null +++ b/superset-frontend/playwright/generators/docs/mobile-screenshots.spec.ts @@ -0,0 +1,167 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Mobile Experience Documentation Screenshot Generator + * + * Captures phone-sized screenshots for the mobile consumption mode docs + * (docs/docs/using-superset/mobile-experience.mdx). Depends on example data + * loaded via `superset load_examples` AND the MOBILE_CONSUMPTION_MODE + * feature flag being enabled in the target environment: + * + * FEATURE_FLAGS = {"MOBILE_CONSUMPTION_MODE": True} + * + * Run locally: + * cd superset-frontend + * PLAYWRIGHT_BASE_URL=http://localhost:8088 PLAYWRIGHT_ADMIN_PASSWORD=admin npm run docs:screenshots + * + * Screenshots are saved under docs/static/img/screenshots/mobile/. + */ + +import path from 'path'; +import { Page, test, expect } from '@playwright/test'; +import { URL } from '../../utils/urls'; + +const MOBILE_SCREENSHOTS_DIR = path.resolve( + __dirname, + '../../../../docs/static/img/screenshots/mobile', +); + +// iPhone 12-class viewport; 2x scale factor for crisp docs images +test.use({ + viewport: { width: 390, height: 844 }, + deviceScaleFactor: 2, + hasTouch: true, +}); + +/** + * Waits for animations and async renders to settle before taking a + * screenshot. ECharts entry animations, drawer transitions, and image + * lazy-loading require a short pause that can't be expressed as a + * deterministic wait condition. + */ +async function settle(page: Page, ms = 1000): Promise { + await page.waitForTimeout(ms); +} + +/** + * Opens the Sales Dashboard (from example data) at phone size and waits for + * the stacked charts to finish rendering. + */ +async function openSalesDashboardMobile(page: Page): Promise { + await page.goto(URL.DASHBOARD_LIST); + // Mobile list is card-only; cards navigate on tap (titles are plain + // text, not links, in consumption mode) + const dashboardCard = page.getByText('Sales Dashboard', { exact: true }); + await expect(dashboardCard.first()).toBeVisible({ timeout: 15000 }); + await dashboardCard.first().click(); + + await expect( + page.locator('[data-test="dashboard-content-wrapper"]'), + ).toBeVisible({ timeout: 30000 }); + await expect( + page.locator('.dashboard-component-chart-holder canvas').first(), + ).toBeVisible({ timeout: 30000 }); +} + +test('mobile dashboard screenshot', async ({ page }) => { + await openSalesDashboardMobile(page); + await settle(page, 2000); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_dashboard.jpg'), + type: 'jpeg', + }); +}); + +test('mobile dashboard filter drawer screenshot', async ({ page }) => { + await openSalesDashboardMobile(page); + + const filterTrigger = page.locator('[data-test="mobile-filters-trigger"]'); + await expect(filterTrigger).toBeVisible({ timeout: 15000 }); + await filterTrigger.click(); + + // Wait for the drawer and its filter controls to render + await expect(page.locator('.ant-drawer-body')).toBeVisible({ + timeout: 10000, + }); + await expect(page.locator('[data-test="filter-bar"]')).toBeVisible({ + timeout: 10000, + }); + // Park the pointer so no hover card is open in the capture + await page.mouse.move(5, 830); + await settle(page); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_filter_drawer.jpg'), + type: 'jpeg', + }); +}); + +test('mobile dashboard list screenshot', async ({ page }) => { + await page.goto(URL.DASHBOARD_LIST); + // Card view is forced on mobile; wait for cards to render + await expect(page.locator('[data-test="styled-card"]').first()).toBeVisible({ + timeout: 15000, + }); + await settle(page); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_dashboard_list.jpg'), + type: 'jpeg', + }); +}); + +test('mobile home screenshot', async ({ page }) => { + await page.goto(URL.WELCOME); + await expect(page.getByText('Recents')).toBeVisible({ timeout: 15000 }); + await settle(page, 2000); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_home.jpg'), + type: 'jpeg', + }); +}); + +test('mobile navigation drawer screenshot', async ({ page }) => { + await page.goto(URL.WELCOME); + await expect(page.getByText('Recents')).toBeVisible({ timeout: 15000 }); + + const menuButton = page.getByRole('button', { name: 'Menu' }); + await expect(menuButton).toBeVisible({ timeout: 10000 }); + await menuButton.click(); + + await expect(page.locator('.ant-drawer-body')).toBeVisible({ + timeout: 10000, + }); + await expect(page.getByText('Dashboards').first()).toBeVisible(); + await settle(page); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_nav_drawer.jpg'), + type: 'jpeg', + }); +}); + +test('mobile unsupported route screenshot', async ({ page }) => { + await page.goto(URL.SQLLAB); + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: 15000 }); + await settle(page); + await page.screenshot({ + path: path.join(MOBILE_SCREENSHOTS_DIR, 'mobile_unsupported.jpg'), + type: 'jpeg', + }); +}); diff --git a/superset-frontend/playwright/tests/mobile/mobile-dashboard.spec.ts b/superset-frontend/playwright/tests/mobile/mobile-dashboard.spec.ts new file mode 100644 index 00000000000..cce973d2017 --- /dev/null +++ b/superset-frontend/playwright/tests/mobile/mobile-dashboard.spec.ts @@ -0,0 +1,325 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { test, expect, devices } from '@playwright/test'; + +// NOTE: These tests exercise the mobile consumption experience and require +// the MOBILE_CONSUMPTION_MODE feature flag to be enabled in the target +// environment (FEATURE_FLAGS = {"MOBILE_CONSUMPTION_MODE": True}). +import { TIMEOUT } from '../../utils/constants'; + +/** + * Mobile dashboard viewing tests verify that dashboards can be viewed + * and interacted with on mobile devices. + * + * These tests assume the World Bank's Health sample dashboard exists. + */ + +// Use iPhone 12 viewport for mobile tests +const mobileViewport = devices['iPhone 12']; + +test.describe('Mobile Dashboard Viewing', () => { + test.use({ + viewport: mobileViewport.viewport, + userAgent: mobileViewport.userAgent, + }); + + test.beforeEach(async ({ page }) => { + // Navigate to dashboard list to find a dashboard + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + }); + + test('dashboard list renders in card view on mobile', async ({ page }) => { + // On mobile, dashboard list should show cards, not table + // Look for card elements + const cards = page.locator('[data-test="styled-card"]'); + + // Should have at least one card if dashboards exist + // (This test may need adjustment based on test data availability) + const cardCount = await cards.count(); + + // Either cards are visible, or the empty state is shown; the table + // view must never render on mobile + if (cardCount > 0) { + await expect(cards.first()).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + } else { + await expect(page.locator('[data-test="empty-state"]')).toBeVisible({ + timeout: TIMEOUT.PAGE_LOAD, + }); + } + await expect(page.locator('[data-test="listview-table"]')).toHaveCount(0); + }); + + test('mobile search button appears in dashboard list', async ({ page }) => { + // On mobile, the search/filter button should appear in the header + const searchButton = page + .locator('[aria-label="Search"]') + .or(page.locator('[data-test="mobile-search-button"]')); + + // Search button should be visible on mobile + await expect(searchButton.first()).toBeVisible({ + timeout: TIMEOUT.PAGE_LOAD, + }); + }); + + test('tapping dashboard card opens the dashboard', async ({ page }) => { + // Find a dashboard card + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + // Click the first card + await cards.first().click(); + + // Should navigate to dashboard view + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Dashboard should load (look for dashboard content) + await expect( + page + .locator('[data-test="dashboard-content-wrapper"]') + .or(page.locator('.dashboard')), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + } else { + test.skip(); + } + }); +}); + +test.describe('Mobile Dashboard Interaction', () => { + test.use({ + viewport: mobileViewport.viewport, + userAgent: mobileViewport.userAgent, + }); + + // Skip this test suite if no dashboards exist + test.beforeAll(async ({ browser }) => { + const page = await browser.newPage({ + viewport: mobileViewport.viewport, + userAgent: mobileViewport.userAgent, + }); + + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + await page.close(); + + if (cardCount === 0) { + test.skip(); + } + }); + + test('dashboard loads and shows charts on mobile', async ({ page }) => { + // Navigate to dashboard list + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + // Click first dashboard + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + await cards.first().click(); + + // Wait for dashboard to load + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Dashboard content should be visible + await expect( + page + .locator('[data-test="dashboard-content-wrapper"]') + .or(page.locator('.dashboard')), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + + // Charts should start loading (look for chart containers) + const chartContainers = page + .locator('[data-test="chart-container"]') + .or(page.locator('.dashboard-chart')); + + // Wait for at least one chart to be visible (with timeout) + await expect(chartContainers.first()).toBeVisible({ + timeout: TIMEOUT.PAGE_LOAD * 2, + }); + } + }); + + test('dashboard header shows hamburger menu on mobile', async ({ page }) => { + // Navigate to dashboard list + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + // Click first dashboard + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + await cards.first().click(); + + // Wait for dashboard + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Look for the hamburger menu / more actions button + const menuButton = page + .locator('[data-test="actions-trigger"]') + .or(page.locator('[aria-label="Menu actions trigger"]')); + + await expect(menuButton.first()).toBeVisible({ + timeout: TIMEOUT.PAGE_LOAD, + }); + } + }); + + test('refresh dashboard works from mobile menu', async ({ page }) => { + // Navigate to dashboard list + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + // Click first dashboard + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + await cards.first().click(); + + // Wait for dashboard + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Open the actions menu + const menuButton = page + .locator('[data-test="actions-trigger"]') + .or(page.locator('[aria-label="Menu actions trigger"]')); + + if ((await menuButton.count()) > 0) { + await menuButton.first().click(); + + // Look for refresh option + const refreshOption = page.getByText('Refresh dashboard'); + + if ((await refreshOption.count()) > 0) { + await refreshOption.click(); + + // Should show success toast or refresh the charts + // This is hard to verify without checking network requests + // Just verify the menu closes and we're still on the dashboard + await page.waitForTimeout(1000); + expect(page.url()).toMatch(/\/dashboard\/(?!list)/); + } + } + } + }); +}); + +test.describe('Mobile Filter Drawer', () => { + test.use({ + viewport: mobileViewport.viewport, + userAgent: mobileViewport.userAgent, + }); + + test('filter button appears on dashboards with filters', async ({ page }) => { + // Navigate to dashboard list + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + // Click first dashboard + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + await cards.first().click(); + + // Wait for dashboard + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Give filters time to load + await page.waitForTimeout(2000); + + // Check for filter button (only visible if dashboard has filters) + const filterButton = page + .locator('[data-test="filter-icon"]') + .or( + page + .locator('[aria-label="Filters"]') + .or(page.locator('.mobile-filter-button')), + ); + + const filterCount = await filterButton.count(); + + // The test passes whether filters exist or not + // If filters exist, button should be visible + // If no filters, that's also valid + if (filterCount > 0) { + await expect(filterButton.first()).toBeVisible(); + } + } + }); + + test('filter drawer opens when filter button is tapped', async ({ page }) => { + // Navigate to dashboard list + await page.goto('dashboard/list/'); + await page.waitForLoadState('networkidle'); + + // Click first dashboard + const cards = page.locator('[data-test="styled-card"]'); + const cardCount = await cards.count(); + + if (cardCount > 0) { + await cards.first().click(); + + // Wait for dashboard + await page.waitForURL(url => /\/dashboard\/(?!list)/.test(url.pathname), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Give filters time to load + await page.waitForTimeout(2000); + + // Check for filter button + const filterButton = page + .locator('[data-test="filter-icon"]') + .or(page.locator('[aria-label="Filters"]')); + + if ((await filterButton.count()) > 0) { + await filterButton.first().click(); + + // Filter drawer should open + const drawer = page + .locator('.ant-drawer-open') + .or(page.locator('[data-test="filter-bar"]')); + + await expect(drawer.first()).toBeVisible({ + timeout: TIMEOUT.FORM_LOAD, + }); + } + } + }); +}); diff --git a/superset-frontend/playwright/tests/mobile/mobile-navigation.spec.ts b/superset-frontend/playwright/tests/mobile/mobile-navigation.spec.ts new file mode 100644 index 00000000000..aec3f325e9d --- /dev/null +++ b/superset-frontend/playwright/tests/mobile/mobile-navigation.spec.ts @@ -0,0 +1,192 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { test, expect, devices } from '@playwright/test'; + +// NOTE: These tests exercise the mobile consumption experience and require +// the MOBILE_CONSUMPTION_MODE feature flag to be enabled in the target +// environment (FEATURE_FLAGS = {"MOBILE_CONSUMPTION_MODE": True}). +import { URL } from '../../utils/urls'; +import { TIMEOUT } from '../../utils/constants'; + +/** + * Mobile navigation tests verify the MobileRouteGuard behavior + * and mobile-specific navigation patterns. + * + * These tests run with a mobile viewport to trigger mobile-specific behavior. + */ + +// Use iPhone 12 viewport for mobile tests +const mobileViewport = devices['iPhone 12']; + +test.describe('Mobile Navigation', () => { + test.use({ + viewport: mobileViewport.viewport, + userAgent: mobileViewport.userAgent, + }); + + test.beforeEach(async ({ page }) => { + await page.goto('/'); + }); + + test('mobile viewport redirects from chart list to MobileUnsupported page', async ({ + page, + }) => { + // Navigate to chart list (not mobile-supported) + await page.goto(URL.CHART_LIST); + + // Should show the MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + + // Primary action buttons should be visible + await expect( + page.getByRole('button', { name: 'View Dashboards' }), + ).toBeVisible(); + await expect( + page.getByRole('button', { name: 'Go to Welcome Page' }), + ).toBeVisible(); + }); + + test('mobile viewport allows access to dashboard list', async ({ page }) => { + // Navigate to dashboard list (mobile-supported) + await page.goto(URL.DASHBOARD_LIST); + + // Should NOT show MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).not.toBeVisible({ timeout: TIMEOUT.FORM_LOAD }); + + // Should show dashboard list content (look for dashboard list elements) + await expect( + page + .locator('[data-test="listview-table"]') + .or(page.locator('[data-test="styled-card"]')) + .first(), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + }); + + test('mobile viewport allows access to welcome page', async ({ page }) => { + // Navigate to welcome page (mobile-supported) + await page.goto(URL.WELCOME); + + // Should NOT show MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).not.toBeVisible({ timeout: TIMEOUT.FORM_LOAD }); + + // Should show welcome page content + await expect( + page.getByText('Recents').or(page.getByText('Dashboards')).first(), + ).toBeVisible({ + timeout: TIMEOUT.PAGE_LOAD, + }); + }); + + test('View Dashboards button navigates to dashboard list', async ({ + page, + }) => { + // Navigate to unsupported route + await page.goto(URL.CHART_LIST); + + // Wait for MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + + // Click View Dashboards button + await page.getByRole('button', { name: 'View Dashboards' }).click(); + + // Should navigate to dashboard list + await page.waitForURL(url => url.pathname.includes('dashboard/list'), { + timeout: TIMEOUT.PAGE_LOAD, + }); + + // Dashboard list should be accessible + await expect( + page + .locator('[data-test="listview-table"]') + .or(page.locator('[data-test="styled-card"]')) + .first(), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + }); + + test('Go to Welcome Page button navigates to welcome', async ({ page }) => { + // Navigate to unsupported route + await page.goto(URL.CHART_LIST); + + // Wait for MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + + // Click Go to Welcome Page button + await page.getByRole('button', { name: 'Go to Welcome Page' }).click(); + + // Should navigate to welcome page + await page.waitForURL(url => url.pathname.includes('welcome'), { + timeout: TIMEOUT.PAGE_LOAD, + }); + }); + + test('unsupported screen offers no bypass', async ({ page }) => { + // The "Continue anyway" bypass was removed: desktop views are unusable + // at phone width, and growing the viewport unblocks routes automatically + await page.goto(URL.CHART_LIST); + + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + + await expect(page.getByText('Continue anyway')).toHaveCount(0); + }); + + test('SQL Lab is not accessible on mobile', async ({ page }) => { + // Navigate to SQL Lab (not mobile-supported) + await page.goto(URL.SQLLAB); + + // Should show the MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + }); +}); + +test.describe('Desktop Navigation (control group)', () => { + // Use default desktop viewport + + test('desktop viewport allows access to all routes', async ({ page }) => { + // Navigate to chart list + await page.goto(URL.CHART_LIST); + + // Should NOT show MobileUnsupported page + await expect( + page.getByText("This view isn't available on mobile"), + ).not.toBeVisible({ timeout: TIMEOUT.FORM_LOAD }); + + // Should show chart list content + await expect( + page + .locator('[data-test="listview-table"]') + .or(page.locator('[data-test="styled-card"]')) + .first(), + ).toBeVisible({ timeout: TIMEOUT.PAGE_LOAD }); + }); +}); diff --git a/superset-frontend/spec/helpers/mobileTestUtils.ts b/superset-frontend/spec/helpers/mobileTestUtils.ts new file mode 100644 index 00000000000..5aabcac0c1f --- /dev/null +++ b/superset-frontend/spec/helpers/mobileTestUtils.ts @@ -0,0 +1,150 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Mobile testing utilities for Jest tests. + * + * Note: We mock 'antd' directly rather than '@superset-ui/core/components' because + * mocking the latter causes circular dependency issues with ActionButton during + * jest.requireActual evaluation. Since Grid is re-exported from antd, mocking + * antd at the source works correctly. + */ + +import { FeatureFlag } from '@superset-ui/core'; + +/** + * Standard mobile breakpoint values (below md breakpoint) + */ +export const mobileBreakpoints = { + xs: true, + sm: true, + md: false, + lg: false, + xl: false, + xxl: false, +}; + +/** + * Standard desktop breakpoint values (at or above md breakpoint) + */ +export const desktopBreakpoints = { + xs: true, + sm: true, + md: true, + lg: true, + xl: true, + xxl: true, +}; + +/** + * Creates a mock for antd Grid.useBreakpoint that returns mobile breakpoints. + * Use this at the top of test files that need to simulate mobile viewport. + * + * @example + * jest.mock('antd', () => mockAntdWithMobileBreakpoint()); + */ +export const mockAntdWithMobileBreakpoint = () => ({ + ...jest.requireActual('antd'), + Grid: { + ...jest.requireActual('antd').Grid, + useBreakpoint: () => mobileBreakpoints, + }, +}); + +/** + * Creates a mock for antd Grid.useBreakpoint that returns desktop breakpoints. + * Use this at the top of test files that need to simulate desktop viewport. + * + * @example + * jest.mock('antd', () => mockAntdWithDesktopBreakpoint()); + */ +export const mockAntdWithDesktopBreakpoint = () => ({ + ...jest.requireActual('antd'), + Grid: { + ...jest.requireActual('antd').Grid, + useBreakpoint: () => desktopBreakpoints, + }, +}); + +/** + * Mocks window.matchMedia so `(max-width: ...)` queries match, simulating + * a mobile viewport for the useIsMobile hook. Returns a cleanup function + * restoring the previous matchMedia. Mobile behavior requires BOTH this + * AND the MOBILE_CONSUMPTION_MODE flag (see enableMobileConsumptionFlag). + */ +export const mockMobileMatchMedia = () => { + const previous = window.matchMedia; + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query: string) => ({ + matches: query.includes('max-width'), + media: query, + onchange: null, + addListener: jest.fn(), + removeListener: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + return () => { + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: previous, + }); + }; +}; + +/** + * Enables the MOBILE_CONSUMPTION_MODE feature flag on window.featureFlags. + * Mobile behavior requires BOTH a small viewport (mockMobileMatchMedia) + * AND this flag; call this in beforeAll/beforeEach of mobile test suites. + * Returns a cleanup function restoring the previous flags. + */ +export const enableMobileConsumptionFlag = () => { + const previous = window.featureFlags; + window.featureFlags = { + ...window.featureFlags, + [FeatureFlag.MobileConsumptionMode]: true, + }; + return () => { + window.featureFlags = previous; + }; +}; + +/** + * Common mobile viewport dimensions for reference + */ +export const mobileViewports = { + iPhoneX: { width: 375, height: 812 }, + iPhoneSE: { width: 375, height: 667 }, + iPhone12Pro: { width: 390, height: 844 }, + pixel5: { width: 393, height: 851 }, + samsungGalaxyS20: { width: 360, height: 800 }, +}; + +/** + * Common tablet viewport dimensions for reference + */ +export const tabletViewports = { + iPadMini: { width: 768, height: 1024 }, + iPadAir: { width: 820, height: 1180 }, + iPadPro11: { width: 834, height: 1194 }, + surfacePro7: { width: 912, height: 1368 }, +}; diff --git a/superset-frontend/src/components/ListView/CardCollection.tsx b/superset-frontend/src/components/ListView/CardCollection.tsx index b77e9f475f4..d66dbb10b8c 100644 --- a/superset-frontend/src/components/ListView/CardCollection.tsx +++ b/superset-frontend/src/components/ListView/CardCollection.tsx @@ -19,6 +19,7 @@ import { ReactNode, MouseEvent as ReactMouseEvent } from 'react'; import { TableInstance, Row, UseRowSelectRowProps } from 'react-table'; import { styled } from '@apache-superset/core/theme'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; import cx from 'classnames'; interface CardCollectionProps { @@ -42,6 +43,18 @@ const CardContainer = styled.div<{ showThumbnails?: boolean }>` ? `${theme.sizeUnit * 8 + 3}px ${theme.sizeUnit * 20}px` : `${theme.sizeUnit * 8 + 1}px ${theme.sizeUnit * 20}px` }; + + /* Full-width cards on mobile (consumption mode) */ + ${ + isMobileConsumptionEnabled() + ? `@media (max-width: ${theme.screenSMMax}px) { + grid-template-columns: 1fr; + grid-gap: ${theme.sizeUnit * 4}px; + padding-left: ${theme.sizeUnit * 4}px; + padding-right: ${theme.sizeUnit * 4}px; + }` + : '' + } `} `; diff --git a/superset-frontend/src/components/ListView/ListView.test.tsx b/superset-frontend/src/components/ListView/ListView.test.tsx index 8b8bd22bd12..8cd957407d7 100644 --- a/superset-frontend/src/components/ListView/ListView.test.tsx +++ b/superset-frontend/src/components/ListView/ListView.test.tsx @@ -380,3 +380,227 @@ describe('ListView', () => { expect(screen.getByTestId('empty-state')).toHaveClass('card'); }); }); + +// Mobile support tests +test('respects forceViewMode prop and hides view toggle', () => { + // Omit cardSortSelectOptions to avoid CardSortSelect needing initialSort + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + +
Card
} + forceViewMode="card" + /> +
+
, + { store: mockStore() }, + ); + + // View toggle should not be present when forceViewMode is set + expect(screen.queryByLabelText('card-view')).not.toBeInTheDocument(); + expect(screen.queryByLabelText('list-view')).not.toBeInTheDocument(); +}); + +test('shows card view when forceViewMode is card', () => { + // Omit cardSortSelectOptions to avoid CardSortSelect needing initialSort + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + +
Card Content
} + forceViewMode="card" + /> +
+
, + { store: mockStore() }, + ); + + // Should render cards, not table rows + expect(screen.getAllByTestId('test-card')).toHaveLength(2); +}); + +test('renders mobile filter drawer when mobileFiltersOpen is true', () => { + const setMobileFiltersOpen = jest.fn(); + // Omit cardSortSelectOptions to avoid CardSortSelect needing initialSort + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // Drawer should be visible with custom title + expect(screen.getByText('Search Dashboards')).toBeInTheDocument(); +}); + +test('calls setMobileFiltersOpen(false) when drawer is closed', async () => { + const setMobileFiltersOpen = jest.fn(); + // Omit cardSortSelectOptions to avoid CardSortSelect needing initialSort + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // Click the close button on the drawer + const closeButton = screen.getByLabelText('Close'); + await userEvent.click(closeButton); + + expect(setMobileFiltersOpen).toHaveBeenCalledWith(false); +}); + +test('mobile drawer contains FilterControls', () => { + const setMobileFiltersOpen = jest.fn(); + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // The drawer should contain the filter controls; select filters render + // as popover triggers (aria-haspopup="listbox") in the drawer + const drawer = screen.getByRole('dialog'); + const filterTriggers = drawer.querySelectorAll('[aria-haspopup="listbox"]'); + expect(filterTriggers.length).toBeGreaterThan(0); +}); + +test('mobile drawer contains CardSortSelect when in card view with sort options', () => { + const setMobileFiltersOpen = jest.fn(); + render( + + +
Card
} + forceViewMode="card" + mobileFiltersOpen + setMobileFiltersOpen={setMobileFiltersOpen} + initialSort={[{ id: 'something' }]} + /> +
+
, + { store: mockStore() }, + ); + + // Sort select should be present (may be multiple - one in drawer, one in header) + const sortSelects = screen.getAllByTestId('card-sort-select'); + expect(sortSelects.length).toBeGreaterThan(0); +}); + +test('uses default drawer title when mobileFiltersDrawerTitle not provided', () => { + const setMobileFiltersOpen = jest.fn(); + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // Default title should be 'Search' + expect(screen.getByText('Search')).toBeInTheDocument(); +}); + +test('does not render drawer when mobileFiltersOpen is false', () => { + const setMobileFiltersOpen = jest.fn(); + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // Drawer should not be visible (title not in visible content) + // Note: Ant Design drawer might still be in DOM but hidden + const drawer = document.querySelector('.ant-drawer-open'); + expect(drawer).toBeNull(); +}); + +test('does not render mobile drawer without setMobileFiltersOpen prop', () => { + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + + + + , + { store: mockStore() }, + ); + + // No drawer elements should exist + const drawer = document.querySelector('.ant-drawer'); + expect(drawer).toBeNull(); +}); + +test('forceViewMode table shows table view', () => { + const { cardSortSelectOptions: _cardSortSelectOptions, ...propsWithoutSort } = + mockedPropsComprehensive; + render( + + +
Card
} + forceViewMode="table" + /> +
+
, + { store: mockStore() }, + ); + + // Should show table, not cards + expect(screen.queryByTestId('card')).not.toBeInTheDocument(); + // Table should be present + expect(screen.getByRole('table')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/ListView/ListView.tsx b/superset-frontend/src/components/ListView/ListView.tsx index aaf28b70043..4c0c73a8310 100644 --- a/superset-frontend/src/components/ListView/ListView.tsx +++ b/superset-frontend/src/components/ListView/ListView.tsx @@ -33,6 +33,7 @@ import BulkTagModal from 'src/features/tags/BulkTagModal'; import { Button, Tooltip, + Drawer, Icons, EmptyState, Loading, @@ -252,6 +253,30 @@ const EmptyWrapper = styled.div` `} `; +const MobileFilterDrawerContent = styled.div` + ${({ theme }) => ` + display: flex; + flex-direction: column; + gap: ${theme.sizeUnit * 4}px; + padding: ${theme.sizeUnit * 2}px; + + /* Make filter inputs stack vertically and full-width */ + > * { + width: 100%; + } + + /* Override inline filter styling for vertical layout */ + .filter-container { + width: 100%; + } + + input[type="text"], + .ant-select { + width: 100% !important; + } + `} +`; + const ViewModeToggle = ({ mode, setMode, @@ -314,6 +339,7 @@ export interface ListViewProps { renderCard?: (row: T & { loading: boolean }) => ReactNode; cardSortSelectOptions?: Array; defaultViewMode?: ViewModeType; + forceViewMode?: ViewModeType; highlightRowId?: number; showThumbnails?: boolean; emptyState?: EmptyStateProps; @@ -329,6 +355,12 @@ export interface ListViewProps { expandable?: Record; /** Content rendered between the filter bar and the table/card body. */ headerContent?: ReactNode; + /** Whether mobile filters drawer is open (controlled externally) */ + mobileFiltersOpen?: boolean; + /** Callback to set mobile filters drawer open state */ + setMobileFiltersOpen?: (open: boolean) => void; + /** Title for the mobile filters drawer */ + mobileFiltersDrawerTitle?: string; } export function ListView({ @@ -350,6 +382,7 @@ export function ListView({ showThumbnails, cardSortSelectOptions, defaultViewMode = 'card', + forceViewMode, highlightRowId, emptyState, columnsForWrapText, @@ -360,6 +393,9 @@ export function ListView({ headerContent, addSuccessToast, addDangerToast, + mobileFiltersOpen = false, + setMobileFiltersOpen, + mobileFiltersDrawerTitle, }: ListViewProps) { const { getTableProps, @@ -386,6 +422,7 @@ export function ListView({ initialFilters: filters, renderCard: Boolean(renderCard), defaultViewMode, + forceViewMode, }); const allowBulkTagActions = bulkTagResourceName && enableBulkTag; const filterable = Boolean(filters.length); @@ -462,11 +499,15 @@ export function ListView({ )}
- {cardViewEnabled && ( + {cardViewEnabled && !forceViewMode && ( )}
- {filterable && ( + {/* When a mobile drawer callback is provided, filters and sort + render inside the drawer instead of inline. Only one + FilterControls instance is ever mounted, so filtersRef and + filterControlsRef always point at the visible instance. */} + {filterable && !setMobileFiltersOpen && ( ({ updateFilterValue={applyFilterValue} /> )} - {viewMode === 'card' && cardSortSelectOptions && ( - setSortBy(value)} - options={cardSortSelectOptions} - /> - )} - {filterable && ( + {viewMode === 'card' && + cardSortSelectOptions && + !setMobileFiltersOpen && ( + setSortBy(value)} + options={cardSortSelectOptions} + /> + )} + {filterable && !setMobileFiltersOpen && ( @@ -660,6 +703,40 @@ export function ListView({ )}
+ + {/* Mobile filter drawer */} + {filterable && setMobileFiltersOpen && ( + setMobileFiltersOpen(false)} + open={mobileFiltersOpen} + width={300} + > + + + {viewMode === 'card' && cardSortSelectOptions && ( + setSortBy(value)} + options={cardSortSelectOptions} + /> + )} + filterControlsRef.current?.clearFilters()} + > + {t('Clear all')} + + + + )} ); } diff --git a/superset-frontend/src/components/ListView/utils.ts b/superset-frontend/src/components/ListView/utils.ts index 12df0e28bb9..5c25c941eac 100644 --- a/superset-frontend/src/components/ListView/utils.ts +++ b/superset-frontend/src/components/ListView/utils.ts @@ -195,6 +195,7 @@ interface UseListViewConfig { initialFilters?: Filter[]; renderCard?: boolean; defaultViewMode?: ViewModeType; + forceViewMode?: ViewModeType; } export function useListViewState({ @@ -207,6 +208,7 @@ export function useListViewState({ initialSort = [], renderCard = false, defaultViewMode = 'card', + forceViewMode, }: UseListViewConfig) { const [query, setQuery] = useQueryParams({ filters: RisonParam, @@ -234,10 +236,19 @@ export function useListViewState({ }; const [viewMode, setViewMode] = useState( - (query.viewMode as ViewModeType) || + // forceViewMode overrides everything (used for mobile) + forceViewMode || + (query.viewMode as ViewModeType) || (renderCard ? defaultViewMode : 'table'), ); + // Update viewMode when forceViewMode changes (e.g., screen resize) + useEffect(() => { + if (forceViewMode) { + setViewMode(forceViewMode); + } + }, [forceViewMode]); + const columnsWithFilter = useMemo( // add exact filter type so filters with falsy values are not filtered out () => columns.map(f => ({ ...f, filter: 'exact' })), diff --git a/superset-frontend/src/components/MobileRouteGuard/MobileRouteGuard.test.tsx b/superset-frontend/src/components/MobileRouteGuard/MobileRouteGuard.test.tsx new file mode 100644 index 00000000000..36ce02b501c --- /dev/null +++ b/superset-frontend/src/components/MobileRouteGuard/MobileRouteGuard.test.tsx @@ -0,0 +1,64 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { MemoryRouter } from 'react-router-dom'; +import { render, screen } from 'spec/helpers/testing-library'; +import { useIsMobile } from 'src/hooks/useIsMobile'; +import MobileRouteGuard from '.'; + +jest.mock('src/hooks/useIsMobile', () => ({ + useIsMobile: jest.fn(), + isMobileConsumptionEnabled: jest.fn().mockReturnValue(true), +})); + +const mockedUseIsMobile = useIsMobile as jest.MockedFunction< + typeof useIsMobile +>; + +const renderGuard = (mobileSupported?: boolean) => + render( + + +
Content
+
+
, + ); + +beforeEach(() => { + mockedUseIsMobile.mockReturnValue(false); +}); + +test('renders children on desktop regardless of mobileSupported', () => { + renderGuard(undefined); + expect(screen.getByTestId('guarded-content')).toBeInTheDocument(); +}); + +test('renders children on mobile when the route is mobileSupported', () => { + mockedUseIsMobile.mockReturnValue(true); + renderGuard(true); + expect(screen.getByTestId('guarded-content')).toBeInTheDocument(); +}); + +test('shows the unsupported screen on mobile for unsupported routes', () => { + mockedUseIsMobile.mockReturnValue(true); + renderGuard(undefined); + expect(screen.queryByTestId('guarded-content')).not.toBeInTheDocument(); + expect( + screen.getByText("This view isn't available on mobile"), + ).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/MobileRouteGuard/index.tsx b/superset-frontend/src/components/MobileRouteGuard/index.tsx new file mode 100644 index 00000000000..26b9a7a0ed3 --- /dev/null +++ b/superset-frontend/src/components/MobileRouteGuard/index.tsx @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { ReactNode } from 'react'; +import { useIsMobile } from 'src/hooks/useIsMobile'; +import MobileUnsupported from 'src/pages/MobileUnsupported'; + +interface MobileRouteGuardProps { + children: ReactNode; + /** + * Whether the wrapped route is part of the mobile consumption + * experience. Set via the `mobileSupported` flag on the route + * definition in `src/views/routes.tsx`. + */ + mobileSupported?: boolean; +} + +/** + * Wraps route content and shows the MobileUnsupported page when a + * non-mobile-friendly route is accessed on a small screen with + * MOBILE_CONSUMPTION_MODE enabled. Growing the viewport past the + * breakpoint unblocks the route automatically. + */ +function MobileRouteGuard({ + children, + mobileSupported, +}: MobileRouteGuardProps) { + const isMobile = useIsMobile(); + + if (!isMobile || mobileSupported) { + return <>{children}; + } + + return ; +} + +export default MobileRouteGuard; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx index 0bbc5850a13..62ba6847f4e 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx @@ -57,6 +57,15 @@ fetchMock.put('glob:*/api/v1/dashboard/*', {}); // Add mock for logging endpoint fetchMock.post('glob:*/log/?*', {}); +// Mock useBreakpoint to return desktop breakpoints (prevents mobile rendering) +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + Grid: { + ...jest.requireActual('antd').Grid, + useBreakpoint: () => ({ xs: true, sm: true, md: true, lg: true, xl: true }), + }, +})); + jest.mock('src/dashboard/actions/dashboardState', () => ({ ...jest.requireActual('src/dashboard/actions/dashboardState'), fetchFaveStar: jest.fn(), @@ -429,6 +438,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: true, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: true, + hasFilters: true, }); const { getByTestId } = setup(); @@ -455,6 +465,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: false, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: true, + hasFilters: true, }); const { getByTestId } = setup(); @@ -481,6 +492,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: true, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: false, + hasFilters: false, }); const { getByTestId } = setup(); @@ -540,6 +552,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: true, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: false, + hasFilters: false, }); const { queryByTestId } = setup(); @@ -553,6 +566,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: true, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: true, + hasFilters: true, }); const { queryByTestId } = setup(); @@ -566,6 +580,7 @@ describe('DashboardBuilder', () => { dashboardFiltersOpen: true, toggleDashboardFiltersOpen: jest.fn(), nativeFiltersEnabled: true, + hasFilters: true, }); const { queryByTestId } = setup({ dashboardState: { ...mockState.dashboardState, editMode: true }, @@ -963,3 +978,85 @@ test('withholds the empty-state edit action while previewing a version', async ( queryByRole('button', { name: 'Edit the dashboard' }), ).not.toBeInTheDocument(); }); + +// Mobile support tests +// Note: The main mobile tests require mocking useBreakpoint to return mobile breakpoints +// which is done at the module level. These tests verify mobile-related component behavior. + +test('should not render filter bar panel on desktop when nativeFiltersEnabled is false', () => { + (useStoredSidebarWidth as jest.Mock).mockImplementation(() => [ + 100, + jest.fn(), + ]); + (fetchFaveStar as jest.Mock).mockReturnValue({ type: 'mock-action' }); + (setActiveTab as jest.Mock).mockReturnValue({ type: 'mock-action' }); + + jest.spyOn(useNativeFiltersModule, 'useNativeFilters').mockReturnValue({ + showDashboard: true, + missingInitialFilters: [], + dashboardFiltersOpen: true, + toggleDashboardFiltersOpen: jest.fn(), + nativeFiltersEnabled: false, + hasFilters: false, + }); + + const { queryByTestId } = render(, { + useRedux: true, + store: storeWithState({ + ...mockState, + dashboardLayout: undoableDashboardLayout, + }), + useDnd: true, + useTheme: true, + useRouter: true, + }); + + // Filter panel should not be present when native filters are disabled + expect(queryByTestId('dashboard-filters-panel')).not.toBeInTheDocument(); +}); + +test('should render dashboard content wrapper', () => { + (useStoredSidebarWidth as jest.Mock).mockImplementation(() => [ + 100, + jest.fn(), + ]); + (fetchFaveStar as jest.Mock).mockReturnValue({ type: 'mock-action' }); + (setActiveTab as jest.Mock).mockReturnValue({ type: 'mock-action' }); + + const { getByTestId } = render(, { + useRedux: true, + store: storeWithState({ + ...mockState, + dashboardLayout: undoableDashboardLayout, + }), + useDnd: true, + useTheme: true, + useRouter: true, + }); + + // Dashboard content wrapper should always be present + expect(getByTestId('dashboard-content-wrapper')).toBeInTheDocument(); +}); + +test('should render header container', () => { + (useStoredSidebarWidth as jest.Mock).mockImplementation(() => [ + 100, + jest.fn(), + ]); + (fetchFaveStar as jest.Mock).mockReturnValue({ type: 'mock-action' }); + (setActiveTab as jest.Mock).mockReturnValue({ type: 'mock-action' }); + + const { queryByTestId } = render(, { + useRedux: true, + store: storeWithState({ + ...mockState, + dashboardLayout: undoableDashboardLayout, + }), + useDnd: true, + useTheme: true, + useRouter: true, + }); + + // Header container should be present + expect(queryByTestId('dashboard-header-container')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index e293bac2167..63ec86719ac 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -38,7 +38,7 @@ import { } from '@superset-ui/core'; import { css, styled, useTheme } from '@apache-superset/core/theme'; import { useDispatch, useSelector } from 'react-redux'; -import { EmptyState, Loading } from '@superset-ui/core/components'; +import { Drawer, EmptyState, 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'; @@ -74,6 +74,7 @@ import { } from 'src/dashboard/util/constants'; import FilterBar from 'src/dashboard/components/nativeFilters/FilterBar'; import { useUiConfig } from 'src/components/UiConfigContext'; +import { isMobileConsumptionEnabled, useIsMobile } from 'src/hooks/useIsMobile'; import ResizableSidebar from 'src/components/ResizableSidebar'; import { BUILDER_SIDEPANEL_WIDTH, @@ -127,6 +128,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; } @@ -440,6 +454,8 @@ const DashboardBuilder = () => { const dispatch = useDispatch(); const uiConfig = useUiConfig(); const theme = useTheme(); + const isNotMobile = !useIsMobile(); + const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false); const dashboardId = useSelector( ({ dashboardInfo }) => `${dashboardInfo.id}`, @@ -551,13 +567,14 @@ const DashboardBuilder = () => { dashboardFiltersOpen, toggleDashboardFiltersOpen, nativeFiltersEnabled, + hasFilters, } = useNativeFilters(); const [containerRef, isSticky] = useElementOnScreen( ELEMENT_ON_SCREEN_OPTIONS, ); - const showFilterBar = !editMode && nativeFiltersEnabled; + const showFilterBar = isNotMobile && !editMode && nativeFiltersEnabled; const offset = FILTER_BAR_HEADER_HEIGHT + @@ -569,6 +586,7 @@ const DashboardBuilder = () => { const draggableStyle = useMemo( () => ({ marginLeft: + !isNotMobile || dashboardFiltersOpen || editMode || !nativeFiltersEnabled || @@ -577,6 +595,7 @@ const DashboardBuilder = () => { : -32, }), [ + isNotMobile, dashboardFiltersOpen, editMode, filterBarOrientation, @@ -608,7 +627,15 @@ const DashboardBuilder = () => { const headerContent = useMemo( () => ( <> - {!hideDashboardHeader && } + {!hideDashboardHeader && ( + setMobileFiltersOpen(true) + : undefined + } + /> + )} {/* Report mode is a one-shot screenshot render (reports, thumbnails), so it must never start a refresh timer that could re-fetch charts mid-capture. */} @@ -641,10 +668,14 @@ const DashboardBuilder = () => { ), [ hideDashboardHeader, + isNotMobile, + nativeFiltersEnabled, + hasFilters, showFilterBar, filterBarOrientation, hideFilterBar, isVersionPreviewActive, + isReport, ], ); @@ -689,6 +720,8 @@ const DashboardBuilder = () => { topLevelTabs, uiConfig.hideTab, uiConfig.hideNav, + isNotMobile, + theme, ], ); @@ -923,6 +956,36 @@ const DashboardBuilder = () => { `} /> )} + {/* Mobile filters drawer */} + {!isNotMobile && nativeFiltersEnabled && ( + setMobileFiltersOpen(false)} + open={mobileFiltersOpen} + width="85vw" + styles={{ + body: { + padding: 0, + display: 'flex', + flexDirection: 'column', + }, + }} + > + {}, + width: 300, + height: '100%', + offset: 0, + mobileMode: true, + }} + hidden={false} + /> + + )} ); }; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardWrapper.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardWrapper.tsx index f94490c9b15..de6565b4d51 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardWrapper.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardWrapper.tsx @@ -25,6 +25,7 @@ import { useSelector } from 'react-redux'; import { useDragDropManager } from 'react-dnd'; import classNames from 'classnames'; import { debounce } from 'lodash-es'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; const StyledDiv = styled.div` ${({ theme }) => css` @@ -110,6 +111,22 @@ const StyledDiv = styled.div` i.warning { color: ${theme.colorWarning}; } + + /* Mobile consumption mode: show the full chart title without + truncation (controls and links are render-gated in SliceHeader) */ + ${ + isMobileConsumptionEnabled() + ? `@media (max-width: ${theme.screenSMMax}px) { + [data-test='slice-header'] .header-title { + -webkit-line-clamp: unset; + display: block; + white-space: normal; + overflow: visible; + text-overflow: unset; + } + }` + : '' + } `} `; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts index a6de9e390c8..67ed1a81c18 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts @@ -121,5 +121,6 @@ export const useNativeFilters = () => { dashboardFiltersOpen, toggleDashboardFiltersOpen, nativeFiltersEnabled, + hasFilters: filterValues.length > 0, }; }; diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx index 6a6e5e419ed..1c06b11c30d 100644 --- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx @@ -186,6 +186,15 @@ const recordError = jest.fn(); const setPaused = jest.fn(); const setPausedByTab = jest.fn(); +// Mock useBreakpoint to return desktop breakpoints (prevents mobile rendering) +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + Grid: { + ...jest.requireActual('antd').Grid, + useBreakpoint: () => ({ xs: true, sm: true, md: true, lg: true, xl: true }), + }, +})); + jest.mock('src/hooks/useUnsavedChangesPrompt', () => ({ useUnsavedChangesPrompt: jest.fn(), })); diff --git a/superset-frontend/src/dashboard/components/Header/index.tsx b/superset-frontend/src/dashboard/components/Header/index.tsx index c0ad92a2e69..576580adb63 100644 --- a/superset-frontend/src/dashboard/components/Header/index.tsx +++ b/superset-frontend/src/dashboard/components/Header/index.tsx @@ -23,7 +23,12 @@ import { FeatureFlag, getExtensionsRegistry, } from '@superset-ui/core'; -import { styled, css, SupersetTheme } from '@apache-superset/core/theme'; +import { + styled, + css, + SupersetTheme, + useTheme, +} from '@apache-superset/core/theme'; import { t } from '@apache-superset/core/translation'; import { Global } from '@emotion/react'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; @@ -37,6 +42,7 @@ import { UnsavedChangesModal, } from '@superset-ui/core/components'; import { findPermission } from 'src/utils/findPermission'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import { safeStringify } from 'src/utils/safeStringify'; import Subject from 'src/types/Subject'; import { DashboardLayout, RootState } from 'src/dashboard/types'; @@ -220,8 +226,14 @@ const discardChanges = () => { window.location.assign(url); }; -const Header = (): JSX.Element => { +interface HeaderComponentProps { + onOpenMobileFilters?: () => void; +} + +const Header = ({ onOpenMobileFilters }: HeaderComponentProps): JSX.Element => { const dispatch = useDispatch(); + const theme = useTheme(); + const isMobile = useIsMobile(); const [didNotifyMaxUndoHistoryToast, setDidNotifyMaxUndoHistoryToast] = useState(false); const [emphasizeUndo, setEmphasizeUndo] = useState(false); @@ -643,7 +655,8 @@ const Header = (): JSX.Element => { const titlePanelAdditionalItems = useMemo( () => [ - !editMode && ( + // The kebab menu's "Refresh dashboard" item covers this on mobile + !editMode && !isMobile && ( ), !editMode && ( @@ -652,7 +665,7 @@ const Header = (): JSX.Element => { onTogglePause={handlePauseToggle} /> ), - !editMode && ( + !editMode && !isMobile && ( { userCanSave={userCanSaveAs} /> ), - !editMode && !isEmbedded && metadataBar, + !editMode && !isEmbedded && !isMobile && metadataBar, ], [ boundActionCreators.savePublished, dashboardInfo.id, editMode, + isMobile, metadataBar, isEmbedded, isPublished, @@ -764,7 +778,7 @@ const Header = (): JSX.Element => { ) : (
{NavExtension && } - {userCanEdit && !isEmbedded && ( + {userCanEdit && !isEmbedded && !isMobile && ( + ) + } titlePanelAdditionalItems={titlePanelAdditionalItems} rightPanelAdditionalItems={rightPanelAdditionalItems} menuDropdownProps={{ @@ -855,7 +889,7 @@ const Header = (): JSX.Element => { disabled: isVersionPreviewActive, }} additionalActionsMenu={menu} - showFaveStar={Boolean(user?.userId && dashboardInfo?.id)} + showFaveStar={!!(user?.userId && dashboardInfo?.id && !isMobile)} showTitlePanelItems /> {showingPropertiesModal && ( diff --git a/superset-frontend/src/dashboard/components/Header/types.ts b/superset-frontend/src/dashboard/components/Header/types.ts index d5fee210d37..c86d0535b3d 100644 --- a/superset-frontend/src/dashboard/components/Header/types.ts +++ b/superset-frontend/src/dashboard/components/Header/types.ts @@ -43,6 +43,10 @@ export interface HeaderDropdownProps { forceRefreshAllCharts: () => unknown; hasUnsavedChanges: boolean; isLoading: boolean; + isMobile?: boolean; + isStarred?: boolean; + isPublished?: boolean; + saveFaveStar?: (id: number, isStarred: boolean) => void; layout: Layout; onSave: (...args: unknown[]) => unknown; refreshFrequency: number; diff --git a/superset-frontend/src/dashboard/components/Header/useHeaderActionsDropdownMenu.tsx b/superset-frontend/src/dashboard/components/Header/useHeaderActionsDropdownMenu.tsx index 6aa8ab247ab..562dbf10f72 100644 --- a/superset-frontend/src/dashboard/components/Header/useHeaderActionsDropdownMenu.tsx +++ b/superset-frontend/src/dashboard/components/Header/useHeaderActionsDropdownMenu.tsx @@ -39,6 +39,7 @@ import { MenuKeys, RootState } from 'src/dashboard/types'; import { HeaderDropdownProps } from 'src/dashboard/components/Header/types'; import { usePermissions } from 'src/hooks/usePermissions'; import { openVersionHistoryPanel } from 'src/features/versionHistory/reducer'; +import getUserName from 'src/utils/getUserName'; export const useHeaderActionsMenu = ({ customCss, @@ -58,6 +59,10 @@ export const useHeaderActionsMenu = ({ userCanCurate, userCanExport, isLoading, + isMobile, + isStarred, + isPublished, + saveFaveStar, lastModifiedTime, addSuccessToast, addDangerToast, @@ -123,6 +128,11 @@ export const useHeaderActionsMenu = ({ case MenuKeys.VersionHistory: dispatch(openVersionHistoryPanel('dashboard')); break; + case 'toggle-favorite': + if (saveFaveStar && isStarred !== undefined) { + saveFaveStar(dashboardId, isStarred); + } + break; default: break; } @@ -135,6 +145,9 @@ export const useHeaderActionsMenu = ({ showRefreshModal, manageEmbedded, dispatch, + saveFaveStar, + dashboardId, + isStarred, history, location, ], @@ -212,6 +225,52 @@ export const useHeaderActionsMenu = ({ const menuItems: MenuItem[] = []; + // Mobile-only: show dashboard info items in menu + if (isMobile && !editMode) { + // Favorite toggle + if (saveFaveStar) { + menuItems.push({ + key: 'toggle-favorite', + label: isStarred ? t('Remove from favorites') : t('Add to favorites'), + }); + } + + // Published status + menuItems.push({ + key: 'status-info', + label: isPublished ? t('Status: Published') : t('Status: Draft'), + disabled: true, + }); + + // Editor info + const editorNames = dashboardInfo?.editors?.length + ? dashboardInfo.editors + .map((editor: { label?: string }) => editor.label) + .filter(Boolean) + .join(', ') + : t('None'); + menuItems.push({ + key: 'owner-info', + label: t('Owner: %(names)s', { names: editorNames }), + disabled: true, + }); + + // Last modified + const modifiedBy = + getUserName(dashboardInfo?.changed_by) || t('Not available'); + const modifiedDate = dashboardInfo?.changed_on_delta_humanized || ''; + menuItems.push({ + key: 'modified-info', + label: t('Modified %(date)s by %(user)s', { + date: modifiedDate, + user: modifiedBy, + }), + disabled: true, + }); + + menuItems.push({ type: 'divider' }); + } + // Refresh dashboard if (!editMode) { menuItems.push({ @@ -231,8 +290,8 @@ export const useHeaderActionsMenu = ({ }); } - // Toggle fullscreen - if (!editMode && !isEmbedded) { + // Toggle fullscreen (hide on mobile) + if (!editMode && !isEmbedded && !isMobile) { menuItems.push({ key: MenuKeys.ToggleFullscreen, label: getUrlParam(URL_PARAMS.standalone) @@ -300,15 +359,15 @@ export const useHeaderActionsMenu = ({ // Only add divider if there are items after it const hasItemsAfterDivider = - (!editMode && reportMenuItem) || + (!editMode && reportMenuItem && !isMobile) || (editMode && !isEmpty(dashboardInfo?.metadata?.filter_scopes)); if (hasItemsAfterDivider) { menuItems.push({ type: 'divider' }); } - // Report dropdown - if (!editMode && reportMenuItem) { + // Report dropdown (hide on mobile) + if (!editMode && reportMenuItem && !isMobile) { menuItems.push(reportMenuItem); } @@ -357,11 +416,15 @@ export const useHeaderActionsMenu = ({ expandedSlices, handleMenuClick, isLoading, + isMobile, + isPublished, + isStarred, lastModifiedTime, layout, onSave, refreshFrequency, reportMenuItem, + saveFaveStar, shareMenuItems, shouldPersistRefreshFrequency, userCanCurate, diff --git a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx index 615e6b4e694..ccf490f087a 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx @@ -43,6 +43,7 @@ import { isEmbedded } from 'src/dashboard/util/isEmbedded'; import { Tooltip, EditableTitle, Icons } from '@superset-ui/core/components'; import { useSelector } from 'react-redux'; import SliceHeaderControls from 'src/dashboard/components/SliceHeaderControls'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import { SliceHeaderControlsProps } from 'src/dashboard/components/SliceHeaderControls/types'; import MemoizedFiltersBadge from 'src/dashboard/components/FiltersBadge'; import MemoizedCustomizationsBadge from 'src/dashboard/components/CustomizationsBadge'; @@ -229,7 +230,9 @@ const SliceHeader = forwardRef( 0, ); - const canExplore = !editMode && supersetCanExplore; + // Consumption-only mobile mode: no explore link, no chart controls + const isMobile = useIsMobile(); + const canExplore = !editMode && supersetCanExplore && !isMobile; const showRowLimitWarning = shouldShowRowLimitWarning && sqlRowCount >= rowLimit && rowLimit > 0; @@ -355,7 +358,7 @@ const SliceHeader = forwardRef( } /> )} - {!uiConfig.hideChartControls && ( + {!uiConfig.hideChartControls && !isMobile && ( { const theme = useTheme(); + const isMobile = useIsMobile(); const fullSizeStyle = css` && { position: fixed !important; @@ -167,6 +174,14 @@ const ChartHolder = ({ }, [outlinedComponentId]); const widthMultiple = useMemo(() => { + // Mobile consumption mode stacks charts vertically at full width, so + // report the full column count. This keeps the pixel width handed to the + // chart plugin (and to ResizableContainer's inline size) in sync with the + // stacked layout instead of the desktop grid fraction. + if (isMobile && !editMode) { + return GRID_COLUMN_COUNT; + } + const columnParentWidth = getComponentById( parentComponent.parents?.find(parent => parent.startsWith(COLUMN_TYPE)), )?.meta?.width; @@ -182,11 +197,29 @@ const ChartHolder = ({ }, [ component, getComponentById, + isMobile, + editMode, parentComponent.meta.width, parentComponent.parents, parentComponent.type, ]); + // Grid units of height for this chart. In mobile consumption mode the + // authored desktop height is capped to the viewport (minus app chrome) so + // tall charts don't dominate the single-column stacked layout. Used for + // both the ResizableContainer shell and the height handed to the plugin, + // so the two can't disagree. + const heightMultiple = useMemo(() => { + const authoredHeight = component.meta.height ?? GRID_MIN_ROW_UNITS; + if (isMobile && !editMode) { + const maxUnits = Math.floor( + (window.innerHeight - MOBILE_CHROME_HEIGHT) / GRID_BASE_UNIT, + ); + return Math.max(GRID_MIN_ROW_UNITS, Math.min(authoredHeight, maxUnits)); + } + return authoredHeight; + }, [component.meta.height, isMobile, editMode]); + const { chartWidth, chartHeight } = useMemo(() => { let width = 0; let height = 0; @@ -200,16 +233,14 @@ const ChartHolder = ({ (widthMultiple - 1) * GRID_GUTTER_SIZE - CHART_MARGIN, ); - height = Math.floor( - (component.meta.height ?? 0) * GRID_BASE_UNIT - CHART_MARGIN, - ); + height = Math.floor(heightMultiple * GRID_BASE_UNIT - CHART_MARGIN); } return { chartWidth: width, chartHeight: height, }; - }, [columnWidth, component, isFullSize, widthMultiple]); + }, [columnWidth, heightMultiple, isFullSize, widthMultiple]); const handleDeleteComponent = useCallback(() => { deleteComponent(id, parentId); @@ -250,7 +281,7 @@ const ChartHolder = ({ widthStep={columnWidth} widthMultiple={widthMultiple} heightStep={GRID_BASE_UNIT} - heightMultiple={component.meta.height ?? GRID_MIN_ROW_UNITS} + heightMultiple={heightMultiple} minWidthMultiple={GRID_MIN_COLUMN_COUNT} minHeightMultiple={GRID_MIN_ROW_UNITS} maxWidthMultiple={availableColumnCount + widthMultiple} @@ -342,12 +373,12 @@ const ChartHolder = ({ ), [ component.id, - component.meta.height, component.meta.chartId, component.meta.sliceNameOverride, component.meta.sliceName, parentComponent.type, columnWidth, + heightMultiple, widthMultiple, availableColumnCount, onResizeStart, diff --git a/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx b/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx index b644a65fef8..dcfa67ee9d2 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Row/Row.tsx @@ -37,6 +37,7 @@ import { Droppable, } from 'src/dashboard/components/dnd/DragDroppable'; import DragHandle from 'src/dashboard/components/dnd/DragHandle'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; import DashboardComponent from 'src/dashboard/containers/DashboardComponent'; import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton'; import HoverMenu from 'src/dashboard/components/menu/HoverMenu'; @@ -120,6 +121,27 @@ const GridRow = styled.div<{ editMode: boolean }>` &.grid-row--empty { min-height: ${theme.sizeUnit * 25}px; } + + ${ + isMobileConsumptionEnabled() && + css` + @media (max-width: ${theme.screenSMMax}px) { + flex-direction: column; + + & > :not(.hover-menu) { + width: 100% !important; + margin-right: 0 !important; + } + + /* Stacked children get the same vertical gutter GridContent puts + between rows and Column puts between its children, so spacing + stays uniform across the whole stacked layout */ + & > :not(.hover-menu):not(:last-child) { + margin-bottom: ${theme.sizeUnit * 4}px; + } + } + ` + } `} `; diff --git a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx index 9e6cf9c423e..d5a4045f9a8 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/TabsRenderer/TabsRenderer.tsx @@ -25,7 +25,8 @@ import { useRef, useState, } from 'react'; -import { styled } from '@apache-superset/core/theme'; +import { css, styled } from '@apache-superset/core/theme'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; import { LineEditableTabs, TabsProps as AntdTabsProps, @@ -87,6 +88,58 @@ const StyledTabsContainer = styled.div<{ isDragging?: boolean }>` display: none !important; } `} + + /* Sticky tabs on mobile (consumption mode) */ + ${({ theme }) => + isMobileConsumptionEnabled() && + css` + @media (max-width: ${theme.screenSMMax}px) { + .ant-tabs-nav { + position: sticky; + 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" + menu is a poor touch target and duplicates half-clipped tabs. + antd's tab nav supports touch-drag scrolling natively and shows + edge shadows (ping classes) when tabs overflow. */ + .ant-tabs-nav-operations { + display: none !important; + } + } + `} `; export interface TabItem { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx index 4e1ea440ad8..7cb98287282 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx @@ -32,7 +32,7 @@ import { import { useSelector } from 'react-redux'; import cx from 'classnames'; import { t } from '@apache-superset/core/translation'; -import { styled, useTheme } from '@apache-superset/core/theme'; +import { css, styled, useTheme } from '@apache-superset/core/theme'; import { RootState } from 'src/dashboard/types'; import { DataMaskStateWithId } from '@superset-ui/core'; import { Icons } from '@superset-ui/core/components/Icons'; @@ -145,6 +145,7 @@ const VerticalFilterBar: FC = ({ onPendingCustomizationDataMaskChange, toggleFiltersBar, width, + mobileMode, }) => { const theme = useTheme(); const [isScrolling, setIsScrolling] = useState(false); @@ -264,32 +265,55 @@ const VerticalFilterBar: FC = ({ {...getFilterBarTestId()} className={cx({ open: filtersOpen })} width={width} + css={ + mobileMode && + css` + width: 100%; + &.open { + width: 100%; + } + ` + } > - + + + + )} + - - - - -
+ {!mobileMode &&
} {!isInitialized ? (
= ({ } toggleFiltersBar={verticalConfig.toggleFiltersBar} width={verticalConfig.width} + mobileMode={verticalConfig.mobileMode} clearAllTriggers={clearAllTriggers} onClearAllComplete={handleClearAllComplete} /> diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts index 5354d7b7e45..8bb2cc0ddc5 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/types.ts @@ -53,6 +53,11 @@ interface VerticalBarConfig { offset: number; toggleFiltersBar: any; width: number; + /** + * Renders the bar for a mobile drawer: full-width, in normal document + * flow, without the header or the collapsed-bar affordance. + */ + mobileMode?: boolean; } export interface FiltersBarProps { diff --git a/superset-frontend/src/dashboard/components/resizable/ResizableContainer.tsx b/superset-frontend/src/dashboard/components/resizable/ResizableContainer.tsx index a0cd0c3f95e..a84631b61c5 100644 --- a/superset-frontend/src/dashboard/components/resizable/ResizableContainer.tsx +++ b/superset-frontend/src/dashboard/components/resizable/ResizableContainer.tsx @@ -35,6 +35,7 @@ import { BottomResizeHandle, BottomRightResizeHandle, } from './ResizableHandle'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; import resizableConfig from '../../util/resizableConfig'; import { GRID_BASE_UNIT, @@ -178,6 +179,21 @@ const StyledResizable = styled(Resizable)` & .resizable-container-handle--bottom { bottom: 0 !important; } + + /* Mobile consumption mode stacks all grid components full-width. + !important is required to beat re-resizable's inline width, which is + sized for the desktop grid (Markdown, Column, and other non-chart + components don't get the JS-level mobile width that ChartHolder + computes). */ + ${({ theme }) => + isMobileConsumptionEnabled() && + css` + @media (max-width: ${theme.screenSMMax}px) { + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + } + `} `; export default function ResizableContainer({ diff --git a/superset-frontend/src/features/dashboards/DashboardCard.tsx b/superset-frontend/src/features/dashboards/DashboardCard.tsx index 11cf3ca86c7..642b55cf010 100644 --- a/superset-frontend/src/features/dashboards/DashboardCard.tsx +++ b/superset-frontend/src/features/dashboards/DashboardCard.tsx @@ -35,6 +35,7 @@ import { SubjectPile } from 'src/features/subjects/SubjectPile'; import { KebabMenuButton } from 'src/components'; import { isUserEditorOrAdmin } from 'src/dashboard/util/permissionUtils'; import type { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; +import { useIsMobile } from 'src/hooks/useIsMobile'; const menuItemButtonCss = css` appearance: none; @@ -76,6 +77,7 @@ function DashboardCard({ onDelete, }: DashboardCardProps) { const userId = user?.userId; + const isMobile = useIsMobile(); const history = useHistory(); const canEdit = hasPerm('can_write'); @@ -206,10 +208,12 @@ function DashboardCard({ isStarred={favoriteStatus} /> )} - + {!isMobile && ( + + )} } /> diff --git a/superset-frontend/src/features/home/ActivityTable.tsx b/superset-frontend/src/features/home/ActivityTable.tsx index e71006a3adb..57167225bbc 100644 --- a/superset-frontend/src/features/home/ActivityTable.tsx +++ b/superset-frontend/src/features/home/ActivityTable.tsx @@ -32,6 +32,7 @@ import { } from 'src/views/CRUD/utils'; import { Chart } from 'src/types/Chart'; import { Icons } from '@superset-ui/core/components/Icons'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import SubMenu from './SubMenu'; import EmptyState from './EmptyState'; import { WelcomeTable, RecentActivity } from './types'; @@ -74,6 +75,12 @@ const Styles = styled.div` const UNTITLED = t('[Untitled]'); const UNKNOWN_TIME = t('Unknown'); +// Dashboards are the only activity entities viewable in the mobile +// consumption experience; charts and saved queries link to unsupported views +const isDashboardEntity = (entity: ActivityObject) => + 'dashboard_title' in entity || + ('item_type' in entity && entity.item_type === 'dashboard'); + const getEntityTitle = (entity: ActivityObject) => { if ('dashboard_title' in entity) return entity.dashboard_title || UNTITLED; if ('slice_name' in entity) return entity.slice_name || UNTITLED; @@ -125,6 +132,7 @@ export default function ActivityTable({ }: ActivityProps) { const [editedCards, setEditedCards] = useState(); const [isFetchingEditedCards, setIsFetchingEditedCards] = useState(false); + const isMobile = useIsMobile(); useEffect(() => { let isMounted = true; @@ -178,12 +186,16 @@ export default function ActivityTable({ }, }); } - const renderActivity = () => { - const activities = - (activeChild === TableTab.Edited - ? editedCards - : activityData[activeChild as keyof ActivityData]) ?? []; - return activities.map((entity: ActivityObject) => { + const rawActivities = + (activeChild === TableTab.Edited + ? editedCards + : activityData[activeChild as keyof ActivityData]) ?? []; + const activities = isMobile + ? rawActivities.filter(isDashboardEntity) + : rawActivities; + + const renderActivity = () => + activities.map((entity: ActivityObject) => { const url = getEntityUrl(entity); const lastActionOn = getEntityLastActionOn(entity); return ( @@ -201,7 +213,6 @@ export default function ActivityTable({ ); }); - }; if ((isFetchingEditedCards && !editedCards) || isFetchingActivityData) { return ; @@ -213,8 +224,7 @@ export default function ActivityTable({ tabs={tabs} backgroundColor="transparent" /> - {Number(activityData[activeChild as keyof ActivityData]?.length) > 0 || - (activeChild === TableTab.Edited && editedCards?.length) ? ( + {activities.length > 0 ? ( {renderActivity()} diff --git a/superset-frontend/src/features/home/EmptyState.tsx b/superset-frontend/src/features/home/EmptyState.tsx index c3802b74798..28eec15ad17 100644 --- a/superset-frontend/src/features/home/EmptyState.tsx +++ b/superset-frontend/src/features/home/EmptyState.tsx @@ -24,6 +24,7 @@ import { TableTab } from 'src/views/CRUD/types'; import { t } from '@apache-superset/core/translation'; import { styled } from '@apache-superset/core/theme'; import { navigateTo } from 'src/utils/navigationUtils'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import { WelcomeTable } from './types'; const EmptyContainer = styled.div` @@ -76,12 +77,19 @@ export interface EmptyStateProps { } export default function EmptyState({ tableName, tab }: EmptyStateProps) { + const isMobile = useIsMobile(); const getActionButton = () => { if (tableName === WelcomeTable.Recents) { return null; } const isFavorite = tab === TableTab.Favorite; + + // Creation flows aren't part of the mobile consumption experience; + // only offer the "See all ..." navigation there + if (isMobile && !isFavorite) { + return null; + } const buttonText = isFavorite ? LABELS.viewAll[tableName] : LABELS.create[tableName]; @@ -111,7 +119,7 @@ export default function EmptyState({ tableName, tab }: EmptyStateProps) { {getActionButton()} diff --git a/superset-frontend/src/features/home/Menu.tsx b/superset-frontend/src/features/home/Menu.tsx index b78a0dff5a4..b34b90beb94 100644 --- a/superset-frontend/src/features/home/Menu.tsx +++ b/superset-frontend/src/features/home/Menu.tsx @@ -29,6 +29,7 @@ import { NavLink, useLocation } from 'react-router-dom'; import { Icons } from '@superset-ui/core/components/Icons'; import { Typography } from '@superset-ui/core/components/Typography'; import { useUiConfig } from 'src/components/UiConfigContext'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import { URL_PARAMS } from 'src/constants'; import { MenuObjectChildProps, @@ -199,6 +200,7 @@ export function Menu({ isFrontendRoute = () => false, }: MenuProps) { const screens = useBreakpoint(); + const isMobile = useIsMobile(); const uiConfig = useUiConfig(); const theme = useTheme(); // screens.md is undefined on the first render before breakpoints are measured; @@ -409,7 +411,18 @@ export function Menu({ aria-label={t('Main navigation')} > - + {/* Mobile: left placeholder for future icon */} + {isMobile && } + {!brand.hide_logo && ( {brand.text} )} - { - const props = { - ...item, - label: t(item.label), - isFrontendRoute: isFrontendRoute(item.url), - childs: item.childs?.map(c => { - if (typeof c === 'string') { - return c; - } + {/* Consumption mode: hide nav items on mobile (drawer holds them) */} + {!isMobile && ( + { + const props = { + ...item, + label: t(item.label), + isFrontendRoute: isFrontendRoute(item.url), + childs: item.childs?.map(c => { + if (typeof c === 'string') { + return c; + } - return { - ...c, - isFrontendRoute: isFrontendRoute(c.url), - }; - }), - }; + return { + ...c, + isFrontendRoute: isFrontendRoute(c.url), + }; + }), + }; - return buildMenuItem(props); - })} - /> + return buildMenuItem(props); + })} + /> + )} - + diff --git a/superset-frontend/src/features/home/RightMenu.test.tsx b/superset-frontend/src/features/home/RightMenu.test.tsx index d57f676cd17..1adaabf9d63 100644 --- a/superset-frontend/src/features/home/RightMenu.test.tsx +++ b/superset-frontend/src/features/home/RightMenu.test.tsx @@ -50,6 +50,15 @@ jest.mock('react-redux', () => ({ useSelector: jest.fn(), })); +// Mock useBreakpoint to return desktop breakpoints (prevents mobile menu rendering) +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + Grid: { + ...jest.requireActual('antd').Grid, + useBreakpoint: () => ({ xs: true, sm: true, md: true, lg: true, xl: true }), + }, +})); + jest.mock('src/features/databases/DatabaseModal', () => { const DatabaseModal = () => ; DatabaseModal.displayName = 'DatabaseModal'; diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx index 2207f9d6c6d..65772b186b4 100644 --- a/superset-frontend/src/features/home/RightMenu.tsx +++ b/superset-frontend/src/features/home/RightMenu.tsx @@ -51,9 +51,16 @@ import { Icons, Typography, TelemetryPixel, + Drawer, + Button, } from '@superset-ui/core/components'; import type { ItemType, MenuItem } from '@superset-ui/core/components/Menu'; -import { ensureAppRoot, stripAppRoot } from 'src/utils/navigationUtils'; +import { + ensureAppRoot, + navigateTo, + stripAppRoot, +} from 'src/utils/navigationUtils'; +import { useIsMobile } from 'src/hooks/useIsMobile'; import { isEmbedded } from 'src/dashboard/util/isEmbedded'; import { findPermission } from 'src/utils/findPermission'; import { isUserAdmin } from 'src/dashboard/util/permissionUtils'; @@ -117,6 +124,7 @@ const RightMenu = ({ navbarRight, isFrontendRoute, environmentTag, + menu, setQuery, }: RightMenuProps & { setQuery: ({ @@ -128,6 +136,8 @@ const RightMenu = ({ }) => void; }) => { const theme = useTheme(); + const isMobile = useIsMobile(); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const user = useSelector( state => state.user, ); @@ -642,6 +652,64 @@ const RightMenu = ({ handleLogout, ]); + // Build mobile menu items - consumption only (no create/admin actions) + const mobileMenuItems = useMemo(() => { + const items: MenuItem[] = []; + + // Add Dashboards link at top (from main menu) + // Match on the FAB-internal `name`, which is stable across locales + // (`label` is translated and would break in non-English deployments) + const dashboardsMenu = menu?.find(item => item.name === 'Dashboards'); + if (dashboardsMenu) { + const dashboardUrl = dashboardsMenu.url || '/dashboard/list/'; + items.push({ + key: 'dashboards', + label: isFrontendRoute(dashboardUrl) ? ( + {t('Dashboards')} + ) : ( + + {t('Dashboards')} + + ), + icon: , + }); + } + + // Add theme menu (flatten children directly) + menuItems.forEach(item => { + if (!item || !('key' in item)) return; + + // Only include theme-sub-menu and language picker + if (item.key === 'theme-sub-menu' || item.key === 'language-picker') { + items.push({ type: 'divider', key: `divider-before-${item.key}` }); + + if ('children' in item && item.children) { + // Theme menu already has a nested group, so just add its children directly + item.children.forEach(child => { + items.push(child); + }); + } else { + items.push(item); + } + } + + // Extract user-related items from settings + if (item.key === 'settings' && 'children' in item && item.children) { + item.children.forEach(child => { + if (!child || !('key' in child)) return; + + // Only include user-section and about-section + if (child.key === 'user-section' || child.key === 'about-section') { + items.push({ type: 'divider', key: `divider-before-${child.key}` }); + items.push(child); + } + }); + } + }); + + return items; + }, [menu, menuItems, isFrontendRoute]); + return ( {canDatabase && ( @@ -702,48 +770,98 @@ const RightMenu = ({ ); })()} - + + setMobileMenuOpen(false)} + open={mobileMenuOpen} + width={280} + styles={{ + header: { display: 'none' }, + body: { padding: 0 }, + }} + > + { + 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) { + navigateTo(navbarRight.user_info_url); + return; + } + if (info.key === 'logout' && navbarRight.user_logout_url) { + navigateTo(navbarRight.user_logout_url); + return; + } + setMobileMenuOpen(false); + }} + items={mobileMenuItems} + css={css` + border-inline-end: none !important; + `} + /> + + + )} + {/* Desktop: horizontal menu */} + {!isMobile && ( + + `} + selectable={false} + mode="horizontal" + onClick={handleMenuSelection} + onOpenChange={onMenuOpen} + disabledOverflow + items={menuItems} + /> + )} {navbarRight.documentation_url && ( <> { userEvent.click(testButton); expect(mockFunc).toHaveBeenCalled(); }); + +// Mobile support tests +test('should render leftIcon when provided', async () => { + setup({ + leftIcon: ( + + ), + }); + expect(await screen.findByTestId('left-icon-button')).toBeInTheDocument(); +}); + +test('should render rightIcon when provided', async () => { + setup({ + rightIcon: ( + + ), + }); + expect(await screen.findByTestId('right-icon-button')).toBeInTheDocument(); +}); + +test('should render both leftIcon and rightIcon together', async () => { + setup({ + leftIcon: Left, + rightIcon: Right, + }); + expect(await screen.findByTestId('mobile-left')).toBeInTheDocument(); + expect(await screen.findByTestId('mobile-right')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/features/home/SubMenu.tsx b/superset-frontend/src/features/home/SubMenu.tsx index c87738f0e30..471071453c3 100644 --- a/superset-frontend/src/features/home/SubMenu.tsx +++ b/superset-frontend/src/features/home/SubMenu.tsx @@ -37,6 +37,7 @@ import { } from '@superset-ui/core/components'; import { Icons } from '@superset-ui/core/components/Icons'; import { MenuObjectProps } from 'src/types/bootstrapTypes'; +import { isMobileConsumptionEnabled } from 'src/hooks/useIsMobile'; import { Typography } from '@superset-ui/core/components/Typography'; const StyledHeader = styled.div<{ backgroundColor?: string }>` @@ -109,13 +110,44 @@ const StyledHeader = styled.div<{ backgroundColor?: string }>` .btn-link { padding: 10px 0; } - @media (max-width: 767px) { - .header, - .nav-right { - position: relative; - margin-left: ${({ theme }) => theme.sizeUnit * 2}px; - } - } + ${({ theme }) => + isMobileConsumptionEnabled() + ? css` + @media (max-width: ${theme.screenSMMax}px) { + .header { + position: relative; + margin-left: 0; + flex: 1; + text-align: center; + } + + /* Consumption mode: hide all buttons on mobile */ + .nav-right, + .nav-right-collapse { + display: none !important; + } + + /* Compact horizontal tabs on mobile (segmented-control style) */ + .menu > .ant-menu { + padding-left: 0; + + .ant-menu-item { + padding: ${theme.sizeUnit}px ${theme.sizeUnit * 2}px; + margin-right: ${theme.sizeUnit / 2}px; + font-size: ${theme.fontSizeSM}px; + } + } + } + ` + : css` + @media (max-width: ${theme.screenSMMax}px) { + .header, + .nav-right { + position: relative; + margin-left: ${theme.sizeUnit * 2}px; + } + } + `} `; const styledDisabled = (theme: SupersetTheme) => css` @@ -165,6 +197,10 @@ export interface SubMenuProps { dropDownLinks?: Array; backgroundColor?: string; children?: ReactNode; + /** Left icon for mobile - shown before the header */ + leftIcon?: ReactNode; + /** Right icon for mobile - shown after the header */ + rightIcon?: ReactNode; } const SubMenuComponent: FunctionComponent = props => { @@ -186,8 +222,16 @@ const SubMenuComponent: FunctionComponent = props => { function handleResize() { if (!isMounted) return; - if (window.innerWidth <= 767) setMenu('inline'); - else setMenu('horizontal'); + // In consumption mode the tabs stay horizontal on mobile (the CSS + // renders them compact); otherwise fall back to the inline layout. + if ( + !isMobileConsumptionEnabled() && + window.innerWidth <= theme.screenSMMax + ) { + setMenu('inline'); + } else { + setMenu('horizontal'); + } if ( props.buttons && @@ -211,13 +255,15 @@ const SubMenuComponent: FunctionComponent = props => { resize.cancel(); window.removeEventListener('resize', resize); }; - }, [props.buttons]); + }, [props.buttons, theme.screenSMMax]); return (