Skip to content

[feat] Add markdown support to page titles in st.Page#14010

Merged
lukasmasuch merged 3 commits intodevelopfrom
lukasmasuch/page-markdown-labels
Feb 20, 2026
Merged

[feat] Add markdown support to page titles in st.Page#14010
lukasmasuch merged 3 commits intodevelopfrom
lukasmasuch/page-markdown-labels

Conversation

@lukasmasuch
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch commented Feb 19, 2026

Describe your changes

  • Enable GitHub-flavored Markdown rendering in page titles for st.Page
  • Supported elements: bold, italics, strikethroughs, inline code, Material icons, and images
  • Unsupported markdown elements are unwrapped to show only their text content
  • Add documentation for the markdown support in st.Page docstrings

Github Issues

Testing Plan

  • Unit Tests (JS) - Added test for markdown rendering in SidebarNavLink.test.tsx
  • E2E Tests - Added test_page_titles_support_markdown to verify bold, italic, and code rendering
  • Updated existing E2E app to use markdown in page titles

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

Enable GitHub-flavored Markdown rendering in page titles for `st.Page`.
Supported elements include bold, italics, strikethroughs, inline code,
Material icons, and images.
Copilot AI review requested due to automatic review settings February 19, 2026 10:00
@lukasmasuch lukasmasuch added change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Feb 19, 2026
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Feb 19, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 19, 2026

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-14010/streamlit-1.54.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-14010.streamlit.app (☁️ Deploy here if not accessible)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds GitHub-flavored Markdown support to page titles in st.Page, enabling users to format navigation labels with bold, italics, strikethroughs, inline code, Material icons, and images. The implementation integrates the existing StreamlitMarkdown component into navigation links with appropriate restrictions (disabling nested links, truncating overflow) while maintaining accessibility and consistent visual styling.

Changes:

  • Added markdown rendering support to page titles via StreamlitMarkdown component in navigation links
  • Updated Python docstrings to document the supported markdown elements
  • Added line-height override in navigation styles to maintain consistent nav item height with markdown content
  • Added tests to verify markdown formatting works correctly in page titles

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
lib/streamlit/navigation/page.py Updated docstrings for Page(), StreamlitPage.title, and title property to document markdown support and list supported elements
frontend/app/src/components/Navigation/SidebarNavLink.tsx Replaced plain text rendering with StreamlitMarkdown component, configuring it with appropriate props (isLabel, boldLabel, disableLinks, truncate)
frontend/app/src/components/Navigation/styled-components.ts Added CSS override to maintain consistent line height for nav items when markdown is truncated
frontend/app/src/components/Navigation/SidebarNavLink.test.tsx Added unit test verifying bold and italic markdown renders correctly in page titles
e2e_playwright/multipage_apps_v2/mpa_v2_basics_test.py Added E2E test verifying bold, italic, and inline code formatting in navigation
e2e_playwright/multipage_apps_v2/mpa_v2_basics.py Updated test app to use markdown in page titles for testing purposes

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

@lukasmasuch lukasmasuch added the update-snapshots Trigger snapshot autofix workflow label Feb 19, 2026
@github-actions github-actions bot removed the update-snapshots Trigger snapshot autofix workflow label Feb 19, 2026
github-actions bot and others added 2 commits February 19, 2026 11:24
## Describe your changes

Automated snapshot updates for #14010 created via the snapshot autofix
CI workflow.

This workflow was triggered by adding the `update-snapshots` label to a
PR after Playwright E2E tests failed with snapshot mismatches.

**Updated snapshots:** 39 file(s)

⚠️ **Please review the snapshot changes carefully** - they could mask
visual bugs if accepted blindly.

This PR targets a feature branch and can be merged without review
approval.

Co-authored-by: Streamlit Bot <[email protected]>
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Feb 19, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Feb 19, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR adds GitHub-flavored Markdown rendering support to page titles in st.Page. On the frontend, the SidebarNavLink component now uses StreamlitMarkdown (with isLabel mode) instead of plain text, supporting bold, italics, strikethroughs, inline code, Material icons, and images. Unsupported markdown elements are gracefully unwrapped to show only their text content. The change is purely frontend rendering — the backend passes the title string as-is and only docstrings were updated.

Key changes:

  • SidebarNavLink.tsx: Replaced plain {children} with <StreamlitMarkdown> component using isLabel, boldLabel, disableLinks, and truncate props.
  • styled-components.ts: Added CSS override to fix lineHeight from StreamlitMarkdown's truncate prop to match nav item height.
  • page.py: Docstring-only updates documenting the markdown support.
  • E2E and unit tests added for the new behavior.

Code Quality

The code is clean and well-structured. The implementation follows existing patterns established by PageLink.tsx (frontend/lib/src/components/elements/PageLink/PageLink.tsx), which already uses StreamlitMarkdown with the same combination of isLabel, boldLabel, and disableLinks props. This consistency is good.

