npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@phreshos/react-ui

v0.1.27

Published

React components for coherent PhreshOS Program interfaces.

Downloads

4,530

Readme

@phreshos/react-ui

Environment-neutral React components and the visual language of PhreshOS.

Appearance · React SDK · Source

Role

React UI interprets Core Appearance and Theme contracts as reusable visual primitives. The Desktop and Programs compose those primitives instead of reimplementing material, spacing, color, radius, or interaction behavior.

The package does not depend on a Client or Server runtime and does not own authoritative application state. React owns runtime-neutral state adaptation; applications own composition.

Installation

| Package manager | Command | | --- | --- | | npm | npm install @phreshos/react-ui | | pnpm | pnpm add @phreshos/react-ui | | Bun | bun add @phreshos/react-ui | | Yarn | yarn add @phreshos/react-ui |

Core is a built-in runtime dependency. React and React DOM remain peer dependencies because the application and React UI must share one React runtime.

import { Button, Surface } from "@phreshos/react-ui"

<Surface>
  <Button>Continue</Button>
</Surface>

Without a provider, components use Core's defaultAppearance and reactively follow the browser's complete visual preferences. UIProvider supplies the Appearance, Preferences, and direction explicitly established for a React UI subtree. Each omitted property inherits independently from the nearest provider or follows its own default resolution. A provider with no properties introduces no boundary or behavior. React UI also exports that same canonical defaultAppearance value for callers that need it explicitly. See Appearance for the contract interpreted by the provider and components.

React UI is neutral between left-to-right and right-to-left interfaces. An explicit UIProvider direction creates a boundary that participates in native DOM inheritance without creating a layout box. When direction is omitted, the provider leaves DOM inheritance unchanged. React UI reads the nearest explicit direction—or <html dir> when there is none—only for JavaScript behavior and portals that cannot rely on native inheritance.

import { UIProvider, Select } from "@phreshos/react-ui"

<UIProvider direction="rtl">
  <Select label="Choice" options={[{ value: "one", label: "One" }]} />
</UIProvider>
import { UIProvider, Button, useBrowserPreferences } from "@phreshos/react-ui"

function Example() {
  const browser = useBrowserPreferences()

  return <UIProvider preferences={{ ...browser, theme: "dark" }}>
    <Button>Dark subtree</Button>
  </UIProvider>
}

Button, Input, Textarea, Select, Checkbox, Switch, and Radio use the shared Surface implementation while retaining their native behavior. Color and material are independent inputs. color accepts an Appearance color and resting level such as background:base or primary:soft, or a direct CSS color. Surface defaults to background:base; solid controls default to default:base. Hover and press derive shades of that fill. The resting fill chooses the higher-contrast text from Appearance's background and foreground once; interaction shades keep that choice. size accepts xsmall, small, medium (default), large, or xlarge; spacing and radius follow Appearance. disabled prevents activation and focus; pending prevents activation while retaining focus.

<Button>Cancel</Button>
<Button color="primary:base" onPress={save}>Save</Button>
<Button color="danger:soft" size="small">Delete</Button>

Surface is the material- and shadow-owning element. It renders a div by default, while as selects another React element and preserves that element's native properties and ref type. Surface owns its paint, opacity, frost, refraction, grain, edge, outer shadow, radius, and clipping requirements. radius accepts a size level, full, a number in pixels, or a CSS radius and defaults to medium.

<Surface color="background:soft" radius="large">Derived values</Surface>
<Surface as="button" type="button" color="#345678" radius={18}>Action</Surface>
<Surface as={Grid} columns={3} gap="medium">Grid content</Surface>

as can also select an outside React component. A valid Surface host preserves the style, dir, and children it receives on one host element and forwards its ref to that same element. This lets layout components carry the material without a wrapper. The host retains ownership of its own behavior and layout properties; Surface retains ownership of material, edge, shadow, radius, and required geometry.

MaterialOptions defines opacity, backdrop, grain, grainAmount, distortion, and saturation. Every material-bearing component, including Surface, exposes these values through its material prop. Color remains a separate property. Omission or true uses appearance.material; false removes the material and paints the resolved color as a normal background. Effect options accept a scale level or a direct number; opacity affects Surface paint only, never its content. The material edge is part of the same Surface rather than a second public entity.

Surface-based controls expose the same separate color and material props. ShadowOptions similarly groups x, y, blur, spread, and opacity under the shadow prop. Omission or true follows the active appearance.shadow branch, while false removes the shadow. Each option accepts a scale level or direct number. The shadow is a neutral black outer shadow. Surface-based controls expose the same shadow prop. For text fields and Select, material targets the field or trigger; for Checkbox, Switch, and Radio, it targets the indicator. RadioGroup supplies material defaults to its options, and a Radio can override them. Shadow follows the same targets and inheritance path.

<Button color="primary:base" material={{ opacity: 0.6, backdrop: 0 }}>Save</Button>
<Input label="Name" radius="large" material={{ grain: "small" }} shadow={{ blur: "small" }} />

Panel composes an outer Surface, an optional header, and an inset content Surface. Both materials retain Surface defaults; the content inset follows Appearance spacing. Positioning, modality, and lifecycle belong to the caller.

import { Panel } from "@phreshos/react-ui"

<Panel>
  <Panel.Header><h2>Title</h2></Panel.Header>
  <Panel.Content style={{ padding: 16 }}>Content</Panel.Content>
</Panel>

Native properties and the root ref target the outer Surface. Panel.Header owns the optional leading region, while Panel.Content is the independently configurable inner Surface.

