Design Guidelines
Table of Contents
- Typography
- Color System
- Spacing System
- Layout & Containers
- Component Standards
- Component Classes
- Responsive Design
- Accessibility Guidelines
- Icon System
Typography
Font Family
- Primary Font: Inter
- Fallback: system-ui, sans-serif
Font Sizes
Size Class | Value | Usage |
---|---|---|
text-xs | 12px / 0.75rem | Helper text, captions |
text-sm | 14px / 0.875rem | Labels, secondary text, small UI elements |
text-base | 16px / 1rem | Body text (all devices) |
text-lg | 18px / 1.125rem | Emphasized text, subsection headers |
text-xl | 20px / 1.25rem | Card/section headers |
text-2xl | 24px / 1.5rem | Major section headers |
text-3xl | 30px / 1.875rem | Page titles |
Font Weights
Weight Class | Value | Usage |
---|---|---|
font-normal | 400 | Regular body text |
font-medium | 500 | Medium emphasis, labels |
font-semibold | 600 | Section headers, emphasis |
font-bold | 700 | Strong emphasis, page headers |
Line Heights
Class | Value | Usage |
---|---|---|
leading-none | 1 | Headings, where tight spacing is needed |
leading-tight | 1.25 | Compact text areas |
leading-normal | 1.5 | Body text (default) |
leading-relaxed | 1.625 | Extended reading text |
Color System
OX Agry uses a nature-inspired color palette that reflects agricultural themes.
Base Colors
Variable | Light Mode | Dark Mode | Usage |
---|---|---|---|
background | hsl(60, 33%, 98%) | hsl(123, 15%, 12%) | Page background |
foreground | hsl(147, 30%, 12%) | hsl(83, 24%, 95%) | Primary text |
primary | hsl(123, 35%, 35%) | hsl(123, 35%, 45%) | Primary actions, branding |
secondary | hsl(83, 24%, 95%) | hsl(147, 20%, 20%) | Secondary elements |
muted | hsl(83, 24%, 95%) | hsl(147, 20%, 20%) | Subdued UI elements |
accent | hsl(76, 39%, 90%) | hsl(147, 20%, 20%) | Highlights, accents |
destructive | hsl(0, 74%, 42%) | hsl(0, 62.8%, 40.6%) | Destructive actions |
Agricultural Semantic Colors
Variable | Value (Light Mode) | Purpose |
---|---|---|
growth | hsl(123, 42%, 35%) | Plant growth indicators |
soil | hsl(27, 65%, 45%) | Soil-related data |
harvest | hsl(45, 85%, 50%) | Harvest/yield information |
water | hsl(195, 45%, 45%) | Water/irrigation data |
leaf | hsl(96, 40%, 45%) | Foliage health indicators |
Status Colors
Variable | Value (Light Mode) | Purpose |
---|---|---|
success | hsl(145, 50%, 40%) | Success states, healthy growth |
warning | hsl(35, 95%, 50%) | Warning states, drought alerts |
error | hsl(0, 75%, 42%) | Error states, disease/pest alerts |
info | hsl(195, 45%, 45%) | Information states, weather alerts |
State Colors
State | Variables | Usage |
---|---|---|
Focus | --ring: hsl(123, 35%, 45%), | Interactive element focus |
--ring-width: 2px | ||
Hover | --hover-opacity: 0.9, | Element hover states |
--hover-brightness: 1.05 | ||
Active | --active-opacity: 0.8, | Element active/pressed states |
--active-brightness: 0.95 | ||
Disabled | --disabled-bg: hsl(83, 10%, 95%), | Disabled elements appearance |
--disabled-text: hsl(147, 10%, 60%), | ||
--disabled-opacity: 0.6 |
Spacing System
OX Agry uses a consistent spacing scale based on 4px increments.
Spacing Scale
Class | Size | Usage |
---|---|---|
p-1, m-1 | 4px | Minimal spacing, icons |
p-2, m-2 | 8px | Tight spacing, compact elements |
p-3, m-3 | 12px | Default inner padding |
p-4, m-4 | 16px | Standard content spacing |
p-6, m-6 | 24px | Section spacing |
p-8, m-8 | 32px | Large section spacing |
p-12, m-12 | 48px | Major section divisions |
p-16, m-16 | 64px | Page level spacing |
Form Field Spacing
- Field to field spacing: 24px (m-6)
- Label to input spacing: 8px (m-2)
- Input to error area: 4px (m-1)
- Reserved error text space: 20px (min-height)
Implementation Example
<div className="space-y-6">
{" "}
{/* 24px between form groups */}
<div className="form-group">
<label className="block text-sm font-medium mb-2">Field Label</label>
<input className="w-full px-3 h-11 rounded-md border border-input" />
<div className="min-h-5">
{" "}
{/* Reserved error space */}
{error && <p className="text-destructive text-sm mt-1">{error}</p>}
</div>
</div>
{/* Next form group */}
</div>
Layout & Containers
Container Widths
Breakpoint | Container Size | Sidebar Width | Content Width |
---|---|---|---|
Mobile (768px and below) | 100% with 16px margins | Off-canvas | 100% when sidebar hidden |
Tablet (768px to 1279px) | 100% with 24px margins | 240-280px | Remaining space |
Desktop (1280px and up) | Max-width 1280-1440px | 280-320px | Remaining space |
Layout Structure
+--------------------------------------------+
| <header> |
+--------+-----------------------------------+
| | |
| | |
| | |
| Sidebar| Content Area |
| | |
| | |
| | |
+--------+-----------------------------------+
Implementation Example
<div className="min-h-screen bg-background">
{/* Main container */}
<div className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row">
{/* Sidebar */}
<aside className="w-full md:w-72 lg:w-80 bg-sidebar text-sidebar-foreground">
{/* Sidebar content */}
</aside>
{/* Main content */}
<main className="flex-1 p-4 md:p-6">{/* Page content */}</main>
</div>
</div>
</div>
Component Standards
Form Controls
Heights
- Standard height: 44px (h-11)
- Use consistently for all interactive elements that appear in the same row
Text Inputs
State | Styling |
---|---|
Default | border-input bg-background |
Focus | ring-2 ring-primary border-primary |
Error | border-destructive |
Disabled | opacity-60 bg-muted |
Buttons
Type | Styling |
---|---|
Primary | bg-primary text-primary-foreground |
Secondary | bg-secondary text-secondary-foreground |
Outline | border border-input bg-background hover:bg-accent |
Destructive | bg-destructive text-destructive-foreground |
Ghost | hover:bg-accent hover:text-accent-foreground |
Disabled | opacity-60 cursor-not-allowed |
Form Structure Example
<form className="space-y-6">
{/* Form field */}
<div>
<label className="text-sm font-medium mb-2 block">Field Label</label>
<input className="w-full h-11 px-3 rounded-md border border-input" />
<div className="min-h-5">{/* Error message placeholder */}</div>
</div>
{/* Actions */}
<div className="flex gap-3 pt-2">
<button className="h-11 px-4 bg-primary text-primary-foreground rounded-md">
Submit
</button>
<button className="h-11 px-4 border border-input bg-background rounded-md">
Cancel
</button>
</div>
</form>
Cards & Panels
- Standard padding: 16px (p-4) to 24px (p-6)
- Rounded corners: 8px (rounded-lg)
- Consistent border: border border-border
- Optional shadow: shadow-sm to shadow-md
<div className="bg-card text-card-foreground p-6 rounded-lg border border-border shadow-sm">
<h3 className="text-xl font-semibold mb-4">Card Title</h3>
<div className="text-base">Card content goes here</div>
</div>
Component Classes
To maintain consistent styling while improving development efficiency, OX Agry uses reusable component classes with Tailwind CSS. This approach avoids repetitive inline styles while maintaining the flexibility of Tailwind.
Implementation Approach
Create a components.css
file with reusable classes:
/* components.css */
@layer components {
/* Form Elements */
.ox-input {
@apply w-full px-3 h-11 rounded-md border border-input bg-background text-foreground;
}
.ox-input:focus {
@apply ring-2 ring-primary border-primary outline-none;
}
.ox-input:disabled {
@apply opacity-60 bg-muted cursor-not-allowed;
}
.ox-input-error {
@apply border-destructive focus:border-destructive focus:ring-destructive;
}
.ox-label {
@apply block text-sm font-medium mb-2;
}
.ox-error {
@apply text-destructive text-sm mt-1;
}
.ox-helper {
@apply text-muted-foreground text-xs mt-1;
}
.ox-form-group {
@apply mb-6;
}
.ox-error-container {
@apply min-h-5;
}
/* Buttons */
.ox-btn {
@apply h-11 px-4 rounded-md inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60;
}
.ox-btn-primary {
@apply bg-primary text-primary-foreground hover:bg-primary/90;
}
.ox-btn-secondary {
@apply bg-secondary text-secondary-foreground hover:bg-secondary/80;
}
.ox-btn-outline {
@apply border border-input bg-background hover:bg-accent hover:text-accent-foreground;
}
.ox-btn-destructive {
@apply bg-destructive text-destructive-foreground hover:bg-destructive/90;
}
/* Cards */
.ox-card {
@apply bg-card text-card-foreground p-6 rounded-lg border border-border shadow-sm;
}
.ox-card-title {
@apply text-lg font-semibold leading-none tracking-tight mb-3;
}
.ox-card-description {
@apply text-sm text-muted-foreground mb-4;
}
/* Agricultural-specific components */
.ox-field-data {
@apply bg-secondary p-3 rounded-md;
}
.ox-crop-badge {
@apply inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold;
}
.ox-growth-indicator {
@apply text-growth;
}
.ox-harvest-indicator {
@apply text-harvest;
}
}
Form Element Classes
Class | Purpose | Applied Styles |
---|---|---|
ox-input | Base input styling | w-full px-3 h-11 rounded-md border border-input bg-background text-foreground |
ox-label | Form labels | block text-sm font-medium mb-2 |
ox-error | Error messages | text-destructive text-sm mt-1 |
ox-helper | Helper text | text-muted-foreground text-xs mt-1 |
ox-form-group | Form group wrapper | mb-6 |
ox-error-container | Error container | min-h-5 |
Button Classes
Class | Purpose | Applied Styles |
---|---|---|
ox-btn | Base button | h-11 px-4 rounded-md inline-flex items-center justify-center |
ox-btn-primary | Primary action | bg-primary text-primary-foreground hover:bg-primary/90 |
ox-btn-secondary | Secondary action | bg-secondary text-secondary-foreground hover:bg-secondary/80 |
ox-btn-outline | Outline button | border border-input bg-background hover:bg-accent |
ox-btn-destructive | Destructive action | bg-destructive text-destructive-foreground hover:bg-destructive/90 |
Card Classes
Class | Purpose | Applied Styles |
---|---|---|
ox-card | Card container | bg-card text-card-foreground p-6 rounded-lg border border-border shadow-sm |
ox-card-title | Card title | text-lg font-semibold leading-none tracking-tight mb-3 |
ox-card-description | Card description | text-sm text-muted-foreground mb-4 |
Usage Examples
Form group with reusable classes:
<div className="ox-form-group">
<label className="ox-label">Crop Type</label>
<select className="ox-input">
<option value="wheat">Wheat</option>
<option value="corn">Corn</option>
</select>
<div className="ox-error-container">
{error && <p className="ox-error">{error}</p>}
</div>
</div>
Button examples:
<button className="ox-btn ox-btn-primary">Save Changes</button>
<button className="ox-btn ox-btn-outline">Cancel</button>
Card example:
<div className="ox-card">
<h3 className="ox-card-title">Field Report</h3>
<p className="ox-card-description">Summary of current field conditions</p>
<div className="ox-field-data">
<span className="ox-growth-indicator">Healthy growth detected</span>
</div>
</div>
Extending shadcn/UI Components
Create wrapper components that apply OX Agry specific styles:
// components/ui/OxInput.jsx
import { Input } from "@/components/ui/input";
export const OxInput = React.forwardRef((props, ref) => {
const { error, ...rest } = props;
return (
<Input
className={`h-11 ${error ? "ox-input-error" : ""}`}
{...rest}
ref={ref}
/>
);
});
This approach ensures consistent styling while leveraging Tailwind and shadcn/UI.
Responsive Design
Breakpoints
Name | Width | CSS |
---|---|---|
xs | < 640px | (default) |
sm | ≥ 640px | sm:... |
md | ≥ 768px | md:... |
lg | ≥ 1024px | lg:... |
xl | ≥ 1280px | xl:... |
2xl | ≥ 1536px | 2xl:... |
Responsive Patterns
-
Stacking to Side-by-Side
<div className="flex flex-col md:flex-row gap-4">
<div className="w-full md:w-1/2">Panel 1</div>
<div className="w-full md:w-1/2">Panel 2</div>
</div> -
Grid Adaptation
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div> -
Hidden to Visible Elements
<button className="md:hidden">Mobile Menu</button>
<nav className="hidden md:block">
{/* Navigation items */}
</nav>
Mobile-First Approach
Always design and implement for mobile first, then enhance for larger screens.
Accessibility Guidelines
Color Contrast
- Text on backgrounds: Minimum 4.5:1 contrast ratio
- Large text/headers: Minimum 3:1 contrast ratio
- UI components/graphics: Minimum 3:1 contrast ratio against adjacent colors
Interactive Elements
- Focus states: All interactive elements must have visible focus states
- Touch targets: Minimum 44px × 44px for touch targets on mobile
- Spacing: Adequate spacing between clickable elements (minimum 8px)
Keyboard Navigation
- All interactive elements must be keyboard accessible
- Logical tab order following visual layout
- Focus visible at all times during keyboard navigation
Assistive Text
- Form inputs should have associated labels
- Images should have appropriate alt text
- Icons used alone should have accessible names
Example Implementation
<button className="ox-btn ox-btn-primary" aria-label="Save field data">
<span>Save</span>
</button>
Icon System
Icon Sizes
Size | Dimensions | Usage | Class |
---|---|---|---|
Small | 16px | Inline with text, dense UIs | ox-icon-sm |
Medium | 20px | Standard UI elements | ox-icon |
Large | 24px | Primary navigation, emphasis | ox-icon-lg |
XLarge | 32px | Feature highlights | ox-icon-xl |
Icon Colors
Icons should use the text color of their context:
text-foreground
for standard iconstext-muted-foreground
for secondary iconstext-primary
for emphasized icons- Current color (
currentColor
) when used within buttons/controls
Implementation Example
<button className="ox-btn ox-btn-primary">
<svg className="w-5 h-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
{/* Icon paths */}
</svg>
<span>Crop Rotation</span>
</button>
Component Classes for Icons
@layer components {
.ox-icon {
@apply w-5 h-5 inline-block;
}
.ox-icon-sm {
@apply w-4 h-4;
}
.ox-icon-lg {
@apply w-6 h-6;
}
.ox-icon-xl {
@apply w-8 h-8;
}
}
Usage example:
<Icon name="crop" className="ox-icon ox-icon-lg text-primary" />