Skip to content

Globals: Repair dynamicTitle: false for user-defined tools#33284

Merged
valentinpalkovic merged 13 commits into
storybookjs:nextfrom
ia319:bug/33281-dynamic-title-select
Feb 4, 2026
Merged

Globals: Repair dynamicTitle: false for user-defined tools#33284
valentinpalkovic merged 13 commits into
storybookjs:nextfrom
ia319:bug/33281-dynamic-title-select

Conversation

@ia319
Copy link
Copy Markdown
Member

@ia319 ia319 commented Dec 5, 2025

Closes #33281

What I did

  • Add showSelectedLabel prop to Select (default true).
  • Only show the selected label when this prop is enabled.
  • Set showSelectedLabel={false} in ToolbarMenuSelect.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features
    • Added a configurable option to control whether selected option titles are displayed in select dropdowns. Default behavior is maintained for backward compatibility, automatically applying across single and multi-select variants.

@ia319 ia319 added the ci:normal label Dec 5, 2025
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Dec 5, 2025

View your CI Pipeline Execution ↗ for commit ec6d656


☁️ Nx Cloud last updated this comment at 2025-12-22 17:37:13 UTC

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

This PR adds a showSelectedOptionTitle boolean prop to the Select component that conditionally displays the selected option's title. The prop defaults to true and is integrated into ToolbarMenuSelect. Four Storybook test stories were added to verify the prop's behavior in both single and multi-select modes.

Changes

Cohort / File(s) Summary
Select component core
code/core/src/components/components/Select/Select.tsx
Added showSelectedOptionTitle?: boolean prop (defaults to true) with conditional rendering logic: displays selected option title when true, otherwise renders children fallback.
Toolbar integration
code/core/src/toolbar/components/ToolbarMenuSelect.tsx
Destructured dynamicTitle prop with default value true and passed it to Select component via showSelectedOptionTitle={dynamicTitle}.
Storybook tests
code/core/src/components/components/Select/Select.stories.tsx
Added four new test stories: ShowSelectedOptionTitleTrue, ShowSelectedOptionTitleFalse, ShowSelectedOptionTitleFalseMulti, and ShowSelectedOptionTitleTrueMulti, covering single and multi-select variants with corresponding assertions.
Documentation
docs/_snippets/storybook-preview-configure-globaltypes.md
Updated comment text to add "(recommended for consistency with the Storybook UI)" note for documentation consistency.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • storybookjs/storybook#33164 — Modifies SelectProps types and Select component internals, overlapping with the prop addition and rendering logic changes in this PR.
✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/core/src/components/components/Select/Select.tsx (1)

47-50: Update the comment to reflect conditional behavior.

The comment states the label "is replaced by the currently selected option's title" in single-select mode, but with the new showSelectedLabel prop, this only occurs when showSelectedLabel is true.

Apply this diff to update the documentation:

   /**
-   * Label for the Select component. In single-select mode, is replaced by the currently selected
-   * option's title.
+   * Label for the Select component. In single-select mode, is replaced by the currently selected
+   * option's title when showSelectedLabel is true.
    */
   children?: React.ReactNode;
🧹 Nitpick comments (1)
code/core/src/components/components/Select/Select.tsx (1)

507-512: Logic correctly implements the intended behavior.

The conditional rendering properly controls whether the selected option's title is displayed based on the showSelectedLabel prop, which solves the reported issue.

Optional refinement for edge cases:

The current logic (showSelectedLabel && selectedOptions[0]?.title) || children might not handle edge cases where title is a falsy value (empty string "" or numeric 0). If such titles are valid in your domain, consider this more explicit check:

-              {(showSelectedLabel && selectedOptions[0]?.title) || children}
+              {showSelectedLabel && selectedOptions[0] ? selectedOptions[0].title : children}

This ensures that any selected title (including falsy values) is displayed when showSelectedLabel is true, rather than falling back to children.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de619c1 and a3bc089.

