Skip to content

Conversation

@seongminn
Copy link
Contributor

@seongminn seongminn commented Sep 10, 2025

  1. Add the data-popup-open attribute to the Icon component, similar to the NavigationMenu component. (6c96cf8)
  2. Fix the issue where the Icon component's ref is incorrectly typed as HTMLDivElement, contrary to the documentation. (2594180)
  3. Add the data-placeholder attribute to Select.Value when a placeholder item with no value is selected. This allows for applying custom styles. (d3eb638) split this out into a [select] add data-placeholder #2737

@pkg-pr-new
Copy link

pkg-pr-new bot commented Sep 10, 2025

Open in StackBlitz

pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/react@2714
pnpm add https://pkg.pr.new/mui/base-ui/@base-ui-components/utils@2714

commit: 1b490bf

@netlify
Copy link

netlify bot commented Sep 10, 2025

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 1b490bf
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/68c820359e86d40008a07b4d
😎 Deploy Preview https://deploy-preview-2714--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@mui-bot
Copy link

mui-bot commented Sep 10, 2025

Bundle size report

Bundle Parsed size Gzip size
@base-ui-components/react 🔺+97B(+0.03%) 🔺+6B(+0.01%)

Details of bundle changes

@seongminn seongminn changed the title [Select] Usability Improvements [select] Usability Improvements Sep 10, 2025
Comment on lines 54 to 56
value,
placeholder: value === null,
}),
Copy link
Contributor

@atomiks atomiks Sep 10, 2025

Choose a reason for hiding this comment

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

One potential issue with this is with item objects as values (#2704), where the null item is an object.

Two use cases:

  • The null item object isn't in the popup list, so this isn't a concern (null is the default and will match like a real placeholder; you can't "deselect" to go back to the placeholder via the popup items list)
  • The null item object is in the popup list, and you need to use defaultValue={items[0]} to ensure it's initially selected, since it appears in the list. Then data-placeholder won't be added.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the detailed feedback!

To make sure I understand correctly, are you referring to a use case like the one below, where the placeholder is an item object with an empty string as its value?

const items = [
  { country: 'Select Country', code: '' },
  { country: 'United States', code: 'US' },
  { country: 'Canada', code: 'CA' },
  { country: 'Australia', code: 'AU' },
];

<Select.Root
  name="country"
  defaultValue={items[0]}
  itemToStringLabel={(item) => item.country}
  itemToStringValue={(item) => item.code}
>
  <Select.Trigger>
    <Select.Value />
  </Select.Trigger>
  <Select.Portal>
    <Select.Positioner>
      <Select.Popup>
        {items.map((it) => (
          <Select.Item key={it.code} value={it}>
            {it.country}
          </Select.Item>
        ))}
      </Select.Popup>
    </Select.Positioner>
  </Select.Portal>
</Select.Root>

If so, what are your thoughts on using the existing serializedValue from SelectRoot to handle this?

const serializedValue = React.useMemo(() => {
  if (isMultiple && Array.isArray(value) && value.length === 0) {
    return '';
  }
  return stringifyAsValue(value, itemToStringValue);
}, [isMultiple, value, itemToStringValue]);

const state: SelectValue.State = React.useMemo(
  () => ({
    value,
    placeholder: !serializedValue, // An empty string will correctly evaluate to `true`
  }),
  [value, serializedValue],
);

Copy link
Contributor

@atomiks atomiks Sep 11, 2025

Choose a reason for hiding this comment

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

Yeah, effectively - an empty string could be considered a placeholder as well:

const items = [
  { value: null, label: 'select' },
  { value: 'apple', label: 'Apple' },
]

<Select.Root items={items} defaultValue={items[0]}>
  <Select.Item value={item}> {/* full object when mapping */}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@atomiks

Got it, thanks for confirming!

It looks like this changes depends on #2704, so I'm going to revert it for now.

And I'll open a new PR for these changes, using #2704 as the base.

Thank you!

@atomiks atomiks added the component: select Changes related to the select component. label Sep 11, 2025
@seongminn seongminn mentioned this pull request Sep 11, 2025
1 task
@atomiks atomiks changed the title [select] Usability Improvements [select] Add open state for Select.Icon and fix ref type Sep 14, 2025
Copy link
Contributor

@atomiks atomiks left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for the contribution

pnpm docs:api needs to be run though. SelectIconDataAttributes file also needs to be created (with that command run) so it displays the data-popup-open attr in a table in the docs

@seongminn
Copy link
Contributor Author

@atomiks I added SelectIconDataAttributes.ts and updated docs. Thank you for your feedback!

@atomiks atomiks merged commit 296ecdd into mui:master Sep 16, 2025
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: select Changes related to the select component.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants