Diese Seite wurde maschinell übersetzt und kann Fehler enthalten. Das englische Original lesen

Elemente

AlertDialog

AlertDialog zeigt den plattformeigenen Alert bzw. Action Sheet an: UIAlertController unter iOS und Mac Catalyst, einen AlertDialog (oder einen Listendialog für ein Action Sheet) unter Android und einen Alert im Dialogstil der Plattform auf den anderen Plattformen. AlertDialog.show (.show() von alert_dialog() in Rust) gibt ein Promise zurück (in Rust ein Future), das mit { action } aufgelöst wird: dem id der Aktion, die der Benutzer gewählt hat. Jedes Label stammt aus der App, ein Alert sagt also genau das, was Ihre App sagt, in deren Sprache.

el-alert-dialog.tsx
el-alert-dialog.tsxLive
import { mount, signal, Text, View } from "nsh";
import { AlertDialog, Button } from "nsh/base";
import { button, buttonText, desktop, focusRing, hoverFill, Inspector, Panel, size, Stage, ui, wide } from "./palette";

type Options = Parameters<typeof AlertDialog.show>[0];

// What each button shows, and what it is about.
const alerts: { label: string; detail: string; danger?: boolean; options: Options }[] = [
  {
    label: "Delete…",
    detail: "cancel + destructive roles",
    danger: true,
    options: {
      title: "Delete the photo?",
      description: "This cannot be undone.",
      actions: [
        { label: "Cancel", role: "cancel", id: "cancel" },
        { label: "Delete", role: "destructive", id: "delete" },
      ],
    },
  },
  {
    label: "Save changes…",
    detail: "three actions, closeOnEscape",
    options: {
      title: "Save changes?",
      description: "Your edits to “Trip notes” are not saved yet.",
      actions: [
        { label: "Don't save", role: "destructive", id: "discard" },
        { label: "Cancel", role: "cancel", id: "cancel" },
        { label: "Save", id: "save" },
      ],
      closeOnEscape: true,
    },
  },
  {
    label: "Share…",
    detail: 'presentation "actionSheet"',
    options: {
      title: "Share the photo",
      presentation: "actionSheet",
      actions: [
        { label: "Copy link", id: "copy" },
        { label: "Save", id: "save" },
        { label: "Delete", role: "destructive", id: "delete" },
        { label: "Cancel", role: "cancel", id: "cancel" },
      ],
    },
  },
];

function App() {
  const answer = signal("–");
  const shown = signal(0);
  const show = async (options: Options) => {
    shown.update((n) => n + 1);
    const { action } = await AlertDialog.show(options);
    answer.set(action === null ? "{ action: null } (closed without an action)" : `{ action: ${JSON.stringify(action)} }`);
  };
  const row = () => ({ ...ui().row, borderRadius: 12, padding: 14, gap: 2 });
  const hint = desktop ? "Escape or a click outside the action sheet closes it with { action: null }." : "A tap outside the action sheet closes it with { action: null }.";
  return (
    <View style={{ flex: 1, backgroundColor: ui().page, padding: 20, paddingTop: 24, gap: 12 }}>
      <Text style={{ fontSize: 22, fontWeight: "700", color: ui().text }}>alert-dialog</Text>
      <Text style={{ color: ui().muted }}>The platform's own alert; every label comes from the app.</Text>

      {() =>
        wide() ? (
          <View style={{ flex: 1, flexDirection: "row", gap: 16 }}>
            {/* A row per alert: what it shows, and a button as wide as its label at the end. */}
            <Stage width={400}>
              <View style={{ ...ui().card, borderRadius: 14, overflow: "hidden" }}>
                <Each of={alerts}>
                  {(a, i) => (
                    <>
                      {i() > 0 ? <View style={{ height: 1, marginLeft: 12, backgroundColor: ui().line }} /> : null}
                      <View style={{ flexDirection: "row", alignItems: "center", gap: 12, height: size.row + 4, paddingHorizontal: 12 }}>
                        <Text style={{ flex: 1, fontSize: 13, color: ui().muted }}>{a().detail}</Text>
                        <Button onPress={() => show(a().options)} {...button()}>
                          <Text style={{ ...buttonText(), color: a().danger ? ui().down : ui().text }}>{a().label}</Text>
                        </Button>
                      </View>
                    </>
                  )}
                </Each>
              </View>
            </Stage>
            <Inspector>
              <Panel title={`AlertDialog.show resolved with (${shown()} shown)`}>
                <Text style={{ color: ui().accent, fontSize: 14, fontWeight: "600" }}>{answer()}</Text>
              </Panel>
              <Text style={{ color: ui().faint, fontSize: 12 }}>{hint}</Text>
            </Inspector>
          </View>
        ) : (
          <View style={{ gap: 10 }}>
            <Each of={alerts}>
              {(a) => (
                <Button onPress={() => show(a().options)} style={row()} activeStyle={{ opacity: 0.7 }} hoverStyle={hoverFill()} focusStyle={focusRing()}>
                  <Text style={{ color: a().danger ? ui().down : ui().text, fontSize: 16, fontWeight: "600" }}>{a().label}</Text>
                  <Text style={{ color: ui().muted, fontSize: 13 }}>{a().detail}</Text>
                </Button>
              )}
            </Each>

            <View style={{ ...ui().inset, borderRadius: 12, padding: 14, gap: 4, marginTop: 4 }}>
              <Text style={{ color: ui().muted, fontSize: 13 }}>AlertDialog.show resolved with ({shown()} shown)</Text>
              <Text style={{ color: ui().accent, fontSize: 16, fontWeight: "600" }}>{answer()}</Text>
            </View>
            <Text style={{ color: ui().faint, fontSize: 13 }}>{hint}</Text>
          </View>
        )
      }
    </View>
  );
}

