Kosmesis
Components

Native Select

A plain, styled native <select>. Purely presentational.

Installation

npx kosmesis add native-select
pnpm dlx kosmesis add native-select
yarn dlx kosmesis add native-select
bunx kosmesis add native-select

Copy and paste the following code into your project.

native-select.tsx
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/css
pnpm add @praxisjs/css
yarn add @praxisjs/css
bun add @praxisjs/css

Copy and paste the following code into your project.

native-select.tsx
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

PropTypeDefault
valuestring— controlled value
defaultValuestring
disabledboolean
requiredboolean
namestring
onChange(value: string, event: Event) => void

On this page