From 6d74fe2e6317f0bb3b1cb3d39abed54deacf8c2b Mon Sep 17 00:00:00 2001 From: Joe Li Date: Thu, 23 Oct 2025 14:31:18 -0700 Subject: [PATCH 1/2] fix(theme): add fontWeightStrong to allowedAntdTokens for bold markdown rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem**: Bold markdown (`**text**`) wasn't rendering with proper font-weight in dashboard widgets after Ant Design v5 upgrade (issue #35485) **Root Cause**: - `fontWeightStrong` token was missing from `allowedAntdTokens` array - Theme.getFilteredAntdTheme() filtered it out - GlobalStyles.tsx:66 set `font-weight: undefined` on `` tags - Browser fell back to user-agent stylesheet instead of theme value **Solution**: Add `'fontWeightStrong'` to allowedAntdTokens in types.ts **Testing**: - Added test verifying fontWeightStrong exists in theme - Test failed before fix (undefined), passes after fix - All 15 Markdown tests pass - Converted Markdown.test.jsx to TypeScript with proper types **Impact**: Fixes bold rendering for all `` tags including markdown, restoring theme-controlled font weights 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../superset-ui-core/src/theme/types.ts | 1 + .../gridComponents/Markdown/Markdown.test.jsx | 416 ----------------- .../gridComponents/Markdown/Markdown.test.tsx | 435 ++++++++++++++++++ 3 files changed, 436 insertions(+), 416 deletions(-) delete mode 100644 superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.jsx create mode 100644 superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.tsx diff --git a/superset-frontend/packages/superset-ui-core/src/theme/types.ts b/superset-frontend/packages/superset-ui-core/src/theme/types.ts index 7943b712a429..7de4b296dc09 100644 --- a/superset-frontend/packages/superset-ui-core/src/theme/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/theme/types.ts @@ -268,6 +268,7 @@ export const allowedAntdTokens = [ 'controlTmpOutline', 'fontFamily', 'fontFamilyCode', + 'fontWeightStrong', 'fontHeight', 'fontHeightLG', 'fontHeightSM', diff --git a/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.jsx b/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.jsx deleted file mode 100644 index d2554611644b..000000000000 --- a/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.jsx +++ /dev/null @@ -1,416 +0,0 @@ -/** - * 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 { Provider } from 'react-redux'; -import { - act, - render, - screen, - fireEvent, - userEvent, -} from 'spec/helpers/testing-library'; -import { mockStore } from 'spec/fixtures/mockStore'; -import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout'; -import MarkdownConnected from './Markdown'; - -// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks -describe('Markdown', () => { - const props = { - id: 'id', - parentId: 'parentId', - component: mockLayout.present.MARKDOWN_ID, - depth: 2, - parentComponent: mockLayout.present.ROW_ID, - index: 0, - editMode: false, - availableColumnCount: 12, - columnWidth: 50, - onResizeStart: jest.fn(), - onResize: jest.fn(), - onResizeStop: jest.fn(), - handleComponentDrop: jest.fn(), - updateComponents: jest.fn(), - deleteComponent: jest.fn(), - logEvent: jest.fn(), - addDangerToast: jest.fn(), - }; - - beforeAll(() => { - const originalError = console.error; - jest.spyOn(console, 'error').mockImplementation(msg => { - if ( - typeof msg === 'string' && - !msg.includes('[antd:') && - !msg.includes('Warning: An update to SafeMarkdown') && - !msg.includes('Warning: React does not recognize') && - !msg.includes("Warning: Can't perform a React state update") - ) { - originalError.call(console, msg); - } - }); - }); - - afterAll(() => { - jest.restoreAllMocks(); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - const setup = async (overrideProps = {}) => { - let utils; - await act(async () => { - utils = render(, { - useDnd: true, - store: mockStore, - }); - await new Promise(resolve => setTimeout(resolve, 0)); - }); - return utils; - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - test('should render the markdown component', async () => { - await setup(); - expect(screen.getByTestId('dashboard-markdown-editor')).toBeInTheDocument(); - }); - - test('should render the markdown content in preview mode by default', async () => { - await setup(); - expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); - expect( - screen.getByTestId('dashboard-component-chart-holder'), - ).toBeInTheDocument(); - }); - - test('should render editor when in edit mode and clicked', async () => { - await setup({ editMode: true }); - const container = screen.getByTestId('dashboard-component-chart-holder'); - await act(async () => { - fireEvent.click(container); - }); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - }); - - test('should switch between edit and preview modes', async () => { - await setup({ editMode: true }); - const container = screen.getByTestId('dashboard-component-chart-holder'); - - await act(async () => { - fireEvent.click(container); - }); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - - // Find and click edit dropdown by role - const editButton = screen.getByRole('button', { name: /edit/i }); - await act(async () => { - fireEvent.click(editButton); - }); - - // Click preview option in dropdown - const previewOption = await screen.findByText(/preview/i); - await act(async () => { - fireEvent.click(previewOption); - }); - - expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); - }); - - test('should call updateComponents when switching from edit to preview with changes', async () => { - const updateComponents = jest.fn(); - const mockCode = 'new markdown!'; - - const { container } = await setup({ - editMode: true, - updateComponents, - component: { - ...mockLayout.present.MARKDOWN_ID, - id: 'test', - meta: { code: '' }, - }, - }); - - // Enter edit mode and change content - await act(async () => { - const markdownHolder = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - fireEvent.click(markdownHolder); - - // Wait for editor to be fully mounted - await new Promise(resolve => setTimeout(resolve, 50)); - - // Find the actual textarea/input element - const editor = container.querySelector('.ace_text-input'); - console.log('Editor element:', editor); - - // Simulate direct input - fireEvent.input(editor, { target: { value: mockCode } }); - console.log('After input:', editor.value); - - // Force blur and change events - fireEvent.change(editor, { target: { value: mockCode } }); - fireEvent.blur(editor); - - // Wait for state update - await new Promise(resolve => setTimeout(resolve, 50)); - - // Click the Edit dropdown button - const editDropdown = screen.getByText('Edit'); - fireEvent.click(editDropdown); - - // Wait for dropdown to open - await new Promise(resolve => setTimeout(resolve, 50)); - - // Find and click preview in dropdown - const previewOption = await screen.findByText(/preview/i); - fireEvent.click(previewOption); - - // Wait for update to complete - await new Promise(resolve => setTimeout(resolve, 50)); - }); - - console.log('Component state:', { - updateCalls: updateComponents.mock.calls, - editorVisible: screen.queryByRole('textbox') !== null, - dropdownOpen: screen.queryByText(/preview/i) !== null, - }); - - // Update assertion to match actual component structure - expect(updateComponents).toHaveBeenCalledWith({ - test: { - id: 'test', - meta: { code: mockCode }, - type: 'MARKDOWN', - children: [], - parents: [], - }, - }); - }); - - test('should show placeholder text when markdown is empty', async () => { - await setup({ - component: { - ...mockLayout.present.MARKDOWN_ID, - meta: { code: '' }, - }, - }); - - expect( - screen.getByText(/Click here to learn more about/), - ).toBeInTheDocument(); - }); - - test('should handle markdown errors gracefully', async () => { - const addDangerToast = jest.fn(); - const { container } = await setup({ - addDangerToast, - component: { - ...mockLayout.present.MARKDOWN_ID, - meta: { code: '# Test' }, - }, - }); - - console.log('Component structure:', { - markdownEditor: screen.getByTestId('dashboard-markdown-editor'), - safeMarkdown: container.querySelector('.safe-markdown'), - allEventListeners: container.querySelectorAll('[data-test]'), - toastFn: addDangerToast.toString(), - }); - - await act(async () => { - const markdownEditor = screen.getByTestId('dashboard-markdown-editor'); - ['error', 'markdownError', 'renderError'].forEach(eventType => { - const event = new CustomEvent(eventType, { - bubbles: true, - detail: { error: new Error('Markdown error') }, - }); - console.log(`Dispatching ${eventType} event`); - markdownEditor.dispatchEvent(event); - }); - - await new Promise(resolve => setTimeout(resolve, 100)); - console.log('After events:', { - toastCalls: addDangerToast.mock.calls, - errorElements: container.querySelectorAll('.error-message'), - }); - }); - }); - - test('should resize editor when width changes', async () => { - const { rerender } = await setup({ editMode: true }); - - await act(async () => { - const chartHolder = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - fireEvent.click(chartHolder); - await new Promise(resolve => setTimeout(resolve, 50)); - }); - - await act(async () => { - rerender( - , - ); - - await new Promise(resolve => setTimeout(resolve, 100)); - }); - }); - - test('should update content when undo/redo changes occur', async () => { - const { rerender } = await setup({ - editMode: true, - component: { - ...mockLayout.present.MARKDOWN_ID, - meta: { code: 'original' }, - }, - }); - - // Simulate undo/redo state change - await act(async () => { - rerender( - , - ); - }); - - expect(screen.getByText('updated')).toBeInTheDocument(); - }); - - test('should adjust width based on parent type', async () => { - const { rerender } = await setup(); - - // Check ROW_TYPE width - const container = screen.getByTestId('dashboard-component-chart-holder'); - const { parentElement } = container; - expect(parentElement).toHaveStyle('width: 248px'); - - // Check non-ROW_TYPE width - await act(async () => { - rerender( - - - , - ); - // Wait for styles to update - await new Promise(resolve => setTimeout(resolve, 100)); - }); - - const updatedContainer = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - const updatedParent = updatedContainer.parentElement; - // Check that width is no longer 248px - expect(updatedParent).not.toHaveStyle('width: 248px'); - }); - - test('shouldFocusMarkdown returns true when clicking inside markdown container', async () => { - await setup({ editMode: true }); - - const markdownContainer = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - - userEvent.click(markdownContainer); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - }); - - test('shouldFocusMarkdown returns false when clicking outside markdown container', async () => { - await setup({ editMode: true }); - - const markdownContainer = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - - userEvent.click(markdownContainer); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - - userEvent.click(document.body); - await new Promise(resolve => setTimeout(resolve, 50)); - - expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); - }); - - test('shouldFocusMarkdown keeps focus when clicking on menu items', async () => { - await setup({ editMode: true }); - - const markdownContainer = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - - userEvent.click(markdownContainer); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - - const editButton = screen.getByText('Edit'); - - userEvent.click(editButton); - await new Promise(resolve => setTimeout(resolve, 50)); - - expect(screen.queryByRole('textbox')).toBeInTheDocument(); - }); - - test('should exit edit mode when clicking outside in same row', async () => { - await setup({ editMode: true }); - - const markdownContainer = screen.getByTestId( - 'dashboard-component-chart-holder', - ); - - userEvent.click(markdownContainer); - - expect(await screen.findByRole('textbox')).toBeInTheDocument(); - - const outsideElement = document.createElement('div'); - outsideElement.className = 'grid-row'; - document.body.appendChild(outsideElement); - - userEvent.click(outsideElement); - await new Promise(resolve => setTimeout(resolve, 50)); - - expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); - - document.body.removeChild(outsideElement); - }); -}); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.tsx new file mode 100644 index 000000000000..dde4cf62dbe6 --- /dev/null +++ b/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.test.tsx @@ -0,0 +1,435 @@ +/** + * 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 { Provider } from 'react-redux'; +import { + act, + render, + screen, + fireEvent, + userEvent, + RenderResult, +} from 'spec/helpers/testing-library'; +import { supersetTheme } from '@superset-ui/core'; +import { mockStore } from 'spec/fixtures/mockStore'; +import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout'; +import MarkdownConnected from './Markdown'; + +interface MarkdownProps { + id: string; + parentId: string; + component: Record; + depth: number; + parentComponent: Record; + index: number; + editMode: boolean; + availableColumnCount: number; + columnWidth: number; + onResizeStart: jest.Mock; + onResize: jest.Mock; + onResizeStop: jest.Mock; + handleComponentDrop: jest.Mock; + updateComponents: jest.Mock; + deleteComponent: jest.Mock; + logEvent: jest.Mock; + addDangerToast: jest.Mock; + undoLength?: number; + redoLength?: number; +} + +const defaultProps: MarkdownProps = { + id: 'id', + parentId: 'parentId', + component: mockLayout.present.MARKDOWN_ID, + depth: 2, + parentComponent: mockLayout.present.ROW_ID, + index: 0, + editMode: false, + availableColumnCount: 12, + columnWidth: 50, + onResizeStart: jest.fn(), + onResize: jest.fn(), + onResizeStop: jest.fn(), + handleComponentDrop: jest.fn(), + updateComponents: jest.fn(), + deleteComponent: jest.fn(), + logEvent: jest.fn(), + addDangerToast: jest.fn(), +}; + +beforeAll(() => { + const originalError = console.error; + jest.spyOn(console, 'error').mockImplementation((msg: unknown) => { + if ( + typeof msg === 'string' && + !msg.includes('[antd:') && + !msg.includes('Warning: An update to SafeMarkdown') && + !msg.includes('Warning: React does not recognize') && + !msg.includes("Warning: Can't perform a React state update") + ) { + originalError.call(console, msg); + } + }); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +const setup = async ( + overrideProps: Partial = {}, +): Promise => { + let utils: RenderResult | undefined; + await act(async () => { + utils = render( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + , + { + useDnd: true, + store: mockStore, + }, + ); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + return utils!; +}; + +test('should render the markdown component', async () => { + await setup(); + expect(screen.getByTestId('dashboard-markdown-editor')).toBeInTheDocument(); +}); + +test('should render the markdown content in preview mode by default', async () => { + await setup(); + expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); + expect( + screen.getByTestId('dashboard-component-chart-holder'), + ).toBeInTheDocument(); +}); + +test('should render editor when in edit mode and clicked', async () => { + await setup({ editMode: true }); + const container = screen.getByTestId('dashboard-component-chart-holder'); + await act(async () => { + fireEvent.click(container); + }); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); +}); + +test('should switch between edit and preview modes', async () => { + await setup({ editMode: true }); + const container = screen.getByTestId('dashboard-component-chart-holder'); + + await act(async () => { + fireEvent.click(container); + }); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); + + // Find and click edit dropdown by role + const editButton = screen.getByRole('button', { name: /edit/i }); + await act(async () => { + fireEvent.click(editButton); + }); + + // Click preview option in dropdown + const previewOption = await screen.findByText(/preview/i); + await act(async () => { + fireEvent.click(previewOption); + }); + + expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); +}); + +test('should call updateComponents when switching from edit to preview with changes', async () => { + const updateComponents = jest.fn(); + const mockCode = 'new markdown!'; + + const { container } = await setup({ + editMode: true, + updateComponents, + component: { + ...mockLayout.present.MARKDOWN_ID, + id: 'test', + meta: { code: '' }, + }, + }); + + // Enter edit mode and change content + await act(async () => { + const markdownHolder = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + fireEvent.click(markdownHolder); + + // Wait for editor to be fully mounted + await new Promise(resolve => setTimeout(resolve, 50)); + + // Find the actual textarea/input element + const editor = container.querySelector('.ace_text-input'); + + if (editor) { + // Simulate direct input + fireEvent.input(editor, { target: { value: mockCode } }); + + // Force blur and change events + fireEvent.change(editor, { target: { value: mockCode } }); + fireEvent.blur(editor); + } + + // Wait for state update + await new Promise(resolve => setTimeout(resolve, 50)); + + // Click the Edit dropdown button + const editDropdown = screen.getByText('Edit'); + fireEvent.click(editDropdown); + + // Wait for dropdown to open + await new Promise(resolve => setTimeout(resolve, 50)); + + // Find and click preview in dropdown + const previewOption = await screen.findByText(/preview/i); + fireEvent.click(previewOption); + + // Wait for update to complete + await new Promise(resolve => setTimeout(resolve, 50)); + }); + + // Update assertion to match actual component structure + expect(updateComponents).toHaveBeenCalledWith({ + test: { + id: 'test', + meta: { code: mockCode }, + type: 'MARKDOWN', + children: [], + parents: [], + }, + }); +}); + +test('should show placeholder text when markdown is empty', async () => { + await setup({ + component: { + ...mockLayout.present.MARKDOWN_ID, + meta: { code: '' }, + }, + }); + + expect( + screen.getByText(/Click here to learn more about/), + ).toBeInTheDocument(); +}); + +test('should handle markdown errors gracefully', async () => { + const addDangerToast = jest.fn(); + await setup({ + addDangerToast, + component: { + ...mockLayout.present.MARKDOWN_ID, + meta: { code: '# Test' }, + }, + }); + + await act(async () => { + const markdownEditor = screen.getByTestId('dashboard-markdown-editor'); + ['error', 'markdownError', 'renderError'].forEach(eventType => { + const event = new CustomEvent(eventType, { + bubbles: true, + detail: { error: new Error('Markdown error') }, + }); + markdownEditor.dispatchEvent(event); + }); + + await new Promise(resolve => setTimeout(resolve, 100)); + }); +}); + +test('should resize editor when width changes', async () => { + const { rerender } = await setup({ editMode: true }); + + await act(async () => { + const chartHolder = screen.getByTestId('dashboard-component-chart-holder'); + fireEvent.click(chartHolder); + await new Promise(resolve => setTimeout(resolve, 50)); + }); + + await act(async () => { + rerender( + , + ); + + await new Promise(resolve => setTimeout(resolve, 100)); + }); +}); + +test('should update content when undo/redo changes occur', async () => { + const { rerender } = await setup({ + editMode: true, + component: { + ...mockLayout.present.MARKDOWN_ID, + meta: { code: 'original' }, + }, + }); + + // Simulate undo/redo state change + await act(async () => { + rerender( + , + ); + }); + + expect(screen.getByText('updated')).toBeInTheDocument(); +}); + +test('should adjust width based on parent type', async () => { + const { rerender } = await setup(); + + // Check ROW_TYPE width + const container = screen.getByTestId('dashboard-component-chart-holder'); + const { parentElement } = container; + expect(parentElement).toHaveStyle('width: 248px'); + + // Check non-ROW_TYPE width + await act(async () => { + rerender( + + + , + ); + // Wait for styles to update + await new Promise(resolve => setTimeout(resolve, 100)); + }); + + const updatedContainer = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + const updatedParent = updatedContainer.parentElement; + // Check that width is no longer 248px + expect(updatedParent).not.toHaveStyle('width: 248px'); +}); + +test('shouldFocusMarkdown returns true when clicking inside markdown container', async () => { + await setup({ editMode: true }); + + const markdownContainer = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + + userEvent.click(markdownContainer); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); +}); + +test('shouldFocusMarkdown returns false when clicking outside markdown container', async () => { + await setup({ editMode: true }); + + const markdownContainer = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + + userEvent.click(markdownContainer); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); + + userEvent.click(document.body); + await new Promise(resolve => setTimeout(resolve, 50)); + + expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); +}); + +test('shouldFocusMarkdown keeps focus when clicking on menu items', async () => { + await setup({ editMode: true }); + + const markdownContainer = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + + userEvent.click(markdownContainer); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); + + const editButton = screen.getByText('Edit'); + + userEvent.click(editButton); + await new Promise(resolve => setTimeout(resolve, 50)); + + expect(screen.queryByRole('textbox')).toBeInTheDocument(); +}); + +test('should exit edit mode when clicking outside in same row', async () => { + await setup({ editMode: true }); + + const markdownContainer = screen.getByTestId( + 'dashboard-component-chart-holder', + ); + + userEvent.click(markdownContainer); + + expect(await screen.findByRole('textbox')).toBeInTheDocument(); + + const outsideElement = document.createElement('div'); + outsideElement.className = 'grid-row'; + document.body.appendChild(outsideElement); + + userEvent.click(outsideElement); + await new Promise(resolve => setTimeout(resolve, 50)); + + expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); + + document.body.removeChild(outsideElement); +}); + +test('should have fontWeightStrong in theme for bold markdown rendering', async () => { + await setup({ + component: { + ...mockLayout.present.MARKDOWN_ID, + meta: { code: '**bold text**' }, + }, + }); + + // CRITICAL: Verify fontWeightStrong exists in the theme + // If it's missing from allowedAntdTokens, GlobalStyles.tsx:66 will set + // font-weight: undefined on tags, breaking bold markdown rendering + // Ant Design default is 600, backend config sets 500, either is acceptable + expect(supersetTheme.fontWeightStrong).toBeDefined(); + expect(supersetTheme.fontWeightStrong).toBeGreaterThan(400); +}); From 300efa8de07b661932cd53a18c2d5eb7a37428c4 Mon Sep 17 00:00:00 2001 From: Joe Li Date: Fri, 24 Oct 2025 15:16:48 -0700 Subject: [PATCH 2/2] fix(dashboard): override font-weight for bold markdown in dashboard widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add font-weight: 600 override specifically for tags in dashboard markdown widgets to restore proper bold text appearance. The global theme uses fontWeightStrong: 500 (medium), which is too subtle to distinguish from normal text (400). This scoped override restores the previous behavior of using font-weight 600 (semibold) for bold markdown without affecting other components. Fixes #35485 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../dashboard/components/gridComponents/Markdown/Markdown.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.jsx b/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.jsx index 9f11710f7e02..c8de3aa722b9 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Markdown/Markdown.jsx @@ -96,6 +96,10 @@ const MarkdownStyles = styled.div` font-weight: ${theme.fontWeightNormal}; } + strong { + font-weight: 600; + } + h6 { font-size: ${theme.fontSizeSM}px; }