Block Kit

Sur cette page

Le Block Kit d’EmDash permet aux plugins sandboxés de décrire leur interface d’administration sous forme de JSON. L’hôte effectue le rendu des blocs — aucun JavaScript fourni par le plugin ne s’exécute dans le navigateur.

Comment ça fonctionne

  1. L’utilisateur navigue vers la page d’administration d’un plugin.
  2. L’admin envoie une interaction page_load à la route d’administration du plugin.
  3. Le plugin renvoie une BlockResponse contenant un tableau de blocs.
  4. L’admin effectue le rendu des blocs à l’aide du composant BlockRenderer.
  5. Lorsque l’utilisateur interagit (clique sur un bouton, soumet un formulaire), l’admin renvoie l’interaction au plugin.
  6. Le plugin renvoie de nouveaux blocs et le cycle se répète.
import { definePlugin } from "emdash";
import type { PluginContext } from "emdash";

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

export default definePlugin({
	routes: {
		admin: {
			handler: async (routeCtx, ctx: PluginContext) => {
				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: [] };
			},
		},
	},
});

Le gestionnaire de route au format standard prend deux arguments : routeCtx (avec input, request, requestMeta) et ctx (le PluginContext).

Types de blocs

TypeDescription
headerGrand titre en gras
sectionTexte avec élément accessoire optionnel
dividerLigne horizontale
fieldsGrille étiquette/valeur à deux colonnes
tableTableau de données avec formatage, tri, pagination
actionsRangée horizontale de boutons et de contrôles
statsCartes de métriques de tableau de bord avec indicateurs de tendance
formChamps de saisie avec visibilité conditionnelle et soumission
imageImage au niveau du bloc avec légende
contextPetit texte d’aide atténué
columnsMise en page à 2–3 colonnes avec blocs imbriqués
emptyEspace réservé d’état vide avec icône, titre, description, ligne de commande optionnelle et boutons d’action
accordionSection réductible enveloppant des blocs imbriqués

Types d’éléments

TypeDescription
buttonBouton d’action avec dialogue de confirmation optionnel
text_inputSaisie de texte sur une ou plusieurs lignes
number_inputSaisie numérique avec min/max
selectSélection déroulante
toggleInterrupteur marche/arrêt
secret_inputSaisie masquée pour clés API et jetons

Assistants de construction

Le package @emdash-cms/blocks exporte des assistants de construction pour un code plus propre :

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" },
		}),
	],
};

Champs conditionnels

Les champs de formulaire peuvent être affichés conditionnellement en fonction des valeurs d’autres champs :

{
	"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 }
}

Le champ api_key n’apparaît que lorsque auth_enabled est activé. Les conditions sont évaluées côté client sans aller-retour.

Essayez-le

Utilisez le Block Playground pour construire et tester des mises en page de blocs de manière interactive.