Components
Native Select
A plain, styled native <select>. Purely presentational.
Installation
npx kosmesis add native-selectpnpm dlx kosmesis add native-selectyarn dlx kosmesis add native-selectbunx kosmesis add native-selectCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export interface NativeSelectProps { value?: string; defaultValue?: string; disabled?: boolean; required?: boolean; name?: string; onChange?: (value: string, event: Event) => void; class?: string; id?: string; children?: Children;}/** * A plain, styled native `<select>` — purely presentational, no Morphos wrap. Prefer `Select` * (which wraps Morphos's custom listbox) for a fully styleable dropdown; reach for this when you * specifically want native OS select behavior (e.g. on mobile, or for very long option lists). */@Component()export class NativeSelect extends StatelessComponent<NativeSelectProps> { render() { const { value, defaultValue, disabled, required, name, onChange, class: cls, id, children } = this.props; return ( <select id={id} name={name} value={value ?? defaultValue} disabled={disabled} required={required} class={cn( "flex h-9 w-full appearance-none rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50", cls, )} onChange={(event: Event) => { onChange?.((event.target as HTMLSelectElement).value, event); }} > {children} </select> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class NativeSelectStyles extends Stylesheet { $root = this.css({ display: "flex", height: "2.25rem", width: "100%", appearance: "none", borderRadius: `calc(${t.radius} - 2px)`, border: `1px solid ${t.input}`, backgroundColor: "transparent", padding: "0.25rem 0.75rem", fontSize: "0.875rem", boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)", outline: "none", transition: "color 120ms ease, box-shadow 120ms ease", }) .disabled({ cursor: "not-allowed", opacity: 0.5 }) .focusVisible({ borderColor: t.ring, boxShadow: `0 0 0 3px color-mix(in oklab, ${t.ring} 50%, transparent)` });}export interface NativeSelectProps { value?: string; defaultValue?: string; disabled?: boolean; required?: boolean; name?: string; onChange?: (value: string, event: Event) => void; class?: string; id?: string; children?: Children;}/** * A plain, styled native `<select>` — purely presentational, no Morphos wrap. Prefer `Select` * (which wraps Morphos's custom listbox) for a fully styleable dropdown; reach for this when you * specifically want native OS select behavior (e.g. on mobile, or for very long option lists). */@Component()export class NativeSelect extends StatelessComponent<NativeSelectProps> { @Styled(NativeSelectStyles) $s!: NativeSelectStyles; render() { const { value, defaultValue, disabled, required, name, onChange, class: cls, id, children } = this.props; return ( <select id={id} name={name} value={value ?? defaultValue} disabled={disabled} required={required} class={cx(this.$s.$root, cls)} onChange={(event: Event) => { onChange?.((event.target as HTMLSelectElement).value, event); }} > {children} </select> ); }}Examples
Usage
import { NativeSelect } from "@/components/ui/native-select";
<NativeSelect defaultValue="apple" onChange={(value) => console.log(value)}>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
</NativeSelect>Prefer Select for a fully custom-styleable dropdown; reach for
NativeSelect specifically when you want native OS picker behavior (better on mobile, or for
very long option lists where a custom listbox would need virtualization).
Props
| Prop | Type | Default |
|---|---|---|
value | string | — controlled value |
defaultValue | string | — |
disabled | boolean | — |
required | boolean | — |
name | string | — |
onChange | (value: string, event: Event) => void | — |