📒 Files selected for processing (2)
  • code/core/src/components/components/Select/Select.tsx (3 hunks)
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ESLint and Prettier configurations that are enforced in the codebase

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
code/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions that need to be tested from their modules

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
code/**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.
📚 Learning: 2025-11-05T09:36:55.944Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.

Applied to files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
📚 Learning: 2025-10-03T07:55:42.639Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: normal
  • GitHub Check: nx
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (3)
code/core/src/components/components/Select/Select.tsx (2)

79-83: LGTM! Clear documentation for the new prop.

The showSelectedLabel prop is well-documented and appropriately optional with a sensible default.


208-208: LGTM! Default parameter correctly maintains backward compatibility.

code/core/src/toolbar/components/ToolbarMenuSelect.tsx (1)

104-104: Verify the showSelectedLabel={false} fix for dynamicTitle behavior in issue #33281.

Setting showSelectedLabel={false} should prevent the Select component from replacing the displayed title with the selected option's title when dynamicTitle is false. This appears to be the correct approach to fix the reported issue, with backward compatibility preserved (default showSelectedLabel={true} maintains existing behavior for other Select usages).

Manual verification recommended: Test with a toolbar configuration where dynamicTitle: false and confirm the toolbar title remains fixed when selecting different options from the dropdown.

onReset={() => updateGlobals({ [id]: '_reset' })}
onSelect={(selected) => updateGlobals({ [id]: selected })}
icon={icon && <Icons icon={icon} __suppressDeprecationWarning={true} />}
showSelectedLabel={false}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
showSelectedLabel={false}
showSelectedLabel={dynamicTitle}

otherwise it'll never update

Comment on lines 49 to 51
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we pass dynamicTitle through, then we can remove this logic and pass title through directly

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for pointing that out — updated accordingly.

Copy link
Copy Markdown
Member

@Sidnioulz Sidnioulz left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this @ia319! This is a bit of a sensitive one as we wanted to enforce dynamic titles on all Selects (and yes, I did forget to handle that old option in ToolbarMenuSelect 😬).

Comment thread code/core/src/components/components/Select/Select.tsx Outdated
Comment thread code/core/src/components/components/Select/Select.tsx
Comment thread code/core/src/toolbar/components/ToolbarMenuSelect.tsx Outdated
Comment thread code/core/src/toolbar/components/ToolbarMenuSelect.tsx Outdated
Comment thread code/core/src/toolbar/components/ToolbarMenuSelect.tsx
…tle handling

- renamed `showSelectedLabel` to `showSelectedOptionTitle` and marked as legacy
- removed unused `_title` alias and redundant title reassignment
- enabled `dynamicTitle` by default
added new stories demonstrating how labels render when:
- single-select: showSelectedOptionTitle = true / false
- multi-select: showSelectedOptionTitle = true / false
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
code/core/src/components/components/Select/Select.tsx (1)

46-50: Keep children JSDoc in sync with showSelectedOptionTitle behavior

The children comment still says that in single‑select mode the label is always replaced by the selected option’s title, which is no longer true when showSelectedOptionTitle is false. Consider tightening the docs so callers understand the interaction:

-  /**
-   * Label for the Select component. In single-select mode, is replaced by the currently selected
-   * option's title.
-   */
+  /**
+   * Label for the Select component.
+   * In single-select mode, when `showSelectedOptionTitle` is true, it is replaced by the currently
+   * selected option's title; otherwise the label remains static.
+   */
   children?: React.ReactNode;
@@
   /**
-   * Legacy option for ToolbarMenuSelect. Do not use in new code. Controls whether to show the
-   * selected option's title.
+   * Legacy option for ToolbarMenuSelect. Do not use in new code.
+   * Controls whether to show the selected option's title instead of the Select's label when a
+   * selection is made (single-select only).
    *
    * @default true
    */
   showSelectedOptionTitle?: boolean;

Also applies to: 79-86

code/core/src/components/components/Select/Select.stories.tsx (1)

1335-1391: New stories nicely cover showSelectedOptionTitle on single and multi select

