Vue overview
@static-bloom/vue is a Vue 3 component library built on Reka UI, the headless primitives that provide keyboard support, focus management and ARIA. Every component is styled with the Static Bloom Tailwind theme, so it looks like the matching sb-* CSS class and follows the flavor and accent of its scope.
preference auto · resolved midnight · theme dark
This is SbFlavorSelect, hydrated as an Astro island. It is a Reka toggle group, not a native <select>, so it also works in OPEN//77 in-game pages.
Conventions
Section titled “Conventions”- Every export is prefixed
Sb, and compound components mirror Reka’s anatomy:SbSelect,SbSelectTrigger,SbSelectContent,SbSelectItem. - Props and events are forwarded to the Reka part, so
v-model,as-childand the Reka options work as documented by Reka. - Many components add
intent,sizeorvariantprops with the same names as the CSS classes. - Every component accepts
class, merged withcn()so your utilities replace the component’s own. - Popups (select lists, menus, popovers, tooltips, dialogs) render in the page through Reka portals. No browser-drawn popup is used.
Install
Section titled “Install”-
Install the components, the Tailwind theme they are styled with, and Tailwind.
Terminal window pnpm add @static-bloom/vue @static-bloom/tailwind vuepnpm add -D tailwindcss @tailwindcss/vite @vitejs/plugin-vueReka UI, tailwind-variants, tailwind-merge,
@lucide/vueand@vueuse/coreare dependencies of the package; Vue 3.5 or later is a peer dependency. Add@lucide/vueto your own dependencies too if your code imports icons. -
Register the Vue and Tailwind plugins.
vite.config.ts import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import tailwindcss from '@tailwindcss/vite'export default defineConfig({ plugins: [vue(), tailwindcss()] }) -
Import Tailwind, the theme, and the component sources in your stylesheet.
src/style.css @import 'tailwindcss';@import '@static-bloom/tailwind';@import '@static-bloom/vue/tailwind.css';The last line is an
@sourcefor the package’sdistfolder, so Tailwind generates every class the components use. -
Wrap the app in
SbProviderand set a flavor on<html>.src/App.vue <script setup lang="ts">import { SbFlavorSelect, SbProvider } from '@static-bloom/vue'</script><template><SbProvider><SbFlavorSelect show-labels /></SbProvider></template>index.html <html lang="en" data-flavor="midnight" data-theme="dark"></html>
SbProvider
Section titled “SbProvider”SbProvider wraps Reka’s ConfigProvider, TooltipProvider and ToastProvider. Put one at the root of every Vue app, and one in every Astro island, since each island is its own app.
| Prop | Default | Effect |
|---|---|---|
flavor |
none | Scopes a flavor to the subtree: a wrapper with data-flavor, data-theme and color-scheme |
accent |
none | Scopes an accent to the subtree with data-accent |
dir |
'ltr' |
Reading direction for every Reka primitive |
locale |
'en' |
Locale for every Reka primitive, dates included |
teleportTo |
body |
Where portalled content (menus, dialogs, toasts) is mounted |
tooltipDelay |
300 |
Tooltip open delay in ms |
tooltipSkipDelay |
200 |
Window in ms to open the next tooltip without delay |
toastDuration |
5000 |
How long a toast stays visible, in ms |
toastSwipeDirection |
'right' |
Swipe direction that dismisses a toast |
toastLabel |
'Notification' |
Screen-reader label of the toast region |
toastLimit |
none | Maximum number of toasts shown at once |
tooltip |
none | Other Reka TooltipProvider props, passed as-is |
It also hands Vue’s useId to Reka, so generated ids match between the server render and hydration.
Plugin or named imports
Section titled “Plugin or named imports”Import components where you use them. The package ships one ES module per component and marks only its CSS as a side effect, so a bundler keeps just what you import:
import { SbSelect, SbSelectContent, SbSelectItem, SbSelectTrigger, SbSelectValue,} from '@static-bloom/vue'StaticBloomPlugin registers every Sb* component globally instead. It suits prototypes; it also pulls every component into the bundle.
import { createApp } from 'vue'import { StaticBloomPlugin } from '@static-bloom/vue'import App from './App.vue'import './style.css'
createApp(App).use(StaticBloomPlugin).mount('#app')Flavors in Vue
Section titled “Flavors in Vue”useFlavor() reads and sets the flavor, and SbFlavorSelect is its picker. They share the static-bloom:flavor storage key and the page runtime with every other package; Flavors & theming covers the composable and its options.
SbFlavorSelect prop |
Default | Effect |
|---|---|---|
show-labels |
false |
Shows the flavor names next to the icons |
size |
'md' |
'sm' or 'md' |
label |
'Flavor' |
Accessible name of the group |
disabled |
false |
Disables every option |
The package also exports cn and tv, configured for the theme: see Class merging.
Server rendering and Astro islands
Section titled “Server rendering and Astro islands”The components render on the server. useFlavor touches neither window nor document until a component mounts, and ids come from Vue’s useId. In Astro, each client:* component is a separate Vue app: wrap its content in SbProvider, and use client:visible unless the component is interactive above the fold. When the page has a flavor runtime (window.staticBloom, installed by the Astro integration or the Starlight plugin), useFlavor delegates to it, which is how the island above follows the header. Vue islands has a complete example.
In-game pages
Section titled “In-game pages”- Start in Blackout:
<html data-flavor="blackout" data-theme="dark">, or<SbProvider flavor="blackout">for one subtree. - Use the Vue selection, date and color components instead of native
<select>, date, time and color inputs; their popups are drawn in the page. - Keep
<html>and<body>transparent so the game shows through, and put backgrounds on panels. - Without a page runtime,
useFlavorapplies the flavor itself; passtargetto scope it to one element. - Call
window.Open77?.ready()after mounting, so the client sends the first state.
In-game UIs lists every platform rule, and Resource template packages a Vite app as a resource.
Component families
Section titled “Component families”| Family | Components |
|---|---|
| Foundations | SbProvider, SbFlavorSelect, useFlavor, StaticBloomPlugin, cn, tv |
| Actions & HUD | SbButton, SbButtonGroup, SbToggle, SbToggleGroup, SbToolbar, SbBadge, SbKbd, SbKeyHint, SbCard, SbSeparator, SbAvatar, SbAspectRatio, SbSkeleton, SbSpinner, SbAlert, SbLink, SbProgress, SbRating, SbTable, SbHudPanel, SbStatBar, SbNeonText |
| Forms | SbLabel, SbInput, SbInputGroup, SbTextarea, SbField, SbForm, SbCheckbox, SbCheckboxGroup, SbRadioGroup, SbSwitch, SbSlider, SbNumberField, SbPinInput, SbTagsInput, SbEditable, SbTagGroup |
| Selection | SbSelect, SbCombobox, SbAutocomplete, SbListbox |
| Date and time | SbCalendar, SbRangeCalendar, SbDateField, SbDateRangeField, SbTimeField, SbTimeRangeField, SbDatePicker, SbDateRangePicker, SbMonthPicker, SbMonthRangePicker, SbYearPicker, SbYearRangePicker |
| Color | SbColorArea, SbColorField, SbColorSlider, SbColorSwatch, SbColorSwatchPicker, SbColorPicker |
| Overlays | SbDialog, SbAlertDialog, SbSheet, SbDrawer, SbPopover, SbTooltip, SbHoverCard, SbDropdownMenu, SbContextMenu, SbMenubar, SbToast, SbToaster |
| Navigation | SbTabs, SbAccordion, SbCollapsible, SbNavigationMenu, SbPagination, SbBreadcrumb, SbStepper, SbTree, SbScrollArea, SbSplitterGroup |
Each family also exports the compound parts of its components, such as SbTabsList, SbTabsTrigger and SbTabsContent.