A SwiftUI-inspired library for building web interfaces with a fluent API.
- v0.0.5
All wishful thing for now :')
import { VStack, Text, Button, State, mount } from '@notswssr/flowui';
function Counter() {
const count = new State(0);
return VStack(
Text("Counter")
.font(.headline)
.padding("bottom", 20),
Button("+")
.onTap(() => count.value++)
.padding(10),
Text("0")
.bind(count, (value, component) => {
component.text(value.toString());
})
);
}
mount(Counter(), "#app");
A bit more advance counter with new two data binding
function CounterExample() {
const counter = new State(0);
const CountButton = (label: string) => Button(label)
.padding("all", 10)
.foregroundColor(Color.white)
.backgroundColor(Color.blue)
.frame({ width: "max-content" })
.cornerRadius(6)
return HStack(
CountButton("-")
.onTap(() => counter.value--),
Text("Count")
.foregroundColor(Color.red)
.bindTo(counter),
CountButton("+")
.onTap(() => counter.value++),
Divider(),
// You can now transform state into a component e.g text node and also format the value like below
counter
.format(x => `Hello, the count is: ${x}`)
.to(Text("")),
)
.frame({ width: "100%" })
}
- đź”— Fluent API: Chainable, SwiftUI-inspired syntax
- 🧩 Component Composition: Build complex UIs from simple components
- 🔄 State Management: Reactive state with simple bindings
- 🎨 Theming System: Light/dark modes and customizable themes
- ✨ Animations: Transitions and animations for dynamic interfaces
- 📱 Responsive Design: Mobile-first grid and layout components
- 🚀 No Build Step Required: Use directly in the browser
- 🔍 TypeScript Powered: Full type safety and autocompletion
npm install @notswssr/flowui
import { Text, Button, VStack, mount } from '@notswssr/flowui';
function HelloWorld() {
return VStack(
Text("Hello, World!")
.font(Font.headline())
.foregroundColor(Color.blue),
Button("Click Me")
.onTap(() => alert("Button clicked!"))
.padding(10)
)
.padding(20)
.backgroundColor(Color.gray.opacity(0.1))
.cornerRadius(10);
}
mount(HelloWorld(), "#app");
import { Text, Button, VStack, State, mount } from '@notswssr/flowui';
function Counter() {
// Create state
const count = new State(0);
// Build UI
return VStack(
Text("Counter")
.font(Font.headline())
.padding("bottom", 20),
Button("Increment")
.onTap(() => count.value++)
.padding(10),
Text("0")
.bind(count, (value, component) => {
component.text(value.toString());
})
);
}
mount(Counter(), "#app");
- VStack: Vertical stack layout
- HStack: Horizontal stack layout
- ZStack: Depth stack for overlapping elements
- Spacer: Flexible space
- Grid: Responsive grid layout
- ScrollView: Scrollable container
VStack(
Text("Header"),
HStack(
Text("Left"),
Spacer(),
Text("Right")
),
Grid({ xs: 1, md: 2 }, 16, [
Card({ title: "Card 1", content: Text("Content 1") }),
Card({ title: "Card 2", content: Text("Content 2") })
])
)
- Text: For displaying text
- Button: Interactive button
- TextField: Text input field
- Toggle: Boolean toggle switch
- Image: Image display with loading state
VStack(
Text("Login Form")
.font(Font.headline()),
TextField("Username")
.padding("bottom", 10),
TextField("Password")
.padding("bottom", 20),
Toggle(rememberMe)
.padding("bottom", 20),
Button("Sign In")
.padding(10)
.backgroundColor(Color.blue)
.cornerRadius(8)
)
- Card: Container with header, content, and footer
- List: Efficient list for rendering collections
- Alert: Contextual alerts with various types
- Modal: Modal dialog windows
- TabView: Tabbed interface
- Divider: Horizontal rule separator
- Form: Form container with submission handling
Card({
title: "User Profile",
subtitle: "Personal information",
content: VStack(
Image("profile.jpg", { width: 100, height: 100 })
.cornerRadius(50),
Text("John Doe")
.font(Font.headline()),
Text("Software Developer")
.foregroundColor(Color.gray)
),
footer: Button("Edit Profile")
})
Apply styles using chainable modifiers:
Text("Hello World")
.font(Font.headline())
.foregroundColor(Color.blue)
.padding(20)
.backgroundColor(Color.gray.opacity(0.1))
.cornerRadius(10)
.border(Color.blue, 2)
.frame({ width: 200, height: 100 })
Common modifiers:
- padding(): Add space around content
- backgroundColor(): Set background color
- foregroundColor(): Set text color
- font(): Set font style and size
- cornerRadius(): Round corners
- border(): Add border
- frame(): Set dimensions
- style(): Apply custom CSS
Add animations to any component:
Button("Animated Button")
.onTap(() => performAction())
.animation(Animation.spring({ stiffness: 100, damping: 10 }))
Add transitions for enter/exit animations:
Text("Fade In Text")
.transition(Transition.opacity())
import { useTheme, VStack, Text, Button } from '@notswssr/flowui';
function ThemeDemo() {
const { theme, toggleDarkMode } = useTheme();
return VStack(
Text(`Current Theme: ${theme.name}`)
.foregroundColor(theme.colors.primary),
Button(theme.isDark ? "Switch to Light" : "Switch to Dark")
.onTap(() => toggleDarkMode())
);
}
import { createTheme, Color, applyThemeToDocument } from '@notswssr/flowui';
const customTheme = createTheme({
name: 'Custom Theme',
colors: {
primary: new Color('#6200EE'),
secondary: new Color('#03DAC6'),
background: new Color('#FAFAFA')
}
});
// Apply the custom theme
applyThemeToDocument(customTheme);
Create your own components by composing existing ones:
```## Coming soon``
- Clone the repository
- Install dependencies:
pnpm install
- Start development server:
pnpm dev:all
This will:
- Start the TypeScript compiler in watch mode
- Launch a development server at http://localhost:5173
pnpm dev
- Start the development server onlypnpm watch
- Start TypeScript in watch mode onlypnpm dev:all
- Start both simultaneouslypnpm build
- Build the librarypnpm test
- Run tests
- Add your test components to
dev/app.ts
- Create containers in
dev/index.html
- Mount your components to test them
- Changes to source files will automatically reload the page