diff --git a/SIP.md b/SIP.md index 8be321d732c..d73bafcd000 100644 --- a/SIP.md +++ b/SIP.md @@ -196,7 +196,26 @@ Each phase brings its own tests; the cumulative bar: 3 passing tests on `setComponentThemeId`: preserves other meta keys + sets numeric `themeId`; stores explicit `null` for the clear path; no-op when the component id isn't in the layout. -- _(Phase 4)_ — pending. +- _(Phase 4)_ — in progress. + - **Chart (4a)**: ✅ landed locally. End-to-end demo on Chart works + now: `SliceHeaderControls` has a new "Apply theme" item (gated on + dashboard edit mode); clicking it opens the Phase-3 + `ThemeSelectorModal` keyed to the component's layoutId; on save the + Phase-3 action updates `meta.themeId`; the Phase-1 + `ComponentThemeProvider` (already wrapping ChartHolder) re-resolves + and re-renders the chart with the new theme tokens. The full + Instance → Dashboard → Tab → Row/Col → Chart inheritance chain is + functionally complete for Chart. + + Open follow-ups for the **Markdown / Row / Column / Tabs** PRs: + - Each gets the menu-pattern conversion (`MarkdownModeDropdown`, + gear icon, none → shared `ComponentHeaderControls`). + - Each wraps its body in ``. + - Each mounts a `` with an "Apply theme" menu + item that opens it. + - Each per-component PR can be reviewed in isolation for the menu/UX + change without dragging in the theming framework changes (those + are already merged in Phases 1-3). ### Phase 1 status diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx index 508b83c0bc1..12b160edba4 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx @@ -57,6 +57,7 @@ import { useDrillDetailMenuItems } from 'src/components/Chart/useDrillDetailMenu import { LOG_ACTIONS_CHART_DOWNLOAD_AS_IMAGE } from 'src/logger/LogUtils'; import { MenuKeys, RootState } from 'src/dashboard/types'; import DrillDetailModal from 'src/components/Chart/DrillDetail/DrillDetailModal'; +import ThemeSelectorModal from 'src/dashboard/components/ThemeSelectorModal'; import { usePermissions } from 'src/hooks/usePermissions'; import { useDatasetDrillInfo } from 'src/hooks/apiResources/datasets'; import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; @@ -166,6 +167,13 @@ const SliceHeaderControls = ( const [drillModalIsOpen, setDrillModalIsOpen] = useState(false); // setting openKeys undefined falls back to uncontrolled behaviour const [isDropdownVisible, setIsDropdownVisible] = useState(false); + const [themeModalOpen, setThemeModalOpen] = useState(false); + + // Per-component theming is an edit-mode affordance only — viewers see the + // applied theme but can't change it. + const editMode = useSelector( + state => !!state.dashboardState.editMode, + ); const [openScopingModal, scopingModal] = useCrossFiltersScopingModal( props.slice.slice_id, ); @@ -258,6 +266,9 @@ const SliceHeaderControls = ( // eslint-disable-next-line no-unused-expressions props.toggleExpandSlice?.(props.slice.slice_id); break; + case MenuKeys.ApplyTheme: + setThemeModalOpen(true); + break; case MenuKeys.ExploreChart: // eslint-disable-next-line no-unused-expressions props.logExploreChart?.(props.slice.slice_id); @@ -450,6 +461,13 @@ const SliceHeaderControls = ( }); } + if (editMode) { + newMenuItems.push({ + key: MenuKeys.ApplyTheme, + label: t('Apply theme'), + }); + } + if (canExplore) { newMenuItems.push({ key: MenuKeys.ExploreChart, @@ -681,6 +699,13 @@ const SliceHeaderControls = ( dataset={datasetWithVerboseMap} /> {canEditCrossFilters && scopingModal} + {editMode && ( + setThemeModalOpen(false)} + /> + )} {isFullSize && } ); diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts index 74e8815179b..9aa306e6655 100644 --- a/superset-frontend/src/dashboard/types.ts +++ b/superset-frontend/src/dashboard/types.ts @@ -379,6 +379,7 @@ export enum MenuKeys { ExportFullXlsx = 'export_full_xlsx', ForceRefresh = 'force_refresh', Fullscreen = 'fullscreen', + ApplyTheme = 'apply_theme', ToggleChartDescription = 'toggle_chart_description', ViewQuery = 'view_query', ViewResults = 'view_results',