Overlays

Overlay components expose each behavioral role as a named part. Roots own open state, triggers own activation, positioned content owns its Surface, and the semantic content remains explicit.

<DropdownMenu>
  <DropdownMenu.Trigger>Actions</DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <Menu aria-label="Document actions">
      <Menu.Item onAction={open}>Open</Menu.Item>
      <Menu.Item color="danger:base" onAction={remove}>Delete</Menu.Item>
    </Menu>
  </DropdownMenu.Content>
</DropdownMenu>

Popover presents anchored non-modal content. DropdownMenu and ContextMenu open the same Menu contract through different interactions. Dialog blocks interaction behind it and may be dismissable, while AlertDialog requires an explicit decision by default. Tooltip supplies a short description on focus or hover. Portal cleanup, focus restoration, keyboard behavior, nested ownership, and entrance and exit transactions remain component-owned.

Inputs

Every input uses Appearance colors and the same five size levels as Button. color selects the fill independently from material. Input, Textarea, Select, and Button use default:base when it is omitted. Invalid fields use danger instead. Text fields share Surface's glass edge. Interaction shades derive from the base color's lightness, and text or selection marks use whichever Appearance background or foreground has higher contrast against the base fill. That text or mark color stays unchanged across interaction shades. These are component-owned derivations, not additional Appearance settings. Theme names never imply particular colors. No component requires a Client or Server SDK.

Fields distinguish hover, pointer focus, keyboard focus, and invalid state. Shared CSS transitions use appearance.transaction for colors and corner radius. The material fill and opacity values transition on the painted layers, not on the Surface host. Select menus scale from 1.05 to 1 while fading in, and reverse that motion when exiting, using React Aria's animation lifecycle. Preferences with animations disabled make these changes immediate without changing the Appearance value. Blur, distortion, geometry, and Surface host opacity are not transitioned; gradients and structurally removed effects change directly rather than adding extra layers or keeping disabled effects alive.

Motion animates toggle presses, selection marks, switch travel, the Select chevron, and Slider thumb feedback. Preferences with animations disabled remove spatial feedback and make state transitions immediate. Slider values and native input behavior are never delayed by visual animation.

| Component | Value contract | Purpose | | --- | --- | --- | | Input | value, defaultValue, onChange(string) | Single-line text; supports text, email, password, search, URL, and telephone types | | Textarea | value, defaultValue, onChange(string) | Multiline text; four rows by default, vertically resizable | | Checkbox | checked, defaultChecked, onChange(boolean) | Independent selection; indeterminate represents a mixed state | | Switch | checked, defaultChecked, onChange(boolean) | An on/off setting | | RadioGroup / Radio | Group value, defaultValue, onChange(string); Radio value | One exclusive choice; vertical by default, optionally horizontal | | Select | value: string \| null, defaultValue, onChange(string \| null) | One choice from options: { value, label, disabled? }[] | | Slider | value, defaultValue, onChange(number) | One numeric value; minValue, maxValue, step, and onChangeEnd; horizontal by default |

Use label for visible labels, or aria-label / aria-labelledby for an accessible name without visible text. description provides associated help. disabled prevents interaction and removes the control from keyboard focus. name participates in native form submission. Controlled values remain owned by the caller; omit them and use defaults for internal state and form reset.

Text fields, Checkbox, Switch, and RadioGroup also support readOnly: the value cannot change, but the control remains focusable. These fields and Select support required, invalid, errorMessage, and React Aria's native or ARIA validation behavior. A Radio's selection and validation belong to its group. Slider represents a bounded number rather than a required text or choice field, and has no read-only or validation-error mode. Select has no read-only mode; disable it when selection must be unavailable.

Input, Textarea, and Select accept radius. Other inputs retain their intrinsic indicator shapes. className and style address the field's root; default visual properties remain component-owned. Input and Textarea refs target their native text controls; other refs target the root div. Checkbox, Switch, and Radio additionally accept inputRef for their native input.

import { Input, Textarea, Checkbox, Radio, RadioGroup, Switch, Select, Slider } from "@phreshos/react-ui"

<Input label="Name" name="name" required />
<Textarea label="Description" name="description" />
<Checkbox label="Remember this choice" name="remember" />
<Switch label="Notifications" name="notifications" defaultChecked />
<RadioGroup label="Layout" name="layout" defaultValue="grid">
  <Radio label="Grid" value="grid" />
  <Radio label="List" value="list" />
</RadioGroup>
<Select label="Sort" name="sort" options={[
  { value: "name", label: "Name" },
  { value: "date", label: "Date" }
]} />
<Slider label="Volume" name="volume" defaultValue={50} minValue={0} maxValue={100} step={1} />

React Aria owns focus, keyboard, form, and selection behavior. Select's popup uses Surface defaults. Toggle indicators use Motion internally and respect animation preferences. The preview Program demonstrates each input's sizes, colors, state, and interaction without overriding its visual defaults.

Development

bun install --frozen-lockfile
bun run verify

verify checks the contracts, tests the components, builds the package, and validates its published shape.

check performs static checks, build creates distributable output, and test runs Vitest assertions from tests/. Run build before testing built artifacts. verify runs check, build, and test in order. Operational tooling belongs in scripts/; tests and their fixtures belong in tests/. Verification uses the committed dependency graph without local package substitutions.

Related repositories

Contributing

See CONTRIBUTING.md for the repository workflow and SECURITY.md for private vulnerability reporting.

License

Licensed under the MIT License. Copyright © 2026 Zohayr SLILEH.