Examples
Real-world usage patterns and code examples for Bao UI components.
Interactive Demo
Try the interactive demo to see all components in action.
Common Patterns
Confirmation Dialog
import { useState } from 'react'
import {
Button,
DialogRoot,
DialogBackdrop,
DialogPopup,
DialogTitle,
DialogClose,
} from '@bao-ui/react'
function DeleteConfirmation() {
const [open, setOpen] = useState(false)
const handleDelete = () => {
// Perform delete action
console.log('Item deleted')
setOpen(false)
}
return (
<DialogRoot open={open} onOpenChange={setOpen}>
<Button variant="destructive" onClick={() => setOpen(true)}>
Delete Item
</Button>
<DialogBackdrop />
<DialogPopup>
<DialogTitle>Confirm Deletion</DialogTitle>
<p>
Are you sure you want to delete this item? This action cannot be
undone.
</p>
<div style={{ display: 'flex', gap: '0.5rem', marginTop: '1rem' }}>
<DialogClose>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button variant="destructive" onClick={handleDelete}>
Delete
</Button>
</div>
</DialogPopup>
</DialogRoot>
)
}Tooltip with Rich Content
import {
Button,
TooltipRoot,
TooltipTrigger,
TooltipPopup,
} from '@bao-ui/react'
function UserProfile() {
return (
<TooltipRoot>
<TooltipTrigger>
<Button variant="ghost">@username</Button>
</TooltipTrigger>
<TooltipPopup>
<div style={{ padding: '0.5rem' }}>
<div style={{ fontWeight: 'bold' }}>John Doe</div>
<div style={{ color: '#666', fontSize: '0.875rem' }}>
Software Engineer
</div>
<div style={{ marginTop: '0.25rem', fontSize: '0.75rem' }}>
Joined March 2024
</div>
</div>
</TooltipPopup>
</TooltipRoot>
)
}Button Loading States
import { useState } from 'react'
import { Button } from '@bao-ui/react'
function AsyncAction() {
const [loading, setLoading] = useState(false)
const handleSubmit = async () => {
setLoading(true)
try {
await new Promise(resolve => setTimeout(resolve, 2000))
console.log('Action completed')
} finally {
setLoading(false)
}
}
return (
<Button
onClick={handleSubmit}
disabled={loading}
style={{ minWidth: '120px' }}
>
{loading ? 'Loading...' : 'Submit'}
</Button>
)
}Form with Validation
import { useState } from 'react'
import {
Button,
DialogRoot,
DialogPopup,
DialogTitle,
DialogClose,
} from '@bao-ui/react'
function ContactForm() {
const [formData, setFormData] = useState({ name: '', email: '' })
const [errors, setErrors] = useState({})
const [showSuccess, setShowSuccess] = useState(false)
const validate = () => {
const newErrors = {}
if (!formData.name) newErrors.name = 'Name is required'
if (!formData.email) newErrors.email = 'Email is required'
if (formData.email && !formData.email.includes('@')) {
newErrors.email = 'Invalid email'
}
setErrors(newErrors)
return Object.keys(newErrors).length === 0
}
const handleSubmit = e => {
e.preventDefault()
if (validate()) {
setShowSuccess(true)
setFormData({ name: '', email: '' })
}
}
return (
<>
<form onSubmit={handleSubmit} style={{ maxWidth: '400px' }}>
<div style={{ marginBottom: '1rem' }}>
<label>
Name
<input
type="text"
value={formData.name}
onChange={e => setFormData({ ...formData, name: e.target.value })}
style={{
width: '100%',
padding: '0.5rem',
marginTop: '0.25rem',
border: errors.name ? '1px solid red' : '1px solid #ccc',
borderRadius: '0.25rem',
}}
/>
{errors.name && (
<div style={{ color: 'red', fontSize: '0.875rem' }}>
{errors.name}
</div>
)}
</label>
</div>
<div style={{ marginBottom: '1rem' }}>
<label>
Email
<input
type="email"
value={formData.email}
onChange={e =>
setFormData({ ...formData, email: e.target.value })
}
style={{
width: '100%',
padding: '0.5rem',
marginTop: '0.25rem',
border: errors.email ? '1px solid red' : '1px solid #ccc',
borderRadius: '0.25rem',
}}
/>
{errors.email && (
<div style={{ color: 'red', fontSize: '0.875rem' }}>
{errors.email}
</div>
)}
</label>
</div>
<Button type="submit">Submit</Button>
</form>
<DialogRoot open={showSuccess} onOpenChange={setShowSuccess}>
<DialogPopup>
<DialogTitle>Success!</DialogTitle>
<p>Your form has been submitted successfully.</p>
<DialogClose>
<Button>Close</Button>
</DialogClose>
</DialogPopup>
</DialogRoot>
</>
)
}Component Composition
import {
Button,
TooltipRoot,
TooltipTrigger,
TooltipPopup,
DialogRoot,
DialogTrigger,
DialogPopup,
DialogTitle,
} from '@bao-ui/react'
function ActionButton({ action, tooltip, confirmMessage, children }) {
return (
<DialogRoot>
<TooltipRoot>
<TooltipTrigger>
<DialogTrigger>
<Button variant="outline">{children}</Button>
</DialogTrigger>
</TooltipTrigger>
<TooltipPopup content={tooltip} />
</TooltipRoot>
<DialogPopup>
<DialogTitle>Confirm Action</DialogTitle>
<p>{confirmMessage}</p>
<div style={{ display: 'flex', gap: '0.5rem', marginTop: '1rem' }}>
<Button variant="outline">Cancel</Button>
<Button onClick={action}>Confirm</Button>
</div>
</DialogPopup>
</DialogRoot>
)
}
// Usage
;<ActionButton
action={() => console.log('Archive action')}
tooltip="Archive this item"
confirmMessage="Are you sure you want to archive this item?"
>
Archive
</ActionButton>Integration Examples
Next.js App Router
// app/layout.tsx
import '@bao-ui/react/styles.css'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
// app/page.tsx
import { Button } from '@bao-ui/react'
export default function HomePage() {
return (
<main>
<h1>My App</h1>
<Button>Get Started</Button>
</main>
)
}React + Vite
// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import '@bao-ui/react/styles.css'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
// App.tsx
import { Button } from '@bao-ui/react'
function App() {
return (
<div>
<h1>Vite + React + Bao UI</h1>
<Button>Click me</Button>
</div>
)
}Styling Examples
Custom Button Styles
// With Tailwind classes
<Button className="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600">
Gradient Button
</Button>
// With inline styles
<Button style={{
background: 'linear-gradient(45deg, #fe6b8b 30%, #ff8e53 90%)',
borderRadius: '20px',
color: 'white'
}}>
Custom Style
</Button>