@nimble-space/preact
v0.1.6
Published
Preact UI components for Nimble Space mini apps.
Readme
@nimble-space/preact
Preact UI components for Nimble Space mini apps running inside Flutter InAppWebView.
The package provides the Nimble Space mobile background, safe-area layout, mobile header/status bar, segmented tabs, buttons, cards, form fields, feedback states, toast, centered modal, bottom sheet and Flutter close bridge.
Install
npm install preact lucide-preact @nimble-space/preactImport the package stylesheet once at the app root:
import { render } from 'preact'
import { NimbleProvider, ToastProvider } from '@nimble-space/preact'
import '@nimble-space/preact/styles.css'
import { App } from './App'
render(
<NimbleProvider>
<ToastProvider>
<App />
</ToastProvider>
</NimbleProvider>,
document.getElementById('app')!,
)NimbleProvider detects iOS once and stores its safe-area state on the document root, so the top inset remains correct when a client-side router replaces the current AppScreen. Flutter's --nim-host-safe-area-top value and the browser's env(safe-area-inset-top) take priority. If neither is available, the provider uses a 59px iOS fallback; override it for a custom WebView when needed:
<NimbleProvider iosSafeAreaTop={62}>
<App />
</NimbleProvider>The inset is applied as top padding rather than margin, which keeps the Nimble background painted behind the native iOS status bar. Android and normal desktop browsers are unchanged.
Use a cover-aware viewport in every bundled mini app so iOS exposes the correct safe-area insets and Android keeps the same CSS pixel scale:
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover, interactive-widget=resizes-content"
/>Mini App Shell
Use MiniAppLayout for full-screen mobile layout. It applies 100dvh, safe-area padding, the Nimble Space background and the translucent body sheet. Its header and body geometry mirrors the Flutter shell: a 40px app bar, a 16px body gap, and a 16px top radius.
import {
Button,
MiniAppHeader,
MiniAppLayout,
MobileTabs,
} from '@nimble-space/preact'
const bookingTabs = [
{ value: 'daily', label: 'จองรายวัน' },
{ value: 'weekly', label: 'จองรายสัปดาห์' },
]
export function SeatBooking() {
return (
<MiniAppLayout
header={<MiniAppHeader title="Seat Booking" />}
actions={<Button fullWidth>บันทึก</Button>}
>
<MobileTabs
ariaLabel="ประเภทการจอง"
options={bookingTabs}
value="daily"
/>
</MiniAppLayout>
)
}MiniAppHeader does not add a fake status bar or status-bar spacer by default. This keeps the header aligned when Flutter already renders the native system bar. Use statusBar only for a standalone browser preview:
<MiniAppHeader title="Seat Booking" statusBar />MiniAppLayout renders the bottom action area only when actions is provided. Omit actions on screens that should end at the native Flutter navigation area.
Flutter Back Bridge
FlutterBackButton and the default MiniAppHeader back action call:
window.flutter_inappwebview?.callHandler('closeMiniApp')The call is guarded and does not throw in a normal browser.
Feedback APIs
Modal and its compatible Dialog alias are centered in the actual visible WebView viewport and include enter/exit motion. The motion automatically collapses for users who enable reduced motion. BottomSheet is a separate mobile action sheet, not a dialog variant.
<Modal open={open} onClose={close} title="Centered modal">
Content
</Modal>
<BottomSheet open={open} onClose={close} title="Mobile actions">
Content
</BottomSheet>For toasts, wrap the app in ToastProvider and call useToast():
const { showToast } = useToast()
showToast('success', 'Saved', 'Your change has been saved.')Public Components
- Layout:
AppScreen,MiniAppLayout,DesignSheet,MiniAppHeader,MobileStatusBar,MobileTabs,ScreenHeader,StickyActionBar - Actions:
Button,IconButton,FlutterBackButton - Content:
Card,Box,Stack,Inline,Container,Section,HeroSection,Tag,Avatar,AvatarGroup - Forms:
InputField,TextareaField - Feedback:
Toast,ToastProvider,useToast,LoadingState,EmptyState,ErrorState,Skeleton,ProgressIndicator,Modal,BottomSheet,ConfirmDialog
The package intentionally does not include select, checkbox, radio, switch, OTP, date picker or upload components yet.