These four stories exercise the requested matrix (single/multi × prop on/off) and align with how the prop is actually implemented (only affecting the single‑select label, with multi‑select still showing the static label plus count). If you want slightly stronger coverage, you could also assert the selection count in ShowSelectedOptionTitleFalseMulti to document that showSelectedOptionTitle does not affect the multi‑select count display, but that’s optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6ac5b3 and fae8f79.

📒 Files selected for processing (5)
  • code/core/src/components/components/Select/Select.stories.tsx (1 hunks)
  • code/core/src/components/components/Select/Select.tsx (3 hunks)
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx (3 hunks)
  • code/core/src/toolbar/utils/get-selected.ts (0 hunks)
  • docs/_snippets/storybook-preview-configure-globaltypes.md (4 hunks)
💤 Files with no reviewable changes (1)
  • code/core/src/toolbar/utils/get-selected.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/_snippets/storybook-preview-configure-globaltypes.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ESLint and Prettier configurations that are enforced in the codebase

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions that need to be tested from their modules

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing

Files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
🧠 Learnings (5)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.
📚 Learning: 2025-11-05T09:36:55.944Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.

Applied to files:

  • code/core/src/components/components/Select/Select.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.

Applied to files:

  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase

Applied to files:

  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-11-05T09:37:25.920Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.

Applied to files:

  • code/core/src/components/components/Select/Select.stories.tsx
🧬 Code graph analysis (1)
code/core/src/components/components/Select/Select.stories.tsx (2)
code/core/src/csf-tools/CsfFile.ts (1)
  • meta (964-966)
code/core/src/node-logger/logger/logger.ts (1)
  • step (197-202)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/core/src/components/components/Select/Select.tsx (1)

210-211: showSelectedOptionTitle wiring achieves the desired toolbar behavior

Defaulting showSelectedOptionTitle to true and using it only in the single‑select label expression keeps existing behavior by default while allowing ToolbarMenuSelect to freeze the visible title when needed:

showSelectedOptionTitle = true;

{icon}
{(showSelectedOptionTitle && selectedOptions[0]?.title) || children}

This cleanly addresses the dynamicTitle: false case without impacting multi‑select semantics or ARIA labeling. Looks good to me.

Also applies to: 512-513

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
code/core/src/components/components/Select/Select.stories.tsx (1)

1376-1432: New showSelectedOptionTitle stories correctly cover single & multi behavior; tests could be slightly stricter

The four new stories nicely exercise the prop in both single and multi-select modes and match the intended semantics (dynamic option title / count when true, static label when false). If you want to harden these tests further, you could also assert the absence of the dynamic text in the “false” variants (e.g., expect(selectButton).not.toHaveTextContent('Frog') and not.toHaveTextContent('2')) to guard against regressions, but the current coverage is already reasonable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fae8f79 and eec0b3d.

📒 Files selected for processing (3)
  • code/core/src/components/components/Select/Select.stories.tsx (1 hunks)
  • code/core/src/components/components/Select/Select.tsx (3 hunks)
  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/core/src/components/components/Select/Select.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use ESLint and Prettier configurations that are enforced in the codebase

Files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode

Files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{ts,tsx,js,jsx,mjs}: Use server-side logger from 'storybook/internal/node-logger' for Node.js code
Use client-side logger from 'storybook/internal/client-logger' for browser code
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions that need to be tested from their modules

