Appearance

Use the system

Start with a runnable example. Both platforms import the same components.
32 controls, icons and shared sections
Owner-approved @bubbasfw/ui@0.8.4 includes the reviewed responsive marketing sections, campaign marquee and offer badge, retaining the web Button caller-style fix. Version 0.6.0 is deprecated. Vite and Astro use the web entry; Expo and the Next.js universal example keep their NativeWind host setup.

Run the examples

git clone https://github.com/handh-dev/bubbas-ui.git cd bubbas-ui pnpm install pnpm build pnpm dev:web # Or: pnpm dev:expo
Use Node 22.13+ and pnpm 11.15.0. The Next example runs on port 4310. Expo opens its normal development flow. The package must be rebuilt after component source changes.

Vite and Astro

pnpm add @bubbasfw/ui@0.8.4 react@19.2.3 react-dom@19.2.3 react-native-web@0.21.4
import { ThemeProvider, HeroSection } from "@bubbasfw/ui/web"; import "@bubbasfw/ui/web.css"; <ThemeProvider appearance="light"> <HeroSection variant="marketing" title="Your page title" /> </ThemeProvider>
Import the shared CSS once. This browser entry includes the web interop and utility styles; it needs no host NativeWind Babel or Tailwind configuration. Keep declared peers compatible and use one React/React Native Web instance. Apps provide content, cleared assets, links and actions.
Astro and Node SSR hosts render shared content before collecting StyleSheet.getSheet() from the same installed react-native-web instance. Include its returned id and textContent in the document alongside web.css so structural styles exist before hydration. Hydrate the shared header and interactive sections with the same data to enable their menus and galleries.

Expo and the Next.js universal example

React, React Native, NativeWind and Tailwind remain peer dependencies. Web also needs React Native Web and React DOM. Native-only apps can omit React Native Web.
pnpm add @bubbasfw/ui@0.8.4 nativewind@4.2.7 pnpm add -D tailwindcss@3.4.17
Pinned example baseline: React 19.2.3, RN 0.86.3, RNW 0.21.4, NativeWind 4.2.7, Tailwind 3.4.17. NativeWind 5 and Tailwind 4 need a separate migration.
The host app scans the package’s published source and loads both presets.
const path = require('node:path'); const uiRoot = path.dirname(require.resolve('@bubbasfw/ui/package.json')); module.exports = { darkMode: 'class', content: ['./App.{js,jsx,ts,tsx}', './{app,pages,src}/**/*.{js,jsx,ts,tsx}', path.join(uiRoot, 'src/**/*.{ts,tsx}')], presets: [require('nativewind/preset'), require('@bubbasfw/ui/tailwind-preset')], };
Import global CSS from the entry, with @tailwind base, @tailwind components and @tailwind utilities. Web sets important: true in its Tailwind config so utilities override RNW defaults.

Building with Xcode 27

Expo SDK 57 needs the scene-lifecycle opt-in for an iOS 27 build. Install a compatible expo-build-properties plugin and configure ios.enableSceneSupport: true before regenerating a native project. Expo 57.0.23 or newer is required; this example pins 57.0.31.
Browser and Metro checks cover their observed behavior. Device, assistive technology and release acceptance remain separate checks for each consuming app.