Select 
Select provides users with a floating element containing a list of options to choose from.
Show code 'use client' ; import  *  as  React  from  'react' ; import  {  Select  }  from  '@base-ui-components/react/Select' ; import  {  css ,  styled  }  from  '@mui/system' ; export  default  function  SelectIntroduction () {   return  (     < Select.Root  defaultValue = "system" >       < SelectTrigger  aria-label = "Select font" >         < Select.Value  placeholder = "System font"  />         < SelectDropdownArrow  />       </ SelectTrigger >       < SelectPositioner  sideOffset = { 5 }>         < SelectScrollUpArrow  />         < SelectPopup >           < SelectOption  value = "system" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >System font</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "arial" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Arial</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "roboto" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Roboto</ Select.OptionText >           </ SelectOption >         </ SelectPopup >         < SelectScrollDownArrow  />       </ SelectPositioner >     </ Select.Root >   ); } const  CheckIcon  =  styled ( function  CheckIcon ( props :  React . SVGProps < SVGSVGElement >) {   return  (     < svg       xmlns = "http://www.w3.org/2000/svg"       { ... props }       width = "24"       height = "24"       viewBox = "0 0 24 24"       fill = "none"     >       < path         d = "M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"         fill = "currentColor"       />     </ svg >   ); }) `   width: 100%;   height: 100%; ` ; const  triggerPaddingX  =  6 ; const  popupPadding  =  4 ; const  SelectTrigger  =  styled ( Select . Trigger ) `   font-family: 'IBM Plex Sans', sans-serif;   display: flex;   align-items: center;   justify-content: space-between;   padding: ${ triggerPaddingX }px 12px;   border-radius: 5px;   background-color: black;   color: white;   border: none;   font-size: 100%;   line-height: 1.5;   user-select: none;   cursor: default;   &:focus-visible {     outline: 2px solid black;     outline-offset: 2px;   } ` ; const  SelectDropdownArrow  =  styled ( Select . Icon ) `   margin-left: 6px;   font-size: 10px;   line-height: 1;   height: 6px; ` ; const  SelectPositioner  =  styled ( Select . Positioner ) `   &[data-side='none'] {     z-index: 1;   } ` ; const  SelectPopup  =  styled ( Select . Popup ) `   overflow-y: auto;   background-color: white;   padding: ${ popupPadding }px;   border-radius: 5px;   box-shadow:     0 2px 4px rgb(0 0 0 / 0.1),     0 0 0 1px rgb(0 0 0 / 0.1);   max-height: var(--available-height);   min-width: min(     calc(var(--available-width) - ${ popupPadding  *  2 }px),     calc(var(--anchor-width) + ${ triggerPaddingX  *  2  +  popupPadding  *  2 }px)   );   scroll-padding: ${ popupPadding }px;   &[data-side='none'] {     scroll-padding: 15px;   }   --padding: 6px;   --icon-size: 16px;   --icon-margin: 4px; ` ; const  SelectOption  =  styled ( Select . Option ) `   outline: 0;   cursor: default;   border-radius: 4px;   user-select: none;   display: flex;   align-items: center;   line-height: 1.5;   padding-block: var(--padding);   padding-inline: calc(var(--padding) + var(--icon-margin) + var(--icon-size));   &[data-selected] {     padding-left: var(--padding);   }   &[data-disabled] {     opacity: 0.5;   }   &[data-highlighted] {     background-color: black;     color: white;   } ` ; const  SelectOptionIndicator  =  styled ( Select . OptionIndicator ) `   margin-right: var(--icon-margin);   visibility: hidden;   width: var(--icon-size);   height: var(--icon-size);   &[data-selected] {     visibility: visible;   } ` ; const  scrollArrowStyles  =  css `   position: relative;   width: 100%;   height: 15px;   font-size: 10px;   cursor: default;   background: white;   display: flex;   align-items: center;   justify-content: center;   border-radius: 5px;   z-index: 1;   &[data-side='none'] {     &::before {       content: '';       display: block;       position: absolute;       width: 100%;       height: calc(100% + 10px);     }   } ` ; const  SelectScrollUpArrow  =  styled ( Select . ScrollUpArrow ) `   ${ scrollArrowStyles }   &::before {     top: -10px;   } ` ; const  SelectScrollDownArrow  =  styled ( Select . ScrollDownArrow ) `   ${ scrollArrowStyles }   bottom: 0;   &::before {     top: 0;   } ` ; Base UI components are all available as a single package.
npm pnpm Yarn 
npm install @base-ui-components/react 
Once you have the package installed, import the component.
import { Select } from '@base-ui-components/react/Select'; Selects are implemented using a collection of related components:
<Select.Root /> is a top-level component that wraps the other components.<Select.Trigger /> renders the trigger element that opens the select popup on click.<Select.Value /> renders the value of the select.<Select.Icon /> renders a caret icon.<Select.Backdrop /> renders a backdrop element behind the popup.<Select.Positioner /> renders the select popup's positioning element.<Select.Popup /> renders the select popup itself.<Select.Option /> renders an option, placed inside the popup.<Select.OptionText /> renders the text of an option.<Select.OptionIndicator /> renders an option indicator inside an option to indicate it's selected (e.g. a check icon).<Select.Group /> renders a group for a set of options, wrapping <Select.Option> components.<Select.GroupLabel /> renders a label for a group of options.<Select.ScrollUpArrow /> renders a scrolling arrow for the alignOptionToTrigger anchoring mode.<Select.ScrollDownArrow /> renders a scrolling arrow for the alignOptionToTrigger anchoring mode.<Select.Separator /> renders a separator between option groups.<Select.Arrow /> renders the select popup's arrow when disabling alignOptionToTrigger. 
< Select.Root >   < Select.Trigger >     < Select.Value  />     < Select.Icon  />   </ Select.Trigger >   < Select.Backdrop  />   < Select.Positioner >     < Select.ScrollUpArrow  />     < Select.Popup >       < Select.Group >         < Select.GroupLabel  />         < Select.Option >           < Select.OptionText  />           < Select.OptionIndicator  />         </ Select.Option >       </ Select.Group >       < Select.Separator  />     </ Select.Popup >     < Select.ScrollDownArrow  />     < Select.Arrow  />   </ Select.Positioner > </ Select.Root > To set an initial value when uncontrolled, use defaultValue:
< Select.Root  defaultValue = "system" > The select's value is empty (null) by default, which enables an empty Option to be initially selected when it has no value prop:
Show code 'use client' ; import  *  as  React  from  'react' ; import  {  Select  }  from  '@base-ui-components/react/Select' ; import  {  css ,  styled  }  from  '@mui/system' ; export  default  function  SelectEmpty () {   return  (     < Select.Root >       < SelectTrigger  aria-label = "Select font" >         < Select.Value  placeholder = "Select font..."  />         < SelectDropdownArrow  />       </ SelectTrigger >       < SelectPositioner  sideOffset = { 5 }>         < SelectScrollUpArrow  />         < SelectPopup >           < SelectOption >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Select font...</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "system" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >System font</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "arial" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Arial</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "roboto" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Roboto</ Select.OptionText >           </ SelectOption >         </ SelectPopup >         < SelectScrollDownArrow  />       </ SelectPositioner >     </ Select.Root >   ); } const  CheckIcon  =  styled ( function  CheckIcon ( props :  React . SVGProps < SVGSVGElement >) {   return  (     < svg       xmlns = "http://www.w3.org/2000/svg"       { ... props }       width = "24"       height = "24"       viewBox = "0 0 24 24"       fill = "none"     >       < path         d = "M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"         fill = "currentColor"       />     </ svg >   ); }) `   width: 100%;   height: 100%; ` ; const  triggerPaddingX  =  6 ; const  popupPadding  =  4 ; const  SelectTrigger  =  styled ( Select . Trigger ) `   font-family: 'IBM Plex Sans', sans-serif;   display: flex;   align-items: center;   justify-content: space-between;   padding: ${ triggerPaddingX }px 12px;   border-radius: 5px;   background-color: black;   color: white;   border: none;   font-size: 100%;   line-height: 1.5;   user-select: none;   cursor: default;   &:focus-visible {     outline: 2px solid black;     outline-offset: 2px;   } ` ; const  SelectDropdownArrow  =  styled ( Select . Icon ) `   margin-left: 6px;   font-size: 10px;   line-height: 1;   height: 6px; ` ; const  SelectPositioner  =  styled ( Select . Positioner ) `   &[data-side='none'] {     z-index: 1;   } ` ; const  SelectPopup  =  styled ( Select . Popup ) `   overflow-y: auto;   background-color: white;   padding: ${ popupPadding }px;   border-radius: 5px;   box-shadow:     0 2px 4px rgb(0 0 0 / 0.1),     0 0 0 1px rgb(0 0 0 / 0.1);   max-height: var(--available-height);   min-width: min(     calc(var(--available-width) - ${ popupPadding  *  2 }px),     calc(var(--anchor-width) + ${ triggerPaddingX  *  2  +  popupPadding  *  2 }px)   );   scroll-padding: ${ popupPadding }px;   &[data-side='none'] {     scroll-padding: 15px;   }   --padding: 6px;   --icon-size: 16px;   --icon-margin: 4px; ` ; const  SelectOption  =  styled ( Select . Option ) `   outline: 0;   cursor: default;   border-radius: 4px;   user-select: none;   display: flex;   align-items: center;   line-height: 1.5;   padding-block: var(--padding);   padding-inline: calc(var(--padding) + var(--icon-margin) + var(--icon-size));   &[data-selected] {     padding-left: var(--padding);   }   &[data-disabled] {     opacity: 0.5;   }   &[data-highlighted] {     background-color: black;     color: white;   } ` ; const  SelectOptionIndicator  =  styled ( Select . OptionIndicator ) `   margin-right: var(--icon-margin);   visibility: hidden;   width: var(--icon-size);   height: var(--icon-size);   &[data-selected] {     visibility: visible;   } ` ; const  scrollArrowStyles  =  css `   position: relative;   width: 100%;   height: 15px;   font-size: 10px;   cursor: default;   background: white;   display: flex;   align-items: center;   justify-content: center;   border-radius: 5px;   z-index: 1;   &[data-side='none'] {     &::before {       content: '';       display: block;       position: absolute;       width: 100%;       height: calc(100% + 10px);     }   } ` ; const  SelectScrollUpArrow  =  styled ( Select . ScrollUpArrow ) `   ${ scrollArrowStyles }   &::before {     top: -10px;   } ` ; const  SelectScrollDownArrow  =  styled ( Select . ScrollDownArrow ) `   ${ scrollArrowStyles }   bottom: 0;   &::before {     top: 0;   } ` ; To control the value with external state, specify the value and onValueChange props:
const  [ value ,  setValue ]  =  React . useState ( 'system' ); return  (   < Select.Root  value = { value }  onValueChange = { setValue }>     { /* subcomponents */ }   </ Select.Root > ); The Select.OptionIndicator subcomponent renders an indicator inside an option to indicate it's selected. By default, it renders a check icon, but this can be customized:
< Select.OptionIndicator >   < MyCheckIcon  /> </ Select.OptionIndicator > Select.Group can be used to group options together with a label. The Select.GroupLabel subcomponent renders the label:
< Select.Group >   < Select.GroupLabel >Label</ Select.GroupLabel >   < Select.Option  value = "option1" >Option 1</ Select.Option >   < Select.Option  value = "option2" >Option 2</ Select.Option > </ Select.Group > Show code 'use client' ; import  *  as  React  from  'react' ; import  {  Select  }  from  '@base-ui-components/react/Select' ; import  {  css ,  styled  }  from  '@mui/system' ; function  createOptions ( items :  string []) {   return  items . map (( item )  =>  ({     value:  item ,     label:  item [ 0 ]. toUpperCase ()  +  item . slice ( 1 ),   })); } const  data  =  {   Fruits:  createOptions ([ 'apple' ,  'banana' ,  'orange' ,  'pear' ,  'grape' ,  'pineapple' ]),   Vegetables:  createOptions ([     'carrot' ,     'lettuce' ,     'broccoli' ,     'cauliflower' ,     'asparagus' ,     'zucchini' ,   ]), }; const  entries  =  Object . entries ( data ); export  default  function  SelectGroup () {   return  (     < Select.Root >       < SelectTrigger  aria-label = "Select food" >         < Select.Value  placeholder = "Select food..."  />         < SelectDropdownArrow  />       </ SelectTrigger >       < SelectPositioner  sideOffset = { 5 }>         < SelectScrollUpArrow  />         < SelectPopup >           < SelectOption >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Select food...</ Select.OptionText >           </ SelectOption >           { entries . map (([ group ,  items ])  =>  (             < React.Fragment  key = { group }>               < SelectSeparator  />               < Select.Group  key = { group }>                 < SelectGroupLabel >{ group }</ SelectGroupLabel >                 { items . map (( item )  =>  (                   < SelectOption                     key = { item . value }                     value = { item . value }                     disabled = { item . value  ===  'banana' }                   >                     < SelectOptionIndicator  render = {< CheckIcon  />} />                     < Select.OptionText >{ item . label }</ Select.OptionText >                   </ SelectOption >                 ))}               </ Select.Group >             </ React.Fragment >           ))}         </ SelectPopup >         < SelectScrollDownArrow  />       </ SelectPositioner >     </ Select.Root >   ); } const  CheckIcon  =  styled ( function  CheckIcon ( props :  React . SVGProps < SVGSVGElement >) {   return  (     < svg       xmlns = "http://www.w3.org/2000/svg"       { ... props }       width = "24"       height = "24"       viewBox = "0 0 24 24"       fill = "none"     >       < path         d = "M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"         fill = "currentColor"       />     </ svg >   ); }) `   width: 100%;   height: 100%; ` ; const  gray  =  {   300 :  '#e5e7eb' , }; const  triggerPaddingX  =  6 ; const  popupPadding  =  4 ; const  SelectTrigger  =  styled ( Select . Trigger ) `   font-family: 'IBM Plex Sans', sans-serif;   display: flex;   align-items: center;   justify-content: space-between;   padding: ${ triggerPaddingX }px 12px;   border-radius: 5px;   background-color: black;   color: white;   border: none;   font-size: 100%;   line-height: 1.5;   user-select: none;   cursor: default;   &:focus-visible {     outline: 2px solid black;     outline-offset: 2px;   } ` ; const  SelectDropdownArrow  =  styled ( Select . Icon ) `   margin-left: 6px;   font-size: 10px;   line-height: 1;   height: 6px; ` ; const  SelectPositioner  =  styled ( Select . Positioner ) `   &[data-side='none'] {     z-index: 1;   } ` ; const  SelectPopup  =  styled ( Select . Popup ) `   overflow-y: auto;   background-color: white;   padding: ${ popupPadding }px;   border-radius: 5px;   box-shadow:     0 2px 4px rgb(0 0 0 / 0.1),     0 0 0 1px rgb(0 0 0 / 0.1);   max-height: var(--available-height);   min-width: min(     calc(var(--available-width) - ${ popupPadding  *  2 }px),     calc(var(--anchor-width) + ${ triggerPaddingX  *  2  +  popupPadding  *  2 }px)   );   scroll-padding: ${ popupPadding }px;   &[data-side='none'] {     scroll-padding: 15px;   }   --padding: 6px;   --icon-size: 16px;   --icon-margin: 4px; ` ; const  SelectOption  =  styled ( Select . Option ) `   outline: 0;   cursor: default;   border-radius: 4px;   user-select: none;   display: flex;   align-items: center;   line-height: 1.5;   padding-block: var(--padding);   padding-inline: calc(var(--padding) + var(--icon-margin) + var(--icon-size));   &[data-selected] {     padding-left: var(--padding);   }   &[data-disabled] {     opacity: 0.5;   }   &[data-highlighted] {     background-color: black;     color: white;   } ` ; const  SelectOptionIndicator  =  styled ( Select . OptionIndicator ) `   margin-right: var(--icon-margin);   visibility: hidden;   width: var(--icon-size);   height: var(--icon-size);   &[data-selected] {     visibility: visible;   } ` ; const  scrollArrowStyles  =  css `   position: relative;   width: 100%;   height: 15px;   font-size: 10px;   cursor: default;   background: white;   display: flex;   align-items: center;   justify-content: center;   border-radius: 5px;   z-index: 1;   &[data-side='none'] {     &::before {       content: '';       display: block;       position: absolute;       width: 100%;       height: calc(100% + 10px);     }   } ` ; const  SelectScrollUpArrow  =  styled ( Select . ScrollUpArrow ) `   ${ scrollArrowStyles }   &::before {     top: -10px;   } ` ; const  SelectScrollDownArrow  =  styled ( Select . ScrollDownArrow ) `   ${ scrollArrowStyles }   bottom: 0;   &::before {     top: 0;   } ` ; const  SelectGroupLabel  =  styled ( Select . GroupLabel ) `   font-weight: bold;   padding: var(--padding)     calc(var(--padding) + var(--icon-margin) + var(--icon-size));   cursor: default;   user-select: none; ` ; const  SelectSeparator  =  styled ( Select . Separator ) `   height: 1px;   background-color: ${ gray [ 300 ] };   margin: 5px 0; ` ; By default, the selected option inside the popup is aligned to the trigger element. This can be disabled with the alignOptionToTrigger prop:
< Select.Root  alignOptionToTrigger = { false }> 
alignOptionToTrigger={true}[data-side] attribute value is none on both Select.Positioner and Select.Popup when in this mode, allowing it to be styled differently.alignOptionToTrigger={false} 
alignOptionToTrigger is always false on touch devices or touch input.
Scrolling is locked when alignOptionToTrigger is true to prevent unwanted scrolling of the
background when expanding the popup, ensuring positioning remains correct.
Show code 'use client' ; import  *  as  React  from  'react' ; import  {  Select  }  from  '@base-ui-components/react/Select' ; import  {  css ,  styled  }  from  '@mui/system' ; function  AlignOptionToTriggerTrue () {   return  (     < Select.Root >       < SelectTrigger  aria-label = "Select font" >         < Select.Value  placeholder = "Align option to trigger"  />         < SelectDropdownArrow  />       </ SelectTrigger >       < SelectPositioner  sideOffset = { 5 }>         < SelectScrollUpArrow  />         < SelectPopup >           < SelectOption >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Align option to trigger</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "system" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >System font</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "arial" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Arial</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "roboto" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Roboto</ Select.OptionText >           </ SelectOption >         </ SelectPopup >         < SelectScrollDownArrow  />       </ SelectPositioner >     </ Select.Root >   ); } function  AlignOptionToTriggerFalse () {   return  (     < Select.Root  alignOptionToTrigger = { false }>       < SelectTrigger  aria-label = "Select font" >         < Select.Value  placeholder = "Align popup to trigger"  />         < SelectDropdownArrow  />       </ SelectTrigger >       < SelectPositioner  sideOffset = { 5 }>         < SelectScrollUpArrow  />         < SelectPopup >           < SelectOption >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Align popup to trigger</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "system" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >System font</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "arial" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Arial</ Select.OptionText >           </ SelectOption >           < SelectOption  value = "roboto" >             < SelectOptionIndicator  render = {< CheckIcon  />} />             < Select.OptionText >Roboto</ Select.OptionText >           </ SelectOption >         </ SelectPopup >         < SelectScrollDownArrow  />       </ SelectPositioner >     </ Select.Root >   ); } export  default  function  SelectAlign () {   return  (     < div       style = {{         display:  'flex' ,         justifyContent:  'center' ,         alignItems:  'center' ,         gap:  10 ,       }}     >       < AlignOptionToTriggerTrue  />       < AlignOptionToTriggerFalse  />     </ div >   ); } const  CheckIcon  =  styled ( function  CheckIcon ( props :  React . SVGProps < SVGSVGElement >) {   return  (     < svg       xmlns = "http://www.w3.org/2000/svg"       { ... props }       width = "24"       height = "24"       viewBox = "0 0 24 24"       fill = "none"     >       < path         d = "M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"         fill = "currentColor"       />     </ svg >   ); }) `   width: 100%;   height: 100%; ` ; const  triggerPaddingX  =  6 ; const  popupPadding  =  4 ; const  SelectTrigger  =  styled ( Select . Trigger ) `   font-family: 'IBM Plex Sans', sans-serif;   display: flex;   align-items: center;   justify-content: space-between;   padding: ${ triggerPaddingX }px 12px;   border-radius: 5px;   background-color: black;   color: white;   border: none;   font-size: 100%;   line-height: 1.5;   user-select: none;   cursor: default;   &:focus-visible {     outline: 2px solid black;     outline-offset: 2px;   } ` ; const  SelectDropdownArrow  =  styled ( Select . Icon ) `   margin-left: 6px;   font-size: 10px;   line-height: 1;   height: 6px; ` ; const  SelectPositioner  =  styled ( Select . Positioner ) `   &[data-side='none'] {     z-index: 1;   } ` ; const  SelectPopup  =  styled ( Select . Popup ) `   overflow-y: auto;   background-color: white;   padding: ${ popupPadding }px;   border-radius: 5px;   box-shadow:     0 2px 4px rgb(0 0 0 / 0.1),     0 0 0 1px rgb(0 0 0 / 0.1);   max-height: var(--available-height);   min-width: min(     calc(var(--available-width) - ${ popupPadding  *  2 }px),     calc(var(--anchor-width) + ${ triggerPaddingX  *  2  +  popupPadding  *  2 }px)   );   scroll-padding: ${ popupPadding }px;   &[data-side='none'] {     scroll-padding: 15px;   }   --padding: 6px;   --icon-size: 16px;   --icon-margin: 4px; ` ; const  SelectOption  =  styled ( Select . Option ) `   outline: 0;   cursor: default;   border-radius: 4px;   user-select: none;   display: flex;   align-items: center;   line-height: 1.5;   padding-block: var(--padding);   padding-inline: calc(var(--padding) + var(--icon-margin) + var(--icon-size));   &[data-selected] {     padding-left: var(--padding);   }   &[data-disabled] {     opacity: 0.5;   }   &[data-highlighted] {     background-color: black;     color: white;   } ` ; const  SelectOptionIndicator  =  styled ( Select . OptionIndicator ) `   margin-right: var(--icon-margin);   visibility: hidden;   width: var(--icon-size);   height: var(--icon-size);   &[data-selected] {     visibility: visible;   } ` ; const  scrollArrowStyles  =  css `   position: relative;   width: 100%;   height: 15px;   font-size: 10px;   cursor: default;   background: white;   display: flex;   align-items: center;   justify-content: center;   border-radius: 5px;   z-index: 1;   &[data-side='none'] {     &::before {       content: '';       display: block;       position: absolute;       width: 100%;       height: calc(100% + 10px);     }   } ` ; const  SelectScrollUpArrow  =  styled ( Select . ScrollUpArrow ) `   ${ scrollArrowStyles }   &::before {     top: -10px;   } ` ; const  SelectScrollDownArrow  =  styled ( Select . ScrollDownArrow ) `   ${ scrollArrowStyles }   bottom: 0;   &::before {     top: 0;   } ` ; The select's height needs to be manually limited by its available space using CSS.
This can be achieved by using the --available-height CSS variable:
< Select.Popup  className = "SelectPopup" > .SelectPopup  {   max-height :  var ( --available-height ); } The Select.Value subcomponent renders the selected value. This is the text content or label of Select.Option by default.
The placeholder prop can be used when the value is empty. During SSR, if a default value is specified as the selected option, the value isn't available until hydration:
< Select.Trigger >   < Select.Value  placeholder = "Select value..."  /> </ Select.Trigger > A function can be specified as a child to customize the rendering of the value:
< Select.Value >{( value )  =>  value . toLowerCase ()}</ Select.Value > To add an arrow (caret or triangle) inside the select popup that points toward the center of the anchor element, use the Select.Arrow component:
This is not supported when alignOptionToTrigger is true.
< Select.Positioner >   < Select.Popup  />   < Select.Arrow  /> </ Select.Positioner > It automatically positions a wrapper element that can be styled or contain a custom SVG shape.
The select can animate when opening or closing with either:
CSS transitions 
CSS animations 
JavaScript animations 
 