The prop choices are well-considered:

  • allowHTML={false} prevents HTML injection (security).
  • disableLinks prevents nested <a> elements inside the nav <a> tag (accessibility and valid HTML).
  • boldLabel={isActive} correctly synchronizes the markdown bold state with the active page indicator.
  • truncate maintains the existing text overflow behavior.

Minor concern — ::after pseudo-element width reservation (styled-components.ts, lines 172-179): The label prop passed to StyledSidebarLinkText is the raw markdown string (e.g., **Different** Title), which is used in content: "${label}" for the hidden ::after pseudo-element that reserves bold-text width. This means the width reservation includes raw markdown syntax characters (**, `, etc.), resulting in slightly over-reserved width compared to the rendered text. This is cosmetic only (the element is hidden with height: 0; visibility: hidden;) and errs on the safe side (over-reserving rather than under-reserving), but could be improved by stripping markdown syntax from the label prop.

Test Coverage

Frontend unit test (SidebarNavLink.test.tsx, lines 106-122): Good test that verifies bold, italic rendering, and importantly validates that links in markdown are disabled (no nested <a> elements). The negative assertion for disabled links is well-chosen.

E2E test (mpa_v2_basics_test.py, lines 191-206): Tests bold (<strong>), italic (<em>), and inline code (<code>) rendering in the sidebar nav. Uses proper playwright expect() assertions. Updated snapshot images cover visual regression across all browser engines and themes.

Suggestions for improved test coverage:

  • The E2E test lacks a negative assertion, which is recommended by the e2e_playwright/AGENTS.md ("Add at least one 'must NOT happen' check per scenario"). For example, asserting that raw markdown syntax characters (**, *, `) are not visible as text, or that an unsupported markdown element (like a heading) is properly unwrapped.
  • The E2E app uses :blue[page] 12 as a title (mpa_v2_basics.py, line 85), but neither the E2E test nor the unit test verifies that the Streamlit color directive renders correctly.
  • No Python backend unit test was added, but since the backend changes are docstring-only, this is acceptable.

Backwards Compatibility

This change is mostly backwards compatible but has a potential edge case. Existing page titles without markdown syntax will render identically. However, titles containing characters that are markdown syntax (e.g., *, **, `, ~) will now be interpreted as markdown rather than displayed literally. For example, a title like page *special* that previously showed literal asterisks will now render "special" in italics.

This behavior is consistent with how other Streamlit label-supporting components work (e.g., st.checkbox, st.radio, st.page_link), so it aligns with user expectations. The standard escape mechanism (\*) is available. The risk is low but non-zero for existing apps.

Security & Risk

  • HTML injection: Properly mitigated by allowHTML={false} on the StreamlitMarkdown component.
  • Nested links: Properly mitigated by disableLinks, preventing <a> tags inside the nav <a> tag (which would be invalid HTML and a potential clickjacking vector).
  • XSS via CSS content: The label prop is used in content: "${label}" in a CSS pseudo-element. If a title contains a double quote, this could break the CSS (e.g., My "title" would produce content: "My "title""). However, this is a pre-existing issue not introduced by this PR, and Emotion's styled components generally handle this safely through its CSS-in-JS engine.
  • Overall security risk is low.

Accessibility

  • No nested interactive elements: The disableLinks prop correctly prevents <a> tags from being nested inside the nav link's <a> tag, which would violate HTML semantics and confuse screen readers.
  • Bold state: The boldLabel={isActive} prop ensures that active page labels are consistently bold, which is a visual affordance. The existing aria-current="page" attribute on active links is preserved for screen reader users.
  • Semantic HTML: The markdown rendering uses semantic elements (<strong>, <em>, <code>) which are properly announced by screen readers.
  • No accessibility concerns identified.

Recommendations

  1. Consider stripping markdown syntax from the label prop passed to StyledSidebarLinkText for the ::after pseudo-element width reservation. This would make the reserved width more accurate by excluding markdown syntax characters. This is a cosmetic improvement, not a blocker.

  2. Add a negative assertion to the E2E test per the project's E2E best practices. For example, verify that raw markdown syntax (**) is not displayed as visible text in the rendered nav link.

  3. Consider testing the :blue[page] 12 title in the E2E test to verify that Streamlit color directives are handled correctly, since it's already used in the test app.

Verdict

APPROVED: A clean, well-implemented feature that adds markdown rendering to page titles following established patterns from PageLink. The change is well-tested, security-conscious, and accessibility-friendly. The minor recommendations above are improvements but not blockers.


This is an automated AI review by opus-4.6-thinking.

@lukasmasuch lukasmasuch merged commit 463b02a into develop Feb 20, 2026
55 of 57 checks passed
@lukasmasuch lukasmasuch deleted the lukasmasuch/page-markdown-labels branch February 20, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Markdown in the title of st.Page

3 participants