diff --git a/.impeccable.md b/.impeccable.md new file mode 100644 index 0000000..d6257d4 --- /dev/null +++ b/.impeccable.md @@ -0,0 +1,17 @@ +## Design Context + +### Users +Developer-founders and indie hackers building SaaS products. They use Plunk to handle transactional and marketing email without the complexity of tools like Mailchimp or Customer.io. They notice tiny details — inconsistent spacing, placeholder text that adds no value, a button that doesn't communicate state. Context: professional environment, desktop-first. + +### Brand Personality +Sharp, minimal, confident. The product earns trust by being simple and correct, not by being flashy. Testimonials emphasize "transparent UI", "easy setup", "clean design" — the brand is *care without noise*. + +### Aesthetic Direction +Light mode only. Palette: black (`neutral-900`), neutral grays, white. No accent colors. No color for decoration — only for semantics (red = error, green = success). Backgrounds are near-white with subtle texture. Cards use white with a neutral border and light shadow. Typography should feel precise and legible, not editorial. Spacing should feel considered, not generous. + +### Design Principles +1. **Every pixel earns its place.** If something doesn't communicate information or provide affordance, remove it. +2. **Neutral by default, semantic by exception.** Color is reserved for error/success/warning states, not decoration. +3. **Interaction should feel fast.** Loading states communicate exactly what's happening. No silent actions. +4. **Developer-grade precision.** Copy is short and direct. Placeholders only appear when they add value. Labels are unambiguous. +5. **Consistency is trust.** The same pattern everywhere. One way to show errors. One way to show success. No creative variation in functional UI. diff --git a/apps/web/src/components/ActivityFeed.tsx b/apps/web/src/components/ActivityFeed.tsx index 2634175..9e19c29 100644 --- a/apps/web/src/components/ActivityFeed.tsx +++ b/apps/web/src/components/ActivityFeed.tsx @@ -2,7 +2,8 @@ import {Button} from '@plunk/ui'; import type {Activity, CursorPaginatedResponse} from '@plunk/types'; import {network} from '../lib/network'; import {ActivityItem} from './ActivityItem'; -import {Loader2} from 'lucide-react'; +import {EmptyState} from './EmptyState'; +import {Activity as ActivityIcon, Loader2} from 'lucide-react'; import {useCallback, useEffect, useMemo, useState} from 'react'; export interface ActivityFeedProps { @@ -186,11 +187,11 @@ export function ActivityFeed({typeFilter, dateRangeDays = 30, contactId}: Activi if (activities.length === 0 && upcomingActivities.length === 0) { return ( -
- No activity found for the selected filters. Activities will appear here as they happen. -
-