Feedback/DSModal

DSModal

feedback
since 0.1.0

Centered overlay dialog with a header, scrollable content area, and footer actions. Blocks background interaction.

iOS 17+macOS 14+watchOS 10+tvOS 17+visionOS 1+

Purpose

Confirmation dialogs, forms requiring immediate attention, and multi-step mini-flows.

Interactive Reference

Live showroom

Need the full visual surface?

Screenshots do not scale well across every component, state, and variant. For the real interactive reference, import the package and launch DSShowcaseRoot().

Best for exploring:

variants, states, categories, and real app examples in one place.

Props

PropTypeDefaultDescription
isPresentedreqBinding<Bool>—Controls visibility. Tapping the backdrop or the close button sets it to false.
titleString?nilModal heading.
maxWidthCGFloat540Maximum width of the panel.
contentreq@ViewBuilder () -> Content—Modal body, including any action buttons.

Examples

Confirmation dialog

Put the modal in an overlay; actions go inside the content.

swift
.overlay {
    DSModal(isPresented: $showDelete, title: "Delete project?") {
        VStack(alignment: .leading, spacing: DSSpacing.lg) {
            DSText("This action cannot be undone.", style: .bodyMuted)
            HStack {
                DSButton("Cancel", variant: .ghost) { showDelete = false }
                DSButton("Delete", variant: .destructive) { viewModel.delete() }
            }
        }
        .padding(DSSpacing.lg)
    }
}

Form modal

Multi-field form with a narrower panel.

swift
DSModal(isPresented: $showAddTask, title: "New Task", maxWidth: 420) {
    VStack(alignment: .leading, spacing: DSSpacing.md) {
        DSTextField(label: "Title", text: $taskTitle)
        DSTextArea(label: "Description", text: $taskDescription)
        DSButton("Create", variant: .primary, isLoading: viewModel.isSaving) {
            viewModel.createTask()
        }
    }
    .padding(DSSpacing.lg)
}

When to Use

✓ Use DSModal for:

  • • Critical confirmations (delete, cancel subscription)
  • • Forms requiring immediate attention
  • • Multi-step flows that block the main UI
  • • Content that needs full user focus

✗ Avoid using for:

  • • Quick confirmations (use DSToast)
  • • Non-blocking forms (use inline or DSBottomSheet)
  • • Mobile-first actions (use DSBottomSheet on iOS)
  • • Simple yes/no questions (use native .alert())

Consider instead:

DSBottomSheet

For iOS-native bottom sheets with better mobile UX

DSAlert

For inline, non-blocking alerts

DSToast

For quick confirmations that auto-dismiss

Accessibility

VoiceOver

Announces 'Modal, [title]'. Focus trapped within modal

Keyboard

  • • Escape to dismiss
  • • Tab cycles through interactive elements
  • • Return to confirm primary action

Dynamic Type

✓ Supported

Contrast

WCAG AA compliant (overlay 3:1, content 4.5:1)

Traits

.isModalFocus trap activeBackground dimmed and non-interactive

Related Components