C11 — Iconography & Illustration System
Scope: Phosphor Icons extension manifest (which icons are in scope), RTL mirror flags, the 30-piece hospitality glyph set, empty-state illustration set, photography style guide, and do/don't for icon usage.
1. Icon library: Phosphor Icons
Melmastoon uses Phosphor Icons as its primary icon library. We use the Regular weight for most UI; Bold for emphasis and primary actions; Light for decorative contexts.
Package: @phosphor-icons/react (web), phosphor-react-native (mobile). Tree-shaken — only imported icons are bundled.
Prohibited: Heroicons, Feather, Material Icons, Font Awesome — do not introduce these.
2. Icon usage rules
| Rule | Description |
|---|---|
| Semantic pairing | Icons must always accompany visible text unless the icon is universally understood (close X, search magnifier, expand/collapse chevron) |
| Size | 16px (inline text), 20px (default UI), 24px (primary actions), 32px (feature icons), 48px (empty state) |
| Color | Use semantic token colors only (color.icon.default, color.icon.muted, color.icon.primary, color.icon.error). Never hardcode hex. |
aria-hidden | All icons have aria-hidden="true" (text label provides the meaning). If icon is standalone (no label), use role="img" aria-label="..." |
| Hover | Interactive icons: color shifts from color.icon.default → color.icon.primary on hover |
3. RTL mirror manifest
Directional icons must mirror horizontally in RTL (transform: scaleX(-1) via CSS):
| Icon name | Mirrors in RTL |
|---|---|
ArrowLeft | ✅ |
ArrowRight | ✅ |
ArrowCircleLeft | ✅ |
ArrowCircleRight | ✅ |
CaretLeft | ✅ |
CaretRight | ✅ |
CaretDoubleLeft | ✅ |
CaretDoubleRight | ✅ |
ChevronLeft | ✅ |
ChevronRight | ✅ |
ChevronDoubleLeft | ✅ |
ChevronDoubleRight | ✅ |
ArrowFatLeft | ✅ |
ArrowFatRight | ✅ |
List (bulleted) | ✅ (text direction) |
TextAlignLeft | ✅ |
TextAlignRight | ✅ |
Reply | ✅ |
Share | ✅ |
Cursor | ✅ |
Hand | ❌ (not directional) |
Star | ❌ |
Heart | ❌ |
Bell | ❌ |
Calendar | ❌ |
MagnifyingGlass | ❌ |
The <Icon> component in packages/ui reads the useRTL() hook and applies style={{ transform: 'scaleX(-1)' }} automatically for icons in the mirror manifest.
4. Hospitality glyph set (30 custom icons)
These hospitality-specific icons are not in Phosphor and are provided as custom SVGs in packages/ui/src/assets/icons/hospitality/:
| Glyph name | Description |
|---|---|
hospitality/bed-single | Single bed |
hospitality/bed-double | Double bed |
hospitality/bed-king | King bed |
hospitality/bed-bunk | Bunk bed |
hospitality/breakfast | Breakfast plate |
hospitality/pool | Swimming pool |
hospitality/pool-heated | Heated pool |
hospitality/spa | Spa leaf |
hospitality/gym | Dumbbell |
hospitality/wifi-full | Full WiFi signal |
hospitality/wifi-weak | Weak WiFi signal |
hospitality/key-card | RFID key card |
hospitality/key-ble | BLE mobile key |
hospitality/housekeeping | Cleaning trolley |
hospitality/luggage | Luggage / bellhop |
hospitality/concierge | Concierge bell |
hospitality/shuttle | Airport shuttle |
hospitality/parking | Parking P |
hospitality/ev-charging | EV charging plug |
hospitality/pet-friendly | Dog/paw |
hospitality/no-smoking | No smoking |
hospitality/restaurant | Fork + knife |
hospitality/bar | Cocktail |
hospitality/room-service | Tray with cover |
hospitality/passport | Passport booklet |
hospitality/folio | Receipt scroll |
hospitality/tax | Document + % |
hospitality/flight | Airplane (angled) |
hospitality/ocean-view | Waves + horizon |
hospitality/mountain-view | Mountain silhouette |
All glyphs: 24×24 viewBox; monochrome fill; designed to match Phosphor Regular weight visual style.
5. Illustration set (empty states and onboarding)
All illustrations are flat vector SVGs with 2 fills: var(--mel-color-primary-default) and var(--mel-color-surface-alt). They are not photographic or gradient-heavy.
| Illustration name | Used in |
|---|---|
empty/no-search-results | Search results zero state |
empty/no-reservations | Operator reservations list — no check-ins today |
empty/no-messages | Messaging inbox empty |
empty/no-housekeeping-tasks | Housekeeping queue complete 🎉 |
empty/no-reviews | Reviews tab — no reviews yet |
empty/offline | Offline mode — no connectivity |
empty/error-generic | Unhandled error fallback |
empty/no-reports | Reports with no data for period |
onboarding/welcome-consumer | Consumer app first launch |
onboarding/welcome-operator | Operator onboarding step 1 |
onboarding/welcome-kiosk | Kiosk setup guide |
marketing/hero-meta | Meta web default hero (before tenant uploads own) |
Do: Use illustrations only in empty states and onboarding. Do not use them as decorative page headers.
Don't: Resize illustrations below 120px height — they lose legibility.
6. Photography style guide
Style: Natural, authentic, warm light. Real guests (not stock-photo-looking models). Local context (Afghan/Central Asian settings when appropriate).
| Rule | Requirement |
|---|---|
| Aspect ratio | 16:9 landscape for hero; 4:3 for room cards; 1:1 for amenity icons |
| Colour temperature | Warm (≤ 5500K) — avoid clinical blue-cast |
| People | Diverse; natural poses; guests should be blurred/anonymous in actual property photos (no model releases needed for blurred background figures) |
| No text in photos | Avoid overlaid text on photos (accessibility + translation issues) |
| No stock photo clichés | No "person on laptop in hotel lobby" unless genuinely your hotel |
Minimum resolution: 2000px wide for hero; 1000px for card images. Cloudflare Images handles responsive sizing after upload.
7. Do / Don't
Do:
- Use
hospitality/breakfastfor breakfast-included amenity - Pair every icon with visible text unless it's universally understood
- Apply RTL mirroring to directional icons automatically via the
<Icon>component
Don't:
- Use raw emoji as icons in production UI (inconsistent across platforms; no design system control)
- Mix Phosphor icons with other icon libraries in the same context
- Use colored icons for decorative purposes — color must convey semantic meaning