Here is an example of how to apply a symmetric scale and fade transition with the default conditionally-rendered behavior:
< Select.Popup  className = "SelectPopup" >   < Select.Option >Option 1</ Select.Option > </ Select.Popup > .SelectPopup  {   transform-origin :  var ( --transform-origin );   transition-property : opacity, transform;   transition-duration :  0.2 s ;   /* Represents the final styles once exited */   opacity :  0 ;   transform :  scale ( 0.9 ); } /* Represents the final styles once entered */ .SelectPopup [ data-open ] {   opacity :  1 ;   transform :  scale ( 1 ); } /* Represents the initial styles when entering */ .SelectPopup [ data-entering ] {   opacity :  0 ;   transform :  scale ( 0.9 ); } Styles need to be applied in three states:
The exiting styles, placed on the base element class 
The open styles, placed on the base element class with [data-state="open"] 
The entering styles, placed on the base element class with [data-entering] 
 
In newer browsers, there is a feature called @starting-style which allows transitions to occur on open for conditionally-mounted components:
/* Base UI API - Polyfill */ .SelectPopup [ data-entering ] {   opacity :  0 ;   transform :  scale ( 0.9 ); } /* Official Browser API - no Firefox support as of May 2024 */ @starting-style  {   .SelectPopup [ data-open ] {     opacity :  0 ;     transform :  scale ( 0.9 );   } } CSS animations can also be used, requiring only two separate declarations:
@keyframes  scale-in  {   from  {     opacity :  0 ;     transform :  scale ( 0.9 );   } } @keyframes  scale-out  {   to  {     opacity :  0 ;     transform :  scale ( 0.9 );   } } .SelectPopup  {   animation : scale-in  0.2 s  forwards ; } .SelectPopup [ data-exiting ] {   animation : scale-out  0.2 s  forwards ; } The keepMounted prop lets an external library control the mounting, for example framer-motion's AnimatePresence component.
function  App () {   const  [ open ,  setOpen ]  =  useState ( false );   return  (     < Select.Root  open = { open }  onOpenChange = { setOpen }>       < Select.Trigger >Trigger</ Select.Trigger >       < AnimatePresence >         { open  &&  (           < Select.Positioner  keepMounted >             < Select.Popup               render = {                 < motion.div                   initial = {{ opacity:  0  }}                   animate = {{ opacity:  1  }}                   exit = {{ opacity:  0  }}                 />               }             >               < Select.Option >Option 1</ Select.Option >               < Select.Option >Option 2</ Select.Option >             </ Select.Popup >           </ Select.Positioner >         )}       </ AnimatePresence >     </ Select.Root >   ); } Four states are available as data attributes to animate the popup, which enables full control depending on whether the popup is being animated with CSS transitions or animations, JavaScript, or is using the keepMounted prop.
[data-open] - open state is true.[data-entering] - the popup was just inserted to the DOM. The attribute is removed 1 animation frame later. Enables "starting styles" upon insertion for conditional rendering.[data-exiting] - the popup is in the process of being removed from the DOM, but is still mounted. 
Use the render prop to override the rendered elements with your own components.
// Element shorthand < Select.Popup  render = {< MySelectPopup  />} /> // Function < Select.Popup  render = {( props )  =>  < MySelectPopup  { ... props } />} /> API Reference SelectRoot 
Prop Type Default Description alignOptionToTriggerbooltrueDetermines if the selected option inside the popup should align to the trigger element. animatedbooltrueIf true, the Select supports CSS-based animations and transitions. It is kept in the DOM until the animation completes. defaultOpenboolfalseIf true, the Select is initially open. defaultValueanynullThe default value of the select. disabledboolfalseIf true, the Select is disabled. namestringThe name of the Select in the owning form. onOpenChangefuncCallback fired when the component requests to be opened or closed. onValueChangefuncCallback fired when the value of the select changes. Use when controlled. openboolAllows to control whether the dropdown is open. This is a controlled counterpart of defaultOpen. readOnlyboolfalseIf true, the Select is read-only. requiredboolfalseIf true, the Select is required. valueanyThe value of the select. 
SelectTrigger 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. disabledboolfalseIf true, the component is disabled. focusableWhenDisabledboolfalseIf true, allows a disabled button to receive focus. labelstringLabel of the button renderunionA function to customize rendering of the component. 
SelectValue 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. placeholderstringThe placeholder value to display when the value is empty (such as during SSR). renderunionA function to customize rendering of the component. 
SelectIcon 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. renderunionA function to customize rendering of the component. 
SelectBackdrop 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. containerunionfalseThe container element to which the Backdrop is appended to. keepMountedboolfalseIf true, the Backdrop remains mounted when the Select popup is closed. renderunionA function to customize rendering of the component. 
SelectPositioner 
Prop Type Default Description alignmentenum'start'The alignment of the Select element to the anchor element along its cross axis. alignmentOffsetnumber0The offset of the Select element along its alignment axis. anchorunionThe anchor element to which the Select popup will be placed at. arrowPaddingnumber5Determines the padding between the arrow and the Select popup's edges. Useful when the popover popup has rounded corners via border-radius. classNameunionClass names applied to the element or a function that returns them based on the component's state. collisionBoundaryunion'clipping-ancestors'The boundary that the Select element should be constrained to. collisionPaddingunion5The padding of the collision boundary. containerunionThe container element to which the Select popup will be appended to. hideWhenDetachedboolfalseIf true, the Select will be hidden if it is detached from its anchor element due to differing clipping contexts. positionMethodenum'absolute'The CSS position method for positioning the Select popup element. renderunionA function to customize rendering of the component. sideenum'bottom'The side of the anchor element that the Select element should align to. sideOffsetnumber0The gap between the anchor element and the Select element. stickyboolfalseIf true, allow the Select to remain in stuck view while the anchor element is scrolled out of view. trackAnchorbooltrueWhether the select popup continuously tracks its anchor after the initial positioning upon mount. 
Prop Type Default Description unionClass names applied to the element or a function that returns them based on the component's state. stringThe id of the popup element. unionA function to customize rendering of the component. 
SelectOption 
Prop Type Default Description disabledboolfalseIf true, the select option will be disabled. labelstringA text representation of the select option's content. Used for keyboard text navigation matching. valueanynullThe value of the select option. 
SelectOptionText 
Prop Type Default Description 
SelectOptionIndicator 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. keepMountedboolfalseIf true, the item indicator remains mounted when the item is not selected. renderunionA function to customize rendering of the component. 
SelectGroup 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. renderunionA function to customize rendering of the component. 
SelectGroupLabel 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. renderunionA function to customize rendering of the component. 
Prop Type Default Description keepMountedboolfalseWhether the component should be kept mounted when it is not rendered. 
Prop Type Default Description keepMountedboolfalseWhether the component should be kept mounted when it is not rendered. 
SelectArrow 
Prop Type Default Description classNameunionClass names applied to the element or a function that returns them based on the component's state. hideWhenUncenteredboolfalseIf true, the arrow is hidden when it can't point to the center of the anchor element. renderunionA function to customize rendering of the component.