Production-ready component examples you can copy and customize.
Login Form
Complete login form with validation and remember me
import { useState } from 'react';
import {
NHCard,
NHCardBody,
NHInput,
NHButton,
NHCheckbox,
NHLink,
VStack,
HStack,
Text
} from '@noiseheroes/ui';
export function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [rememberMe, setRememberMe] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
console.log({ email, password, rememberMe });
setIsLoading(false);
};
return (
<NHCard className="max-w-md mx-auto">
<NHCardBody>
<form onSubmit={handleSubmit}>
<VStack spacing={6}>
<Text className="text-2xl font-bold text-center">
Welcome Back
</Text>
<NHInput
type="email"
label="Email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<NHInput
type="password"
label="Password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<HStack justify="between" className="w-full">
<NHCheckbox
isSelected={rememberMe}
onValueChange={setRememberMe}
>
Remember me
</NHCheckbox>
<NHLink href="#" size="sm">
Forgot password?
</NHLink>
</HStack>
<NHButton
type="submit"
color="primary"
className="w-full"
isLoading={isLoading}
>
Sign In
</NHButton>
<Text className="text-center text-sm">
Don't have an account?{' '}
<NHLink href="#" size="sm">
Sign up
</NHLink>
</Text>
</VStack>
</form>
</NHCardBody>
</NHCard>
);
}Dashboard Stats
Stats cards for dashboards with icons and trends
import {
NHCard,
NHCardBody,
HStack,
VStack,
Text,
Box,
ArrowUpIcon,
ArrowDownIcon,
UsersIcon,
CurrencyDollarIcon,
ShoppingCartIcon,
ChartBarIcon
} from '@noiseheroes/ui';
interface StatCardProps {
title: string;
value: string;
change: number;
icon: React.ReactNode;
}
function StatCard({ title, value, change, icon }: StatCardProps) {
const isPositive = change >= 0;
return (
<NHCard>
<NHCardBody>
<HStack justify="between">
<VStack spacing={2} align="start">
<Text className="text-sm text-gray-600 dark:text-gray-400">
{title}
</Text>
<Text className="text-2xl font-bold">
{value}
</Text>
<HStack spacing={1}>
{isPositive ? (
<ArrowUpIcon className="h-4 w-4 text-green-500" />
) : (
<ArrowDownIcon className="h-4 w-4 text-red-500" />
)}
<Text
className={`text-sm ${
isPositive ? 'text-green-500' : 'text-red-500'
}`}
>
{Math.abs(change)}%
</Text>
</HStack>
</VStack>
<Box className="p-3 bg-orange-100 dark:bg-orange-900/20 rounded-lg">
{icon}
</Box>
</HStack>
</NHCardBody>
</NHCard>
);
}
export function DashboardStats() {
return (
<Box className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
<StatCard
title="Total Users"
value="12,345"
change={12.5}
icon={<UsersIcon className="h-6 w-6 text-orange-500" />}
/>
<StatCard
title="Revenue"
value="$45,678"
change={-2.4}
icon={<CurrencyDollarIcon className="h-6 w-6 text-orange-500" />}
/>
<StatCard
title="Orders"
value="1,234"
change={8.7}
icon={<ShoppingCartIcon className="h-6 w-6 text-orange-500" />}
/>
<StatCard
title="Conversion"
value="3.45%"
change={0.9}
icon={<ChartBarIcon className="h-6 w-6 text-orange-500" />}
/>
</Box>
);
}Pricing Cards
Responsive pricing cards with features list
import {
NHCard,
NHCardBody,
NHCardHeader,
NHButton,
NHChip,
VStack,
HStack,
Text,
Box,
CheckIcon
} from '@noiseheroes/ui';
interface PricingCardProps {
name: string;
price: string;
description: string;
features: string[];
isPopular?: boolean;
}
function PricingCard({
name,
price,
description,
features,
isPopular
}: PricingCardProps) {
return (
<NHCard className={`relative ${isPopular ? 'border-2 border-orange-500' : ''}`}>
{isPopular && (
<NHChip
color="primary"
size="sm"
className="absolute -top-3 left-1/2 -translate-x-1/2"
>
Most Popular
</NHChip>
)}
<NHCardHeader>
<VStack spacing={2}>
<Text className="text-xl font-semibold">{name}</Text>
<Text className="text-3xl font-bold">
{price}
<span className="text-lg font-normal text-gray-600 dark:text-gray-400">
/month
</span>
</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
{description}
</Text>
</VStack>
</NHCardHeader>
<NHCardBody>
<VStack spacing={4}>
<VStack spacing={2} align="start" className="w-full">
{features.map((feature, index) => (
<HStack key={index} spacing={2}>
<CheckIcon className="h-5 w-5 text-green-500 flex-shrink-0" />
<Text className="text-sm">{feature}</Text>
</HStack>
))}
</VStack>
<NHButton
color={isPopular ? "primary" : "default"}
variant={isPopular ? "solid" : "bordered"}
className="w-full"
>
Get Started
</NHButton>
</VStack>
</NHCardBody>
</NHCard>
);
}
export function PricingSection() {
const plans = [
{
name: "Starter",
price: "$9",
description: "Perfect for side projects",
features: [
"Up to 3 projects",
"1,000 API requests/month",
"Basic support",
"Community access"
]
},
{
name: "Pro",
price: "$29",
description: "For growing businesses",
features: [
"Unlimited projects",
"50,000 API requests/month",
"Priority support",
"Advanced analytics",
"Custom domains"
],
isPopular: true
},
{
name: "Enterprise",
price: "$99",
description: "For large teams",
features: [
"Everything in Pro",
"Unlimited API requests",
"24/7 phone support",
"SLA guarantee",
"Custom integrations",
"Dedicated account manager"
]
}
];
return (
<Box className="grid md:grid-cols-3 gap-6 py-8">
{plans.map((plan) => (
<PricingCard key={plan.name} {...plan} />
))}
</Box>
);
}Notification List
Notification inbox with actions and status indicators
import { useState } from 'react';
import {
NHCard,
NHCardBody,
NHButton,
NHChip,
NHAvatar,
VStack,
HStack,
Text,
Box,
BellIcon,
CheckIcon,
XMarkIcon
} from '@noiseheroes/ui';
interface Notification {
id: string;
title: string;
message: string;
time: string;
type: 'info' | 'success' | 'warning' | 'error';
read: boolean;
avatar?: string;
}
export function NotificationList() {
const [notifications, setNotifications] = useState<Notification[]>([
{
id: '1',
title: 'New message from Sarah',
message: 'Hey, are you available for a quick call?',
time: '5 min ago',
type: 'info',
read: false,
avatar: 'https://i.pravatar.cc/150?img=1'
},
{
id: '2',
title: 'Deployment successful',
message: 'Your application has been deployed to production.',
time: '1 hour ago',
type: 'success',
read: false
},
{
id: '3',
title: 'Payment failed',
message: 'Your payment method was declined. Please update your billing info.',
time: '2 hours ago',
type: 'error',
read: true
}
]);
const markAsRead = (id: string) => {
setNotifications(prev =>
prev.map(n => n.id === id ? { ...n, read: true } : n)
);
};
const deleteNotification = (id: string) => {
setNotifications(prev => prev.filter(n => n.id !== id));
};
const typeColors = {
info: 'default',
success: 'success',
warning: 'warning',
error: 'danger'
};
return (
<NHCard className="max-w-2xl">
<NHCardBody>
<VStack spacing={4}>
<HStack justify="between" className="w-full">
<HStack>
<BellIcon className="h-6 w-6" />
<Text className="text-xl font-semibold">Notifications</Text>
</HStack>
<NHChip size="sm" variant="flat">
{notifications.filter(n => !n.read).length} unread
</NHChip>
</HStack>
<VStack spacing={2} className="w-full">
{notifications.map(notification => (
<Box
key={notification.id}
className={`p-4 rounded-lg border transition-colors ${
notification.read
? 'bg-gray-50 dark:bg-gray-900 border-gray-200 dark:border-gray-800'
: 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700'
}`}
>
<HStack justify="between" align="start">
<HStack align="start" spacing={3}>
{notification.avatar ? (
<NHAvatar src={notification.avatar} size="sm" />
) : (
<Box className="w-10 h-10 rounded-full bg-gray-200 dark:bg-gray-700" />
)}
<VStack align="start" spacing={1}>
<HStack spacing={2}>
<Text className="font-semibold">
{notification.title}
</Text>
<NHChip
size="sm"
color={typeColors[notification.type] as any}
variant="flat"
>
{notification.type}
</NHChip>
</HStack>
<Text className="text-sm text-gray-600 dark:text-gray-400">
{notification.message}
</Text>
<Text className="text-xs text-gray-500">
{notification.time}
</Text>
</VStack>
</HStack>
<HStack>
{!notification.read && (
<NHButton
size="sm"
variant="flat"
isIconOnly
onClick={() => markAsRead(notification.id)}
>
<CheckIcon className="h-4 w-4" />
</NHButton>
)}
<NHButton
size="sm"
variant="flat"
isIconOnly
onClick={() => deleteNotification(notification.id)}
>
<XMarkIcon className="h-4 w-4" />
</NHButton>
</HStack>
</HStack>
</Box>
))}
</VStack>
<NHButton variant="flat" className="w-full">
View all notifications
</NHButton>
</VStack>
</NHCardBody>
</NHCard>
);
}Settings Form
User settings form with sections and toggles
import { useState } from 'react';
import {
NHCard,
NHCardBody,
NHCardHeader,
NHInput,
NHTextarea,
NHSwitch,
NHButton,
NHDivider,
VStack,
HStack,
Text,
Box
} from '@noiseheroes/ui';
export function SettingsForm() {
const [profile, setProfile] = useState({
name: 'John Doe',
email: 'john.doe@example.com',
bio: 'Software developer passionate about building great products.',
website: 'https://johndoe.com'
});
const [notifications, setNotifications] = useState({
email: true,
push: false,
sms: false,
marketing: true
});
const [privacy, setPrivacy] = useState({
profilePublic: true,
showEmail: false,
allowMessages: true
});
const handleSave = () => {
console.log('Saving settings:', { profile, notifications, privacy });
};
return (
<VStack spacing={6} className="max-w-2xl">
{/* Profile Settings */}
<NHCard>
<NHCardHeader>
<Text className="text-xl font-semibold">Profile Settings</Text>
</NHCardHeader>
<NHCardBody>
<VStack spacing={4}>
<NHInput
label="Name"
value={profile.name}
onChange={(e) => setProfile({ ...profile, name: e.target.value })}
/>
<NHInput
label="Email"
type="email"
value={profile.email}
onChange={(e) => setProfile({ ...profile, email: e.target.value })}
/>
<NHTextarea
label="Bio"
placeholder="Tell us about yourself"
value={profile.bio}
onChange={(e) => setProfile({ ...profile, bio: e.target.value })}
rows={4}
/>
<NHInput
label="Website"
type="url"
value={profile.website}
onChange={(e) => setProfile({ ...profile, website: e.target.value })}
/>
</VStack>
</NHCardBody>
</NHCard>
{/* Notification Settings */}
<NHCard>
<NHCardHeader>
<Text className="text-xl font-semibold">Notifications</Text>
</NHCardHeader>
<NHCardBody>
<VStack spacing={4}>
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Email Notifications</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Receive notifications via email
</Text>
</Box>
<NHSwitch
isSelected={notifications.email}
onValueChange={(checked) =>
setNotifications({ ...notifications, email: checked })
}
/>
</HStack>
<NHDivider />
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Push Notifications</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Receive push notifications on your device
</Text>
</Box>
<NHSwitch
isSelected={notifications.push}
onValueChange={(checked) =>
setNotifications({ ...notifications, push: checked })
}
/>
</HStack>
<NHDivider />
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">SMS Notifications</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Receive notifications via SMS
</Text>
</Box>
<NHSwitch
isSelected={notifications.sms}
onValueChange={(checked) =>
setNotifications({ ...notifications, sms: checked })
}
/>
</HStack>
<NHDivider />
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Marketing Emails</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Receive promotional emails and updates
</Text>
</Box>
<NHSwitch
isSelected={notifications.marketing}
onValueChange={(checked) =>
setNotifications({ ...notifications, marketing: checked })
}
/>
</HStack>
</VStack>
</NHCardBody>
</NHCard>
{/* Privacy Settings */}
<NHCard>
<NHCardHeader>
<Text className="text-xl font-semibold">Privacy</Text>
</NHCardHeader>
<NHCardBody>
<VStack spacing={4}>
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Public Profile</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Make your profile visible to everyone
</Text>
</Box>
<NHSwitch
isSelected={privacy.profilePublic}
onValueChange={(checked) =>
setPrivacy({ ...privacy, profilePublic: checked })
}
/>
</HStack>
<NHDivider />
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Show Email</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Display your email on your public profile
</Text>
</Box>
<NHSwitch
isSelected={privacy.showEmail}
onValueChange={(checked) =>
setPrivacy({ ...privacy, showEmail: checked })
}
/>
</HStack>
<NHDivider />
<HStack justify="between" className="w-full">
<Box>
<Text className="font-medium">Allow Messages</Text>
<Text className="text-sm text-gray-600 dark:text-gray-400">
Let other users send you direct messages
</Text>
</Box>
<NHSwitch
isSelected={privacy.allowMessages}
onValueChange={(checked) =>
setPrivacy({ ...privacy, allowMessages: checked })
}
/>
</HStack>
</VStack>
</NHCardBody>
</NHCard>
{/* Save Button */}
<HStack justify="end" className="w-full">
<NHButton variant="flat">Cancel</NHButton>
<NHButton color="primary" onClick={handleSave}>
Save Changes
</NHButton>
</HStack>
</VStack>
);
}