Files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
code/**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

code/**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier with --write flag to format code before committing
Run ESLint with yarn lint:js:cmd to check for linting issues and fix errors before committing

Files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.
📚 Learning: 2025-10-03T07:55:42.639Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/manager/components/preview/Toolbar.tsx:102-105
Timestamp: 2025-10-03T07:55:42.639Z
Learning: In code/core/src/manager/components/preview/Toolbar.tsx, we intentionally do not add aria-label/aria-labelledby to StyledToolbar (AbstractToolbar) because the enclosing section is already labeled via an sr-only heading and the toolbar is the only content. Revisit only if real user testing indicates a need.

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
📚 Learning: 2025-11-28T14:50:24.889Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-28T14:50:24.889Z
Learning: Follow existing patterns and conventions in the Storybook codebase

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-11-05T09:38:47.712Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
📚 Learning: 2025-11-05T09:37:25.920Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/tooltip/WithTooltip.tsx:54-96
Timestamp: 2025-11-05T09:37:25.920Z
Learning: Repo: storybookjs/storybook — In code/core/src/components/components/tooltip/WithTooltip.tsx, the legacy WithTooltip implementation is intentionally reintroduced for backward compatibility and is deprecated; maintainers (per Sidnioulz) do not want maintenance or improvements on it. Prefer WithTooltipNew/Popover; avoid suggesting changes to WithTooltip.* going forward.

Applied to files:

  • code/core/src/toolbar/components/ToolbarMenuSelect.tsx
  • code/core/src/components/components/Select/Select.stories.tsx
📚 Learning: 2025-11-05T09:36:55.944Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.

Applied to files:

  • code/core/src/components/components/Select/Select.stories.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/core/src/toolbar/components/ToolbarMenuSelect.tsx (1)

36-100: Dynamic toolbar title now correctly controlled via dynamicTitle

Wiring dynamicTitle (defaulting to true) through to showSelectedOptionTitle while always rendering the static title as children cleanly restores the expected behavior: dynamicTitle: false keeps the toolbar label fixed, and the default preserves the previous dynamic title behavior. The icon selection logic remains unchanged and gated by preventDynamicIcon, which is appropriate.

Copy link
Copy Markdown
Member

@Sidnioulz Sidnioulz left a comment

Choose a reason for hiding this comment

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

Kudos @ia319, there's just one tiny thing to do with Select multiSelect and we can merge this. Thanks for your contribution ❤️

Comment thread code/core/src/components/components/Select/Select.stories.tsx
@Sidnioulz Sidnioulz self-requested a review December 19, 2025 12:16
@Sidnioulz Sidnioulz changed the title fix(core): fix dynamicTitle: false not taking effect in the toolbar. Globals: Repair dynamicTitle: false for user-defined tools Dec 19, 2025
@Sidnioulz Sidnioulz added the bug label Dec 19, 2025
@Sidnioulz Sidnioulz added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Dec 19, 2025
Copy link
Copy Markdown
Member

@Sidnioulz Sidnioulz left a comment

Choose a reason for hiding this comment

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

Thanks @ia319!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/core/src/components/components/Select/Select.tsx (1)

48-52: Update children JSDoc + mark legacy prop as deprecated

children’s comment (Line 48-51) now overstates behavior (“is replaced”); it’s only replaced when showSelectedOptionTitle is true. Also, since this prop is explicitly “legacy”, adding @deprecated helps prevent new usage via TS hints.

Proposed diff
   /**
    * Label for the Select component. In single-select mode, is replaced by the currently selected
-   * option's title.
+   * option's title when `showSelectedOptionTitle` is true.
    */
   children?: React.ReactNode;

   /**
    * Legacy option for ToolbarMenuSelect. Do not use in new code. Controls whether to show the
    * selected option's title.
    *
+   * `@deprecated` Legacy option for ToolbarMenuSelect; do not use in new code.
    * `@default` true
    */
   showSelectedOptionTitle?: boolean;

Also applies to: 81-88

🧹 Nitpick comments (1)
code/core/src/components/components/Select/Select.tsx (1)

203-220: Prefer explicit ternary/?? over || for the single-select label

(showSelectedOptionTitle && selectedOptions[0]?.title) || children is compact but treats '' as “missing” and is a bit opaque. A ternary with ?? is clearer and avoids falsy edge-cases.

Proposed diff
-              {(showSelectedOptionTitle && selectedOptions[0]?.title) || children}
+              {showSelectedOptionTitle ? (selectedOptions[0]?.title ?? children) : children}

Also applies to: 532-536

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eec0b3d and 66a1278.

📒 Files selected for processing (2)
  • code/core/src/components/components/Select/Select.stories.tsx
  • code/core/src/components/components/Select/Select.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/core/src/components/components/Select/Select.stories.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx,json,md,html,css,scss}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Format code using Prettier with yarn prettier --write <file>