mount(App);
use nsh_base::{alert_dialog, button};
use nsh_core::prelude::*;

fn app() -> impl IntoElement {
    let answer = signal(SharedString::from("–"));
    let confirm = move || {
        spawn(async move {
            let choice = alert_dialog()
                .title("Delete the photo?")
                .description("This cannot be undone.")
                .cancel("cancel", "Cancel")
                .destructive("delete", "Delete")
                .show()
                .await;
            let deleted = matches!(choice, Ok(r) if r.action.as_deref() == Some("delete"));
            answer.set(if deleted { "deleted" } else { "kept" }.into());
        });
    };
    view()
        .flex_1()
        .p_4()
        .pt(px(48.0))
        .gap_3()
        .child(
            button()
                .on_press(confirm)
                .rounded_lg()
                .bg(rgb(0xdc2626))
                .px_4()
                .py_3()
                .child(text("Delete…").text_color(white()).font_weight(FontWeight::SEMIBOLD)),
        )
        .child(text(answer))
}

Für Dialoge mit eigenem Aussehen (eine Karte, ein Sheet, ein Vollbild-Ablauf) verwenden Sie Dialog.

#AlertDialog.show

AlertDialog.show(options: AlertDialogOptions): Promise<AlertDialogResult>
alert_dialog().title(..).description(..).action(..).cancel(..).destructive(..).show()
    -> impl Future<Output = Result<AlertDialogResult, String>>

Das Ergebnis ist { action } (AlertDialogResult): das id der gewählten Aktion oder null (None), wenn der Dialog ohne Aktion geschlossen wurde: durch einen Tipp außerhalb, Escape oder die Zurück-Taste, sofern closeOnBackdropPress und closeOnEscape dies erlauben. Ohne Aktionen wird das Promise mit einem TypeError abgelehnt (in Rust mit einem Err). In Rust richtet nsh_base::alert_dialog() den Dialog mit einer Methode pro Option und pro Aktion ein, in der Reihenfolge, in der die Aktionen angezeigt werden, und .show() zeigt ihn an; warten Sie in einem Task auf die Antwort (spawn).

#Action sheets

Ein Action Sheet übernimmt dieselben Optionen mit der Präsentation "actionSheet":

use nsh_base::alert_dialog;
use nsh_core::prelude::*;

fn share() {
    spawn(async move {
        let choice = alert_dialog()
            .title("Share the photo")
            .action_sheet()
            .action("copy", "Copy link")
            .action("save", "Save")
            .destructive("delete", "Delete")
            .cancel("cancel", "Cancel")
            .show()
            .await;
        match choice.ok().and_then(|r| r.action).as_deref() {
            Some("copy") => { /* … */ }
            Some("save") => { /* … */ }
            Some("delete") => { /* … */ }
            _ => {} // "cancel", or closed without an action.
        }
    });
}

#AlertDialogOptions

Feld Rust Typ Standard Beschreibung
title .title(..) string | null keiner Über der Beschreibung.
description .description(..) string | null keiner Unter dem Titel.
actions .action(..), .cancel(..), .destructive(..), eine pro Aktion AlertDialogAction[] erforderlich Die Aktionen in ihrer Reihenfolge (mindestens eine; bei einem Android-Alert höchstens drei).
presentation .action_sheet() "alert" | "actionSheet" "alert" Ein Alert in der Mitte oder ein Sheet mit Aktionen vom unteren Rand (unter Android ein Listendialog).
closeOnEscape .close_on_escape(..) boolean | null false bei einem Alert, true bei einem Action Sheet Escape und die Android-Zurück-Taste schließen den Dialog ohne Aktion.
closeOnBackdropPress .close_on_backdrop_press(..) boolean | null false bei einem Alert, true bei einem Action Sheet Ein Tipp außerhalb schließt den Dialog ohne Aktion.

#AlertDialogResult

Feld Rust Typ Beschreibung
action action string | null (Option<SharedString>) Das id der gewählten Aktion oder null, wenn der Dialog ohne Aktion geschlossen wurde.

#AlertDialogAction

Feld Rust Typ Standard Beschreibung
id das erste Argument der Methode string erforderlich Was show bei Auswahl als action meldet: der Name der App dafür, der unabhängig von der Sprache der Labels gleich bleibt.
label das zweite Argument der Methode string erforderlich Was sie anzeigt.
role .action(..), .cancel(..), .destructive(..) "default" | "cancel" | "destructive" "default" Was sie bedeutet: Die Plattform platziert und zeichnet sie nach ihrer Rolle (eine destruktive Aktion ist unter iOS rot).

#Hinweise zu den Plattformen

  • iOS: UIAlertController ordnet die Aktionen an. Eine Aktion mit der Rolle "cancel" wird dort platziert, wo iOS Abbrechen-Aktionen platziert, und ein Action Sheet zeigt sie getrennt an seinem unteren Rand. Auf dem iPad und unter Mac Catalyst ist das Action Sheet ein Popover mit einer Abbrechen-Aktion ohne Titel: Ein Tipp außerhalb schließt es, und action ist null.
  • Android: Ein AlertDialog zeigt bis zu drei Aktionen an, die nach Position zugeordnet werden: Die letzte Aktion ist der positive Button, die davor der negative Button und die davor der neutrale Button. Ein Action Sheet ist eine Liste der Aktionen in einem Dialog, wobei ein Tipp außerhalb oder die Zurück-Taste an die Stelle der Abbrechen-Aktion tritt (action ist dann null). Der Listendialog zeigt den title oder die description, wenn das Sheet keinen Titel hat.
  • Windows, Linux, GPUI und das Web: NSH zeichnet den Alert bzw. das Action Sheet im Dialogstil der Plattform.