Getting Started
Render a button
Buttons are separate exports per variant, not a single component with a variant prop. Pass copy via text:
import { PrimaryButton, SecondaryButton, Toast } from "@appboxo/ui-kit"
export function Example() {
return (
<>
<PrimaryButton
text="Continue"
onClick={() => Toast.info("Saved")}
/>
<SecondaryButton text="Skip" onClick={() => Toast.error("Skipped")} />
</>
)
}Variants: PrimaryButton, SecondaryButton, TertiaryButton, QuaternaryButton.
Compose with Flex + typography
import { Flex, Card, LargeTitle, Body2 } from "@appboxo/ui-kit"
export function Example() {
return (
<Flex vertical gap={16}>
<LargeTitle>Welcome</LargeTitle>
<Card>
<Body2 color="text-4">Tap continue to start.</Body2>
</Card>
</Flex>
)
}Plug in host capabilities
Default haptic and share handlers are no-ops. Swap them in once at startup:
import { setHapticHandler, setShareFileHandler } from "@appboxo/ui-kit"
import { hapticFeedback } from "@telegram-apps/sdk"
setHapticHandler((style) => hapticFeedback.impactOccurred(style))
setShareFileHandler(async (url, name) => myHost.share({ url, name }))Multi-provider composition
When you have several context providers, MultiProvider flattens the nesting:
import { MultiProvider, QueryProvider, UIKitProvider } from "@appboxo/ui-kit"
import { QueryClient } from "@tanstack/react-query"
const queryClient = new QueryClient()
const providers = [
<QueryProvider queryClient={queryClient} />,
<UIKitProvider />,
// <YourAuthProvider />, <YourTrackingProvider />, ...
]
export function App({ children }: { children: React.ReactNode }) {
return <MultiProvider providers={providers}>{children}</MultiProvider>
}Switch theme at runtime
Themes are stylesheets, not React state. Layer them by mounting / unmounting the link tag, or pre-load all of them and toggle a class. See the Storybook brand toolbar for a reference implementation using a single <style> tag.
Build mini-apps with Boxo
Freedom UI Kit is the design system behind partner mini-apps shipping on the Boxo platform.
Learn more about Boxo