nutriguard-ui
Version:
NutriGuard Design System - Black/White/Red Minimalism Component Library based on Google Stitch architecture
496 lines (383 loc) • 9.35 kB
Markdown
<div align="center">
<h3>NutriGuard Design System</h3>
<p>Black/White/Red Minimalism | Google Stitch Architecture</p>
<p>
<img src="https://img.shields.io/npm/v/nutriguard-ui" alt="npm version" />
<img src="https://img.shields.io/badge/React-18+-61DAFB?style=flat&logo=react" alt="React" />
<img src="https://img.shields.io/badge/TypeScript-5+-3178C6?style=flat&logo=typescript" alt="TypeScript" />
<img src="https://img.shields.io/badge/Framer_Motion-11+-FF0055?style=flat&logo=framer" alt="Framer Motion" />
</p>
</div>
---
NutriGuard is a design system that combines:
- **Google Stitch (Material You 3)** dynamic architecture
- **Black/White/Red** strict minimalism
- **Motion as information flow**, not decoration
### Core Principles
1. **Strict Color Palette**: Only Black (#000), White (#FFF), Red (#DC2626), and limited Gray scale
2. **4px Grid System**: All spacing must be multiples of 4px
3. **Hard Shadows Only**: No soft blur shadows
4. **Minimal Border Radius**: 0px or 8px maximum
5. **No Emoji Policy**: SVG icons only (Lucide React)
6. **Bold Borders**: 2px standard, no 1px lines
7. **Framer Motion**: All animations use spring physics
---
## 📦 Installation
```bash
npm install nutriguard-ui framer-motion lucide-react
```
### Peer Dependencies
```json
{
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
```
Add to your `tailwind.config.js`:
```javascript
module.exports = {
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/nutriguard-ui/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
black: '#000000',
white: '#FFFFFF',
red: '#DC2626',
},
boxShadow: {
'hard': '4px 4px 0 0 #000',
'hard-lg': '8px 8px 0 0 #000',
},
},
},
}
```
---
```tsx
import { Button, Card, Modal, ToastProvider, useToast } from 'nutriguard-ui';
function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<ToastProvider>
<Card padding="md" hoverable>
<h1>Welcome to NutriGuard</h1>
<Button
variant="primary"
onClick={() => setIsModalOpen(true)}
>
Open Modal
</Button>
</Card>
<Modal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="Example Modal"
>
<p>This is a modal with backdrop blur and hard shadow.</p>
</Modal>
</ToastProvider>
);
}
```
```tsx
import { useToast } from 'nutriguard-ui';
function MyComponent() {
const { success, error, warning, info } = useToast();
return (
<Button onClick={() => success('Operation completed!')}>
Show Success
</Button>
);
}
```
---
Interactive button with motion and multiple variants.
```tsx
<Button variant="primary" size="md" loading={false}>
Click Me
</Button>
```
**Props:**
- `variant`: `'default' | 'primary' | 'red' | 'outline' | 'ghost'`
- `size`: `'sm' | 'md' | 'lg'`
- `loading`: boolean
- `iconLeft`, `iconRight`: React.ReactNode
Container with border and hover shadow effect.
```tsx
<Card hoverable largeShadow padding="md">
<CardHeader>
<CardTitle>Card Title</CardTitle>
</CardHeader>
<CardContent>
Content goes here
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>
```
Full-screen overlay with centered content.
```tsx
<Modal
isOpen={isOpen}
onClose={onClose}
title="Modal Title"
size="md"
closeOnBackdrop={true}
>
<p>Modal content</p>
<ModalFooter>
<Button onClick={onClose}>Close</Button>
</ModalFooter>
</Modal>
```
Auto-dismiss notification system.
```tsx
// Wrap your app with ToastProvider
<ToastProvider maxToasts={5}>
<App />
</ToastProvider>
// Use in components
const { success, error, warning, info } = useToast();
success('Success message', 'Optional Title', 5000);
```
Slide-in panel from screen edges.
```tsx
<Drawer
isOpen={isOpen}
onClose={onClose}
position="right"
size="md"
title="Drawer Title"
>
<p>Drawer content</p>
<DrawerFooter>
<Button onClick={onClose}>Close</Button>
</DrawerFooter>
</Drawer>
```
Simple confirmation dialog.
```tsx
<Dialog
isOpen={isOpen}
onClose={onClose}
title="Confirm Action"
description="Are you sure you want to proceed?"
confirmText="Yes, proceed"
cancelText="Cancel"
onConfirm={handleConfirm}
variant="danger"
showIcon
/>
```
Text input with validation states.
```tsx
<Input
label="Email"
type="email"
placeholder="Enter your email"
state="default"
helperText="We'll never share your email"
iconLeft={<Mail />}
/>
<Textarea
label="Message"
placeholder="Enter your message"
rows={4}
helperText="Max 500 characters"
/>
```
```tsx
<Spinner size="md" />
<Badge variant="primary" size="sm">NEW</Badge>
<Badge variant="red">Alert</Badge>
```
---
```tsx
import { buttonVariants, cardVariants } from 'nutriguard-ui';
import { motion } from 'framer-motion';
<motion.div variants={cardVariants} initial="initial" whileHover="hover">
Animated Card
</motion.div>
```
- `buttonVariants` - Scale on hover/tap
- `cardVariants` - Shadow lift on hover
- `modalVariants` - Center entrance
- `drawerVariants` - Slide from edges
- `toastVariants` - Slide from top-right
- `dialogVariants` - Drop from top
- `staggerContainerVariants` - Stagger children
- `collapseVariants` - Accordion animation
---
```tsx
import { colors } from 'nutriguard-ui';
colors.black // #000000
colors.white // #FFFFFF
colors.red // #DC2626
colors.gray[400] // #9CA3AF
```
```tsx
import { spacing } from 'nutriguard-ui';
spacing[1] // 4px
spacing[2] // 8px
spacing[4] // 16px
spacing[6] // 24px
spacing[12] // 48px
```
```tsx
import { typography } from 'nutriguard-ui';
typography.fontFamily.sans // 'Inter'
typography.fontSize.base // '16px'
typography.fontWeight.bold // 700
```
---
```tsx
// ❌ Using emoji
<Button>Save 💾</Button>
// ❌ Soft shadows
<div style={{ boxShadow: '0 4px 12px rgba(0,0,0,0.1)' }} />
// ❌ Non-grid spacing
<div style={{ padding: '13px' }} />
// ❌ Unauthorized colors
<Button style={{ background: '#3B82F6' }} />
// ❌ Large border radius
<Card style={{ borderRadius: '20px' }} />
```
```tsx
// ✅ Use SVG icons
<Button iconLeft={<Save />}>Save</Button>
// ✅ Hard shadows
<Card hoverable largeShadow />
// ✅ 4px grid spacing
<div className="p-4" /> // 16px
// ✅ Strict palette
<Button variant="primary" />
// ✅ Minimal radius
<Card /> // 8px default
```
---
```tsx
import {
Button,
Card,
CardHeader,
CardTitle,
CardContent,
Modal,
ToastProvider,
useToast,
} from 'nutriguard-ui';
import { ArrowRight } from 'lucide-react';
function Dashboard() {
const [isModalOpen, setIsModalOpen] = useState(false);
const { success } = useToast();
const handleSave = () => {
success('Changes saved successfully!');
setIsModalOpen(false);
};
return (
<div className="max-w-[1440px] mx-auto px-8 py-16">
<div className="grid grid-cols-3 gap-6">
<Card hoverable>
<CardHeader>
<CardTitle>Analytics</CardTitle>
</CardHeader>
<CardContent>
<p className="text-4xl font-black">1,234</p>
<p className="text-sm text-gray-600">Total Users</p>
</CardContent>
</Card>
<Card hoverable onClick={() => setIsModalOpen(true)}>
<CardHeader>
<CardTitle>Settings</CardTitle>
</CardHeader>
<CardContent>
<p>Click to configure</p>
</CardContent>
</Card>
</div>
<Modal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="Settings"
size="md"
>
<p>Configure your settings here.</p>
<div className="flex gap-4 mt-6">
<Button variant="outline" fullWidth onClick={() => setIsModalOpen(false)}>
Cancel
</Button>
<Button variant="primary" fullWidth onClick={handleSave} iconRight={<ArrowRight />}>
Save Changes
</Button>
</div>
</Modal>
</div>
);
}
function App() {
return (
<ToastProvider>
<Dashboard />
</ToastProvider>
);
}
```
---
```bash
npm install
npm run dev
npm run build
npm test
npm run storybook
```
---
MIT © Nutrivision
---
- **Google Material Design Team** - Stitch architecture inspiration
- **Framer** - Motion library
- **Lucide** - Icon system
- **Tailwind CSS** - Utility-first CSS
---
- Documentation: [docs.nutrivision.com](https://docs.nutrivision.com)
- Issues: [GitHub Issues](https://github.com/nutrivision/nutriguard-ui/issues)
- Email: design@nutrivision.com