Native select
Native select control styled to match the Control UI control family.
Composition
The preferred shape for composing the installed primitive from its exported parts.
Root
Single-slot surface with no nested parts.
NativeSelect
First install and activate one skin. Core deliberately contains no visual token defaults.
The Control UI source installs this primitive from src/registry/sources/control-ui/ui/native-select.tsx. Install it on its own with the command above, or inspect the source below.
npx shadcn@latest add https://control-ui.dev/r/native-select.jsonKnobs
Typed custom properties the recipe paints with. Set one on the root — style, a utility class, or a skin — and every slot inherits it.
--cui-field-* · 8 knobsHow the cascade resolves--cui-field-radius<length-percentage>var(--radius-control)--cui-field-background*oklch(from var(--card) l c h / 0.72)--cui-field-foreground<color>var(--foreground)--cui-field-border-color<color>var(--border)--cui-field-border-width<length>1px--cui-field-shadow*var(--shadow-sm)--cui-field-backdrop-filter*blur(0px)--cui-field-focus-border-color<color>var(--border)Installed dependencies
Support files installed with this primitive — shared ones arrive once with your first Control UI component. Public dependencies stay linked to their own pages.
src/registry/sources/control-ui/control-variants.tsSupportRaw code
This primitive's source and the support files it installs with
import type { ComponentProps, CSSProperties } from "react";import type { ControlSize } from "@/components/control-ui/control-variants";import { controlSize } from "@/components/control-ui/control-variants";import type { FieldKnobStyle } from "@/components/control-ui/knob-contracts/field-knobs";import { cn } from "@/components/control-ui/lib/cn";export type NativeSelectProps = Omit<Omit<ComponentProps<"select">, "size">, "style"> & { style?: CSSProperties & FieldKnobStyle } & { size?: ControlSize;};// real native <select>, not floating Base UI Select — its options open OS menu, so nothing portals and no scope is re-asserted.export function NativeSelect({ size = "md", className, children, ...props }: NativeSelectProps) { return ( <div className="relative inline-flex w-full items-center"> <select data-control-ui="native-select" data-field-kind="native-select" data-slot="root" data-size={size} data-control-family="field" data-control="true" className={cn("w-full min-w-0 cursor-pointer pr-[calc(var(--padding-x)*1.4)]", controlSize({ size }), className)} {...props} > {children} </select> <span aria-hidden="true" data-control-ui="native-select" data-control-family="field" data-field-kind="native-select" data-slot="icon" className="pointer-events-none absolute right-[calc(var(--padding-x)*0.6)]" > <svg viewBox="0 0 12 12" className="size-3" aria-hidden="true" fill="none"> <path d="M3 4.5 6 7.5 9 4.5" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round" /> </svg> </span> </div> );}