Fix unreadable release notes blockquote in dark theme - #9957
Conversation
MarkdownStyleSheet.fromTheme takes the blockquote text style from the theme but hard codes the fill as Colors.blue.shade100, so the side panel drew onSurface text on light blue. Release notes that open with a blockquote, like 2.60.0, were unreadable in the dark theme. The panel now passes its own blockquote decoration, and widget tests assert the text clears WCAG AA contrast in both themes.
There was a problem hiding this comment.
Code Review
This pull request addresses an issue with unreadable blockquote text in the release notes panel under the dark theme by customizing the blockquote decoration in the SidePanel. It also introduces a regression test to ensure proper contrast ratios across both light and dark themes. The reviewer identified a critical issue where instantiating MarkdownStyleSheet directly discards other theme-derived styles, and suggested using MarkdownStyleSheet.fromTheme(theme).copyWith(...) to preserve the stylesheet.
| styleSheet: MarkdownStyleSheet( | ||
| // [MarkdownStyleSheet.fromTheme], which supplies the | ||
| // rest of the style sheet, hard codes | ||
| // `Colors.blue.shade100` as the blockquote fill while | ||
| // taking the text color from the theme. In the dark | ||
| // theme that draws light gray text on light blue. | ||
| blockquoteDecoration: BoxDecoration( | ||
| color: theme.colorScheme.secondaryContainer, | ||
| borderRadius: defaultBorderRadius, | ||
| ), | ||
| ), |
There was a problem hiding this comment.
[MUST-FIX] Instantiating MarkdownStyleSheet directly via its default constructor will result in a stylesheet where all other text styles (such as p, h1, code, etc.) are null. This causes the Markdown widget to fall back to default unstyled text, losing all theme-derived styles (fonts, sizes, colors) for the rest of the release notes.
To preserve the theme's styles while overriding only the blockquote decoration, use MarkdownStyleSheet.fromTheme(theme).copyWith(...) instead.
| styleSheet: MarkdownStyleSheet( | |
| // [MarkdownStyleSheet.fromTheme], which supplies the | |
| // rest of the style sheet, hard codes | |
| // `Colors.blue.shade100` as the blockquote fill while | |
| // taking the text color from the theme. In the dark | |
| // theme that draws light gray text on light blue. | |
| blockquoteDecoration: BoxDecoration( | |
| color: theme.colorScheme.secondaryContainer, | |
| borderRadius: defaultBorderRadius, | |
| ), | |
| ), | |
| styleSheet: MarkdownStyleSheet.fromTheme(theme).copyWith( | |
| // MarkdownStyleSheet.fromTheme, which supplies the | |
| // rest of the style sheet, hard codes | |
| // Colors.blue.shade100 as the blockquote fill while | |
| // taking the text color from the theme. In the dark | |
| // theme that draws light gray text on light blue. | |
| blockquoteDecoration: BoxDecoration( | |
| color: theme.colorScheme.secondaryContainer, | |
| borderRadius: defaultBorderRadius, | |
| ), | |
| ) |
References
- The repository style guide requires prefixing comments with a severity category, such as [MUST-FIX] for logical bugs. (link)
There was a problem hiding this comment.
The widget merges this sheet over the theme one. flutter_markdown resolves kFallbackStyle(context, widget.styleSheetTheme).merge(widget.styleSheet) before parsing, widget.dart:391 in 0.7.7, and merge keeps every field the override leaves null. I probed this exact sheet on a dark theme, merged.p stays equal to MarkdownStyleSheet.fromTheme(theme).p while the blockquote fill changes. I'm keeping the minimal override.
|
|
||
| /// The smallest contrast ratio WCAG 2.1 accepts for body text at level AA. | ||
| /// | ||
| /// See https://www.w3.org/TR/WCAG21/#contrast-minimum. |
Work towards #9945
The blockquote fill comes from
MarkdownStyleSheet.fromTheme, which hard codes it toColors.blue.shade100and takes the text style from the theme. With the dark palette, that works out to#C7C6CAon#BBDEFB, a 1.21:1 ratio. The 2.60.0 notes open with a blockquote right under the title, which is the banner in the screenshots.I moved the decoration onto the panel: the fill becomes
secondaryContainerand the corner radius followsdefaultBorderRadiusinstead of the hard coded 2.0. I kept the text color atonSurface, which clears AA on the new fill, 5.48:1 dark and 13.29:1 light, and keeps the diff to just the one stylesheet override. Widget tests measure the contrast in both themes.The rest of the issue, whether the notes belong in the embedded view, is untouched.
Pre-launch Checklist
General checklist
///).Issues checklist
contributions-welcomeorgood-first-issuelabel.contributions-welcomeorgood-first-issuelabel. I understand this means my PR might take longer to be reviewed.Tests checklist
AI-tooling checklist
Feature-change checklist
release-notes-not-requiredlabel or left a comment requesting the label be added.packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md.If you need help, consider asking for help on Discord.