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

solid-baseui

v0.1.0-alpha.4

Published

WIP: An unofficial port of Base UI for SolidJS

Readme

solid-baseui

WIP: An unofficial port of Base UI for SolidJS

A native Solid 2 port of Base UI. It preserves Base UI's observable behavior and accessibility contracts while replacing React-specific architecture with Solid-native reactivity, rendering, refs, and lifecycle APIs.

This is an unofficial community port. It is not affiliated with, endorsed by, or maintained by MUI or the Base UI team, nor by the SolidJS core team.

Install

Install the current release:

bun add solid-baseui

Peer dependencies:

solid-js     ^2.0.0-rc.6
@solidjs/web ^2.0.0-rc.6

Solid 2 is itself a release candidate, which is part of why this package is alpha. Upgrade both runtimes together and use a compatible Solid 2 compiler. RC.6 includes the portal event-delegation fix required by this port; no local dependency patch is needed. This workspace uses @solidjs/[email protected] with the RC.6 compiler.

Usage

import { For } from "solid-js";
import { Toast, useToastManager } from "solid-baseui/toast";

function ToastList() {
  const manager = useToastManager();
  return (
    <For each={manager.toasts()} keyed={(toast) => toast.id}>
      {(toast) => (
        <Toast.Root toast={toast()}>
          <Toast.Content>
            <Toast.Title />
            <Toast.Description />
          </Toast.Content>
          <Toast.Close>Dismiss</Toast.Close>
        </Toast.Root>
      )}
    </For>
  );
}

function AddButton() {
  const { add } = useToastManager();
  return <button onClick={() => add({ title: "Saved" })}>Save</button>;
}

// `useToastManager` reads provider context, so both live inside the provider.
export function App() {
  return (
    <Toast.Provider>
      <AddButton />
      <Toast.Portal>
        <Toast.Viewport>
          <ToastList />
        </Toast.Viewport>
      </Toast.Portal>
    </Toast.Provider>
  );
}

Every family is available from the root entry point or its own subpath (solid-baseui/dialog, solid-baseui/select, and so on).

Polymorphic parts render their native element by default. To replace it, supply a callback and forward its live DOM props, including ref, to the final element:

import { Button } from "solid-baseui/button";

<Button
  nativeButton={false}
  render={(props, state) => (
    <a {...props} href="/settings" data-disabled={state.disabled ? "" : undefined} />
  )}
>
  Settings
</Button>;

The callback receives live object state, not an accessor. Read state.disabled and supplied props in JSX or reactive computations. Destructuring or eagerly copying them during callback setup loses liveness. Always forward props and ref, including through custom components, so events, accessibility, focus, and registration reach the final DOM node.

Migrating To 0.1.0-alpha.1

Version 0.1.0-alpha.1 replaces as with callback-only render. There is no compatibility alias, and JSX-valued render={<a />} is unsupported. Replace an old <Button as="a" href="/settings" nativeButton={false}> with the callback above. No Dynamic, dynamic(), or withoutComponentBinding adapter is needed: the callback writes native or custom-component JSX directly.

  • Outer attributes remain typed for the default native element. Put href and other replacement-only attributes inside the callback, not on a native-button outer API. Likewise, supply required custom-component props inside the callback, for example render={(props) => <AppLink {...props} to="/settings" />}.
  • Keep semantic flags such as nativeButton={false} where supported when the final element is not a button. Selecting an element does not automatically select the component's keyboard or disabled policy.
  • Render selection happens at mount. Replacing the render prop later does not switch the renderer. To change the root, use conditional JSX inside one stable callback and forward props/ref to every possible final element, for example render={(props) => <>{compact() ? <span {...props} /> : <div {...props} />}</>} on a visual part that supports those roots.
  • Put interaction handlers such as onClick on the outer Base UI component. It composes caller handlers with its internal behavior. Use render for the element, styling, and prop forwarding, not to override supplied event handlers. Custom components used inside render should also forward those handlers to the final DOM node.
  • A spread does not compose an overridden ref or class. Preserve supplied values with Solid ref/class arrays when adding your own.
import { Button } from "solid-baseui/button";

<Button
  onClick={() => console.info("Save activated")}
  render={(props) => (
    <button
      {...props}
      class={[props.class, "action"]}
      ref={[props.ref, (element) => { element.dataset.action = "save"; }]}
    />
  )}
>
  Save
</Button>;

Avoid render={(props) => <button {...props} onClick={handleClick} />}: the explicit handler replaces the supplied handler and can break the component's internal interaction behavior. Moving the spread last can instead discard your handler. Put onClick={handleClick} on the outer component so both behaviors are preserved without manually composing handlers.

Component authors can import useRender from solid-baseui/use-render or the package root. Its signature is useRender(props, stateAccessor, nativeFallbackCallback), returning a local JSX component. For example, `const Render = useRender(props, () => state(), (domProps) =>

See CHANGELOG.md for this alpha's changes.

Status

| Area | Status | | --- | --- | | Current release | 0.1.0-alpha.4, available from solid-baseui | | Components | All 38 component families implemented and exported | | Framework | Native Solid 2, using the RC.6 runtime and compiler | | Verification | Typecheck, lint, unit, SSR, hydration, and Chromium/Firefox/WebKit suites passing | | Current focus | Stabilization, performance, and real-application integrations |

The latest release includes the completed Tooltip, Combobox, Autocomplete, and Drawer verification work. The optional unstable-use-media-query utility remains outside the 38-component scope and is not implemented.

See knowledge/README.md for verification scope and remaining work, and BASE_UI_PORTING_INVENTORY.md for the upstream porting inventory.

Solid API decisions

This is a port, not a transliteration. Where React idioms do not carry over, the Solid-native equivalent wins:

  • Components use class, not className.
  • Polymorphic components use callback-only render with native JSX defaults. React element cloning and JSX-valued render props are not supported.
  • Provider hooks return accessors, because replacing a Solid context value is not reactive.
  • Refs are ordinary props and compose through Solid ref arrays. There is no forwardRef and there are no ref objects.
  • Event callbacks receive native DOM events, carrying Base UI's cancellation methods where applicable.
  • Ordinary props use Solid's merge and omit; classes and refs use native arrays rather than a general-purpose prop merger.
  • Lists keyed by identity use <For each={...} keyed={(item) => item.id}> where Base UI relied on React's key.

Development

Bun is the only supported package manager.

bun install
bun run test:browser:install
bun run typecheck
bun run lint
bun run test
bun run test:package
bun run build

bun run build emits:

  • dist/lib/client — hydratable browser artifacts
  • dist/lib/server — hydratable SSR artifacts
  • dist/lib/types — public declarations
  • dist/client — the static preview application

bun run dev serves the preview app, which has a page per family covering every scenario from that component's Base UI documentation.

Credits

Base UI by MUI, MIT licensed, is the upstream this port follows. Its copyright notice is preserved in LICENSE.

License

MIT