Files:

  • code/core/src/components/components/Select/Select.tsx
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Run ESLint checks using yarn lint:js:cmd <file> or the full command cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives to fix linting errors before committing

Files:

  • code/core/src/components/components/Select/Select.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode across all packages

Files:

  • code/core/src/components/components/Select/Select.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Export functions from modules if they need to be tested
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/components/components/Select/Select.tsx
code/{core,lib,addons,builders,frameworks,presets}/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use logger from storybook/internal/node-logger for server-side logging in Node.js code

Files:

  • code/core/src/components/components/Select/Select.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Select/Select.tsx:200-204
Timestamp: 2025-11-05T09:38:47.712Z
Learning: Repo: storybookjs/storybook — Guidance: Until Storybook 11 is released, do not suggest using React.useId anywhere (e.g., in code/core/src/components/components/Select/Select.tsx) to maintain compatibility with React 17 runtimes. Prefer advising: accept a caller-provided props.id and, if needed, generate a client-only fallback id to minimize SSR hydration issues — but avoid useId. Resume prompting for useId after Storybook 11.
📚 Learning: 2025-11-05T09:36:55.944Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32458
File: code/core/src/components/components/Tabs/Tabs.stories.tsx:222-227
Timestamp: 2025-11-05T09:36:55.944Z
Learning: Repo: storybookjs/storybook PR: 32458 — In code/core/src/components/components/Button/Button.tsx (React/TypeScript), ButtonProps includes ariaLabel?: string | false and the component maps it to the DOM aria-label. Convention: ariaLabel is mandatory on all Button usages — provide a descriptive string for icon-only buttons; set ariaLabel=false when the button’s children already serve as the accessible name. Do not suggest using a raw aria-label prop on Button call sites.

Applied to files:

  • code/core/src/components/components/Select/Select.tsx
🔇 Additional comments (1)
code/core/src/components/components/Select/Select.tsx (1)

490-501: Verify a11y intent: dynamic ariaLabel when visual title is fixed

When showSelectedOptionTitle === false, the visible label stays as children, but finalAriaLabel still includes the selected option’s title (Line 493-499). That may be intended (announce current value), but it’s worth confirming it doesn’t reintroduce “dynamic title” behavior for screen readers in the toolbar use-case.

Also applies to: 532-536

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@ndelangen ndelangen added patch:yes Bugfix & documentation PR that need to be picked to main branch and removed patch:yes Bugfix & documentation PR that need to be picked to main branch labels Jan 26, 2026
@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented Jan 26, 2026

Package Benchmarks

Commit: 9eaacdb, ran on 4 February 2026 at 20:38:06 UTC

No significant changes detected, all good. 👏

@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @ia319

Thank you for putting together this PR!

This PR has some merge conflicts. Would you be able to take a look?

@ia319 ia319 force-pushed the bug/33281-dynamic-title-select branch from 66a1278 to 9eaacdb Compare February 4, 2026 20:24
@ia319
Copy link
Copy Markdown
Member Author

ia319 commented Feb 4, 2026

@valentinpalkovic Conflicts resolved. Verified that yarn test and yarn lint passed without any related issues.

@valentinpalkovic valentinpalkovic merged commit d355c8b into storybookjs:next Feb 4, 2026
112 of 115 checks passed
@github-project-automation github-project-automation Bot moved this from Empathy Queue (prioritized) to Done in Core Team Projects Feb 4, 2026
valentinpalkovic added a commit that referenced this pull request Feb 5, 2026
Globals: Repair dynamicTitle: false for user-defined tools
(cherry picked from commit d355c8b)
@github-actions github-actions Bot added the patch:done Patch/release PRs already cherry-picked to main/release branch label Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal needs triage patch:done Patch/release PRs already cherry-picked to main/release branch patch:yes Bugfix & documentation PR that need to be picked to main branch

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Setting dynamicTitle to false in globals has no effect

5 participants