Block Kit

Auf dieser Seite

EmDashs Block Kit ermöglicht es sandboxed Plugins, ihre Admin-Oberfläche als JSON zu beschreiben. Der Host rendert die Blöcke – es wird nie vom Plugin bereitgestelltes JavaScript im Browser ausgeführt.

Funktionsweise

  1. Der Benutzer navigiert zur Admin-Seite eines Plugins.
  2. Der Admin sendet eine page_load-Interaktion an die Admin-Route des Plugins.
  3. Das Plugin gibt eine BlockResponse zurück, die ein Array von Blöcken enthält.
  4. Der Admin rendert die Blöcke mithilfe der BlockRenderer-Komponente.
  5. Wenn der Benutzer interagiert (einen Button klickt, ein Formular absendet), sendet der Admin die Interaktion zurück an das Plugin.
  6. Das Plugin gibt neue Blöcke zurück, und der Zyklus wiederholt sich.
import type { SandboxedPlugin } from "emdash/plugin";

interface BlockInteraction {
	type: "page_load" | "block_action" | "form_submit";
	page?: string;
	action_id?: string;
	values?: Record<string, unknown>;
}

export default {
	routes: {
		admin: {
			handler: async (routeCtx, ctx) => {
				const interaction = routeCtx.input as BlockInteraction;

				if (interaction.type === "page_load") {
					return {
						blocks: [
							{ type: "header", text: "My Plugin Settings" },
							{
								type: "form",
								block_id: "settings",
								fields: [
									{ type: "text_input", action_id: "api_url", label: "API URL" },
									{ type: "toggle", action_id: "enabled", label: "Enabled", initial_value: true },
								],
								submit: { label: "Save", action_id: "save" },
							},
						],
					};
				}

				if (interaction.type === "form_submit" && interaction.action_id === "save") {
					await ctx.kv.set("settings", interaction.values);
					return {
						blocks: [/* ... updated blocks ... */],
						toast: { message: "Settings saved", type: "success" },
					};
				}

				return { blocks: [] };
			},
		},
	},
} satisfies SandboxedPlugin;

Der Route-Handler nimmt zwei Argumente entgegen: routeCtx (mit input, request, requestMeta) und ctx (der PluginContext). satisfies SandboxedPlugin leitet beide ab.

Block-Typen

TypBeschreibung
headerGroße fette Überschrift
sectionText mit optionalem Accessory-Element
dividerHorizontale Trennlinie
fieldsZweispaltiges Label/Wert-Raster
tableDatentabelle mit Formatierung, Sortierung, Paginierung
actionsHorizontale Reihe von Buttons und Steuerelementen
statsDashboard-Metrik-Karten mit Trendindikatoren
formEingabefelder mit bedingter Sichtbarkeit und Submit
imageBlock-Level-Bild mit Bildunterschrift
contextKleiner gedämpfter Hilfetext
columns2–3 Spalten-Layout mit verschachtelten Blöcken
emptyLeerzustand-Platzhalter mit Icon, Titel, Beschreibung, optionaler Befehlszeile und Action-Buttons
accordionEinklappbarer Bereich, der verschachtelte Blöcke umschließt

Element-Typen

TypBeschreibung
buttonAction-Button mit optionalem Bestätigungsdialog
text_inputEinzeiliges oder mehrzeiliges Texteingabefeld
number_inputNumerisches Eingabefeld mit Min/Max
selectDropdown-Auswahl
toggleEin/Aus-Schalter
secret_inputMaskiertes Eingabefeld für API-Keys und Tokens

Builder-Helfer

Das Paket @emdash-cms/blocks exportiert Builder-Helfer für saubereren Code:

import { blocks, elements } from "@emdash-cms/blocks";

const { header, form, section, stats } = blocks;
const { textInput, toggle, select, button } = elements;

return {
	blocks: [
		header("SEO Settings"),
		form({
			blockId: "settings",
			fields: [
				textInput("site_title", "Site Title", { initialValue: "My Site" }),
				toggle("generate_sitemap", "Generate Sitemap", { initialValue: true }),
				select("robots", "Default Robots", [
					{ label: "Index, Follow", value: "index,follow" },
					{ label: "No Index", value: "noindex,follow" },
				]),
			],
			submit: { label: "Save", actionId: "save" },
		}),
	],
};

Bedingte Felder

Formularfelder können basierend auf anderen Feldwerten bedingt angezeigt werden:

{
	"type": "toggle",
	"action_id": "auth_enabled",
	"label": "Enable Authentication"
}
{
	"type": "secret_input",
	"action_id": "api_key",
	"label": "API Key",
	"condition": { "field": "auth_enabled", "eq": true }
}

Das api_key-Feld erscheint nur, wenn auth_enabled aktiviert ist. Bedingungen werden clientseitig ohne Round-Trip ausgewertet.

Ausprobieren

Verwenden Sie den Block Playground, um Block-Layouts interaktiv zu erstellen und zu testen.