Skip to content

Cross-Platform

Craft Easy Admin runs on web, iOS, and Android from a single codebase using React Native + Expo. The UI adapts automatically to each platform.

Platform Support

Platform Runtime Notes
Web react-native-web Standard browser deployment
iOS Expo (native) Full native performance
Android Expo (native) Full native performance

Responsive Layout

Desktop (width >= 768px)

  • Sidebar is permanently visible on the left (250px wide)
  • Header spans the remaining width, no menu button
  • Content fills the remaining space
┌──────────┬─────────────────────────────────┐
│          │          Header                  │
│ Sidebar  ├─────────────────────────────────┤
│ (250px)  │                                 │
│          │        Content Area             │
│          │                                 │
│          │                                 │
└──────────┴─────────────────────────────────┘

Mobile (width < 768px)

  • Sidebar hidden, rendered as a drawer/modal overlay
  • Header shows a menu button to open the drawer
  • Content takes full width
┌─────────────────────────────────┐
│  [☰]     Header                 │
├─────────────────────────────────┤
│                                 │
│         Content Area            │
│         (full width)            │
│                                 │
└─────────────────────────────────┘

Mobile-Optimized Components

Several components use modal-based pickers optimized for touch:

Component Desktop Mobile
Select Modal dropdown Slide-up modal with FlatList
MultiSelect Modal with checkboxes Same — touch-friendly checkboxes
RelationPicker Search modal Same — with ActivityIndicator
Navigation Sidebar Drawer overlay

All interactive elements use appropriate touch targets:

  • Minimum hitSlop={8} on small buttons
  • Pressable components with adequate spacing
  • Modal animations via animationType="slide" for native feel

ETag Collision Modal

When two users edit the same document simultaneously, the API returns 412 Precondition Failed. The admin app handles this with a dedicated collision modal:

interface ETagCollisionModalProps {
  visible: boolean;
  onReload: () => void;
  onOverwrite: () => void;
  onCancel: () => void;
}

When it appears: A PATCH or PUT request fails with HTTP 412, meaning the document was modified since it was loaded.

Options:

Action Behavior
Reload Fetches the latest version, re-initializes the form with updated data
Overwrite Fetches the latest ETag, re-submits the user's changes with the new ETag
Cancel Closes the modal, abandons the save attempt

This prevents silent data loss from concurrent edits.

Soft Delete Filter

List views include a SoftDeleteFilter toggle that controls whether soft-deleted items are visible:

interface SoftDeleteFilterProps {
  showDeleted: boolean;
  onToggle: (showDeleted: boolean) => void;
}

When enabled, the list query includes is_deleted=true items in the results.

Views

The admin app includes four view types that adapt to the current resource schema:

ListView

  • Breadcrumb navigation
  • Title with item count
  • Search bar (when search_fields configured)
  • Sort chips (when sort_fields configured)
  • Paginated list with FlatList
  • Bulk selection via long-press
  • Create button (when features.create is true)

DetailView

  • Read-only display of all fields
  • Edit button (when features.edit is true)
  • Delete button with confirmation dialog (when features.delete is true)
  • Audit trail section (created_at, updated_at, created_by, updated_by)
  • Formatted values: booleans as checkmarks, dates localized, numbers formatted

CreateView

  • Form groups from resource.form.groups
  • Field validation: required, min_length, regex pattern
  • Cancel and Save buttons

EditView

  • Same form layout as CreateView
  • Pre-populated with current data via useResource()
  • ETag collision detection on save
  • Cancel, Save buttons