# Modern UX & Front-End Design Best Practices > Reference guide for B2B SaaS dashboard applications, with emphasis on ISP/network monitoring tools. > All examples use Tailwind CSS. Phoenix LiveView patterns included where relevant. --- ## Table of Contents 1. [Design Systems](#1-design-systems) 2. [Layout Patterns](#2-layout-patterns) 3. [Data Display](#3-data-display) 4. [Forms & Input](#4-forms--input) 5. [Navigation](#5-navigation) 6. [Accessibility](#6-accessibility) 7. [Animation & Transitions](#7-animation--transitions) 8. [Phoenix LiveView Specific](#8-phoenix-liveview-specific) 9. [Color & Typography](#9-color--typography) 10. [Anti-Patterns](#10-anti-patterns) --- ## 1. Design Systems ### Component Hierarchy Organize components in three tiers: | Tier | Examples | Characteristics | |------|----------|-----------------| | **Primitives** | Button, Badge, Input, Label | Stateless, no business logic, maximum reuse | | **Composites** | Card, DataTable, FormGroup, Modal | Combine primitives, may have local state | | **Features** | DevicePanel, AlertFeed, BandwidthChart | Domain-specific, connected to data | ``` components/ ├── ui/ # Primitives — button, badge, input, tooltip ├── composite/ # Composites — card, data_table, form_group └── features/ # Features — device_panel, alert_feed ``` ### Design Tokens Define tokens in `tailwind.config.js` — never use raw hex in templates: ```js // tailwind.config.js module.exports = { theme: { extend: { colors: { // Semantic tokens surface: { DEFAULT: 'var(--color-surface)', // white / gray-900 raised: 'var(--color-surface-raised)', // gray-50 / gray-800 overlay: 'var(--color-surface-overlay)', // white / gray-800 }, border: { DEFAULT: 'var(--color-border)', // gray-200 / gray-700 strong: 'var(--color-border-strong)', // gray-300 / gray-600 }, status: { healthy: '#10b981', // emerald-500 warning: '#f59e0b', // amber-500 critical: '#ef4444', // red-500 unknown: '#6b7280', // gray-500 maint: '#3b82f6', // blue-500 }, }, spacing: { 'sidebar': '16rem', // 256px collapsed 'sidebar-sm': '4rem', // 64px collapsed 'topbar': '4rem', // 64px }, fontSize: { 'kpi': ['2rem', { lineHeight: '2.5rem', fontWeight: '700' }], 'metric': ['1.5rem', { lineHeight: '2rem', fontWeight: '600' }], }, }, }, } ``` ### Tailwind Best Practices **Avoid class soup — extract components, not utilities:** ```html <.button variant="primary" size="md">Save ``` **The component function:** ```elixir # core_components.ex attr :variant, :string, default: "primary", values: ~w(primary secondary ghost danger) attr :size, :string, default: "md", values: ~w(sm md lg) attr :disabled, :boolean, default: false slot :inner_block, required: true def button(assigns) do ~H""" """ end ``` ### Dark Mode Use Tailwind's `dark:` variant with CSS custom properties for seamless theming: ```css /* app.css */ :root { --color-surface: theme('colors.white'); --color-surface-raised: theme('colors.gray.50'); --color-surface-overlay: theme('colors.white'); --color-border: theme('colors.gray.200'); --color-border-strong: theme('colors.gray.300'); --color-text-primary: theme('colors.gray.900'); --color-text-secondary: theme('colors.gray.500'); } .dark { --color-surface: theme('colors.gray.900'); --color-surface-raised: theme('colors.gray.800'); --color-surface-overlay: theme('colors.gray.800'); --color-border: theme('colors.gray.700'); --color-border-strong: theme('colors.gray.600'); --color-text-primary: theme('colors.gray.100'); --color-text-secondary: theme('colors.gray.400'); } ``` **Toggle strategy:** ```js // Respect system preference, allow manual override const theme = localStorage.getItem('theme'); if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.documentElement.classList.add('dark'); } ``` --- ## 2. Layout Patterns ### App Shell The canonical B2B SaaS layout: fixed sidebar + top bar + scrollable content area. ```html
Network / Devices
``` ### Collapsible Sidebar ```html ``` ### Mobile Sidebar (Slide-over) ```html
``` ### Dashboard Grid Use CSS Grid with responsive breakpoints for KPI cards and widgets: ```html

Total Devices

1,247

+12 this week

Bandwidth Usage (24h)

Recent Alerts

``` ### Card Component ```html

Device Health

Last updated 2 min ago

``` ### Skeleton Loading ```html
``` **Skeleton shimmer effect (optional CSS):** ```css @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } .skeleton-shimmer { background: linear-gradient(90deg, theme('colors.gray.200') 25%, theme('colors.gray.100') 50%, theme('colors.gray.200') 75% ); background-size: 200% 100%; animation: shimmer 1.5s infinite; } .dark .skeleton-shimmer { background: linear-gradient(90deg, theme('colors.gray.700') 25%, theme('colors.gray.600') 50%, theme('colors.gray.700') 75% ); } ``` --- ## 3. Data Display ### Tables Tables are the backbone of network monitoring UIs. Get them right. ```html
Hostname
IP Address Status Uptime Last Seen
core-router-01 10.0.1.1 Online 142d 7h 2 min ago

Showing 1 to 25 of 1,247

...
``` **Table design rules:** - Left-align text, right-align numbers - Use `font-mono text-xs` for IPs, MACs, serial numbers - Status columns: colored badge with dot indicator - Always provide a row hover state - Sticky header on long tables: `sticky top-0 z-10` - Avoid wrapping — use `truncate` and `max-w-*` with tooltips ### Charts — Which Type When | Data Type | Chart | Example | |-----------|-------|---------| | **Time series** | Line/Area | Bandwidth, latency, CPU over time | | **Composition** | Stacked area/bar | Traffic by protocol over time | | **Comparison** | Horizontal bar | Top 10 talkers by bandwidth | | **Distribution** | Histogram | Latency distribution | | **Single value + trend** | KPI card + sparkline | Current throughput | | **Part of whole** | Donut (never pie) | Device status breakdown | | **Geographic** | Map with pins/heatmap | Tower locations, coverage | | **Correlation** | Scatter plot | Packet loss vs. distance | **Chart guidelines for monitoring dashboards:** - Default to **24h** time range with **auto-refresh** - Always show the y-axis scale and units (Mbps, ms, %) - Use **area fills** with low opacity (`fill-opacity: 0.1`) for single-line charts - Color thresholds: green < 70%, amber 70–90%, red > 90% - Provide time range selector: 1h | 6h | 24h | 7d | 30d - Tooltip should show exact timestamp + value - Loading state: show axes + gray placeholder area ### KPI Widget ```html

Packet Loss

0.02%

-0.01%

vs. 0.03% yesterday

``` ### Empty / Error / Loading States Every data view needs all three. **Never show a blank screen.** ```html

No devices found

Add your first device to start monitoring your network.

Failed to load devices

Something went wrong. Please try again or contact support if the problem persists.

``` **State hierarchy:** 1. **Loading** → skeleton (content areas) or spinner (actions) 2. **Error** → message + retry action 3. **Empty** → illustration + explanation + primary action 4. **Data** → the actual content --- ## 4. Forms & Input ### Validation Patterns **Inline validation — validate on blur, show errors immediately:** ```html

Hostname must contain only lowercase letters, numbers, and hyphens.

``` **Validation rules:** - Validate on blur (not on every keystroke) - Show success states for complex fields (IP addresses, CIDR notation) - Group related errors at the top of the form for long forms - Never clear the user's input on error - For LiveView: use `phx-change` with debounce for real-time validation ### Radio Card Groups Perfect for selecting device types, plan tiers, or monitoring profiles: ```html
Device Type
``` ### Search & Filter Patterns **Combo filter bar:** ```html
Status: Online Type: Router
``` ### Auto-Save Indicator ```html
Saving... Saved Failed to save
``` ### Confirmation Dialogs Use for destructive actions only. **Never confirm routine saves.** ```html

Delete Device

Are you sure you want to delete core-router-01? All monitoring data will be permanently removed. This action cannot be undone.

``` **Rules for confirmation dialogs:** - Destructive button on the **right**, cancel on the **left** - Name the action specifically ("Delete Device" not "Are you sure?") - Include the resource name in the message - Red color for destructive action button - For high-stakes actions, require typing the resource name --- ## 5. Navigation ### Breadcrumbs ```html ``` ### Tabs ```html
``` ### Command Palette (Cmd+K) Essential for power users in network monitoring tools: ```html
ESC

Devices

core-router-01

10.0.1.1 · Router

core-router-02

10.0.1.2 · Router

Actions

Add new device

N
↑↓ Navigate Open ESC Close
``` ### Notifications **Toast notifications** — for transient feedback: ```html
``` **Toast rules:** - Auto-dismiss success toasts after 5 seconds - Error toasts persist until dismissed - Max 3 visible toasts; queue the rest - Position: bottom-right for desktop, top-center for mobile **Banner notifications** — for system-wide alerts: ```html

Scheduled maintenance: Core network upgrade on March 15 at 02:00 UTC. Learn more

``` **Notification badge:** ```html
Alerts
12
``` ### Onboarding **Setup checklist:** ```html

Getting Started

2 of 4 complete
``` **Progressive disclosure:** Show complexity only when needed. ```html
``` --- ## 6. Accessibility ### ARIA Essentials ```html
Device core-router-01 status changed to offline
Online
``` ### Keyboard Navigation | Component | Keys | Behavior | |-----------|------|----------| | **Modal** | `Escape` | Close | | **Tabs** | `←` `→` | Switch tabs | | **Dropdown** | `↑` `↓` `Enter` `Escape` | Navigate, select, close | | **Table** | `Space` | Toggle row selection | | **Command palette** | `⌘K` / `Ctrl+K` | Open | | **Toast** | Auto-focus close button | Dismiss | ### Focus Management ```html Skip to main content ``` ### Color Contrast **WCAG 2.1 AA minimum contrast ratios:** | Element | Ratio | Example | |---------|-------|---------| | Normal text (< 18px) | **4.5:1** | `gray-600` on white = 5.4:1 ✅ | | Large text (≥ 18px bold / 24px) | **3:1** | `gray-500` on white = 4.6:1 ✅ | | UI components & graphics | **3:1** | Border, icons, form controls | **Don't rely on color alone:** - ❌ Red text for errors, green text for success (color blind users lose info) - ✅ Red text + error icon + descriptive text - ✅ Status dot + text label ("Online", "Offline") - ✅ Chart lines with different patterns/shapes, not just colors ```html Critical ``` --- ## 7. Animation & Transitions ### CSS Transitions Use for state changes, not entrance animations. Keep them fast (150–200ms). ```html