Rédigez une notification avec le thème et les conventions de boutons de Paste, une échelle d’espacement vérifiée et une distinction claire entre la modification, la révision et l’envoi effectif d’un message.
Interprétation hors ligne HTML des échelles Paste officielles et des règles d’état des boutons ; ni l’environnement d’exécution natif ni un service de messagerie. · Référence de mise en œuvre
02
Référence de conception du système de design Twilio Paste
Source amont twilio-labs/paste vérifiée. Les valeurs ci-dessous distinguent les noms des jetons YAML de leurs noms au format JavaScript. Cette référence ne présente pas le fork indépendant Paste DSys comme une documentation Twilio.
Système de design Twilio Paste : utilisez le système officiel sans confondre la documentation avec sa version dérivée
Source Twilio et continuation indépendante
Paste est publié dans le dépôt twilio-labs. Lors de la vérification, les anciennes routes de documentation de paste.twilio.design redirigeaient vers ce dépôt. Le site Paste DSys, hébergé séparément, se présente comme un fork indépendant sans affiliation avec Twilio. Ce guide s’appuie donc sur les fichiers sources officiels pour les valeurs des jetons et le comportement des composants.
Un composeur de notifications constitue un exemple utile, car il met en évidence plusieurs états qu’une galerie statique de boutons ne peut pas illustrer : contenu modifiable, confirmation après examen, instantané préparé et séparation nette avant l’envoi. Cet aperçu ne fait appel à aucun API Twilio.
Système de design Twilio Paste : consultez l’échelle d’espacement avant de choisir un suffixe
Les nombres des jetons sont des noms, pas des valeurs en pixels
space30 correspond à un demi-rem, tandis que space70 correspond à un rem et demi. Les suffixes 30 et 70 désignent des positions dans l’échelle, et non 30px et 70px. Avec une racine de 16px, le composeur peut utiliser 8px entre le libellé et le champ, 12px à l’intérieur d’une commande et 24px entre les zones.
La source YAML utilise des noms avec des traits d’union. Le tableau de référence présente les noms au format JavaScript utilisés par les utilisateurs de Paste et indique les valeurs résolues à côté. Une valeur exprimée en rem varie en fonction de la taille de police de la racine ; son équivalent en pixels ne doit pas être considéré comme une mesure inconditionnelle dans le navigateur.
Système de design Twilio Paste : associer les tailles de police à des jetons de hauteur de ligne distincts
L’échelle n’implique pas que les valeurs numériques soient identiques
Les alias de taille de police et de hauteur de ligne sont distincts. fontSize30 vaut 14px avec la taille de police racine par défaut, et lineHeight30 vaut 20px. fontSize70 vaut 24px, avec une option de hauteur de ligne de 32px. Ces associations assurent la lisibilité des libellés et du contenu multiligne, sans transformer chaque section en grand titre promotionnel.
L’exemple intégré utilise une pile de polices sans empattement système et une illustration de téléphone propre à l’application. Ces choix sont explicitement illustratifs. Aucun fichier de police propriétaire n’est redistribué et les dimensions du cadre du téléphone ne sont pas présentées comme des jetons Paste.
Système de design Twilio Paste : les rôles de texte sémantiques incluent des contraintes de contraste
Un texte atténué n’est pas la même chose qu’un texte désactivé
La source de couleurs en amont consigne les associations de contraste avec les rôles. Le texte principal, le texte secondaire, les erreurs et les messages de réussite ont chacun un rôle de premier plan prévu à cet effet. Le rôle de texte le moins contrasté s’accompagne d’un avertissement déconseillant son utilisation pour les commandes actives ordinaires. Un compteur de caractères atténué ne doit pas simplement utiliser le gris le plus pâle disponible.
Dans l’exemple, le bleu indique une action et le texte neutre foncé porte le message. Le brouillon préparé ne devient pas vert simplement parce que l’utilisateur a appuyé sur un bouton : son statut indique qu’un instantané local a été créé. Les valeurs de l’exemple sont liées à la palette indiquée ; les autres variantes de thème peuvent produire des valeurs différentes.
Système de design Twilio Paste : le changement de thème est une modification d’état explicite
Variantes du fournisseur et surfaces de l’application
Theme exporte un Provider et un Consumer, ainsi que des objets de thème nommés et des utilitaires. Les constantes de variantes actuelles comprennent default, dark, twilio, twilio-dark, sendgrid et evergreen. L’exemple ne bascule volontairement qu’entre default et dark.
Les commandes natives propres à l’application nécessitent un traitement de surface adapté lorsque le fournisseur change. Un fournisseur peut appliquer un thème aux composants Paste, mais ne peut pas restyler automatiquement tous les widgets externes. Le code fourni définit explicitement les couleurs de premier plan et d’arrière-plan de l’élément englobant, et précise que la zone de texte appartient à l’application.
Système de design Twilio Paste : utiliser l’état enfoncé uniquement avec une famille de boutons compatible
Les actions, la navigation et les opérations en attente répondent à des règles différentes
L’implémentation de Button valide certaines combinaisons de propriétés. Le bouton de changement de thème utilise secondary avec pressed. Le bouton d’action du formulaire définit type="submit", car le composant est de type button par défaut. Un bouton prenant la forme d’un lien nécessite href et ne peut pas être traité comme une action désactivée ou en cours de chargement.
Utilisez primary pour préparer le brouillon et secondary pour le changement de thème indépendant.
Conservez la navigation sous forme de lien ; n’ajoutez pas href à un bouton sans utiliser la forme correspondante pour un lien.
Réservez loading aux véritables opérations en attente, car cet état modifie à la fois le comportement occupé et désactivé.
Évitez les valeurs positives de tabIndex ; l’implémentation limite les valeurs prises en charge à 0 et -1.
Système de design Twilio Paste : séparer le texte modifiable de l’instantané vérifié
Une séquence fidèle à la réalité
L’aperçu en direct suit la valeur actuelle de la zone de texte. Le contenu préparé est stocké séparément et ne change qu’après validation. Une nouvelle modification ne doit pas réécrire discrètement l’instantané précédemment préparé. La case de vérification est une interaction locale, et ne prouve ni le consentement d’un destinataire ni la conformité légale.
Saisissez le contenu dans la zone de texte associée à un libellé.
Vérifiez le message actuel et cochez la case de vérification locale.
Préparez un instantané sans appeler de service de messagerie.
Modifiez de nouveau le texte et comparez le brouillon au contenu préparé avant de créer un nouvel instantané.
Système de design Twilio Paste : rendre les retours compréhensibles sans interpréter une maquette de téléphone
Les libellés et les retours textuels restent hors de l’illustration
La zone de texte comporte un libellé visible et renvoie aux descriptions du compteur et des erreurs. Le compteur est défini en points de code Unicode ; il ne prétend pas mesurer la segmentation des SMS, l’encodage ou le coût. Le résultat préparé est également affiché sous forme de texte ordinaire, hors de l’appareil illustratif.
La validation doit signaler un message vide ou l’absence de confirmation de vérification. La région de statut annonce le résultat local sans prétendre qu’un message a été envoyé. Le focus clavier reste visible sur toutes les commandes et tous les boutons natifs, y compris dans une fenêtre d’affichage étroite.
Système de design Twilio Paste : vérifier le package indépendamment de l’interprétation hors ligne
Ce que l’exemple fourni démontre
La configuration importe les véritables packages Paste Theme et Button et fournit une composition complète de React. Les commandes natives du formulaire sont indiquées comme propres à l’application, et non attribuées à un composant API dont la disponibilité n’a pas été vérifiée. La version intégrée est une interprétation hors ligne de HTML, sans dépendance à un CDN externe.
Avant toute utilisation dans un service, résolvez les dépendances entre pairs, créez l’exemple natif et ajoutez une véritable frontière de backend pour l’envoi. La réussite d’un test d’aperçu local confirme le comportement de l’éditeur, et non l’intégration d’une messagerie en production ni l’envoi par Twilio.
Système de design Twilio Paste : exemples de composants
Exemple interactif autonome complet
Enregistrez le document complet sous le nom index.html et ouvrez-le dans un navigateur. Interprétation hors ligne de HTML des échelles Paste en amont et des règles d’état des boutons ; il ne s’agit ni de l’environnement d’exécution natif ni d’un service de messagerie.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Paste notification draft studio</title><style>
*{box-sizing:border-box}body{margin:0;background:#f4f4f6;color:#121c2d;font:14px/20px Arial,sans-serif}header{background:#121c2d;color:white;padding:20px 32px;display:flex;justify-content:space-between;gap:16px}.brand{font-weight:700;letter-spacing:.02em}header small{color:#cacdd8}main{max-width:1000px;padding:32px;margin:auto}h1{font-size:28px;line-height:40px;margin:0 0 8px}h2{font-size:18px;line-height:28px;margin:0 0 16px}.intro{color:#606b85;margin:0 0 32px}.layout{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:32px}form{background:white;border:1px solid #e1e3ea;border-radius:8px;padding:24px}label{display:block;font-weight:600}textarea{width:100%;font:16px/24px Arial,sans-serif;border:1px solid #8891aa;border-radius:4px;padding:12px;margin-top:8px;resize:vertical;min-height:150px}textarea:focus,button:focus-visible,input:focus-visible{outline:3px solid #0263e0;outline-offset:3px}.count{color:#606b85;font-size:12px;line-height:20px}.review{display:flex;align-items:start;gap:8px;margin-top:24px}.review label{font-weight:400}.review input{width:16px;height:16px;accent-color:#0263e0}button{font:600 14px/20px Arial,sans-serif;cursor:pointer;border:1px solid #0263e0;border-radius:4px;padding:10px 16px;background:#0263e0;color:white}button:hover{background:#043cb5}button.secondary{background:white;color:#0263e0}.error{color:#ad1111;min-height:20px}aside{text-align:center}.phone{margin:auto;background:white;border:8px solid #121c2d;border-radius:32px;min-height:400px;padding:24px 12px;box-shadow:0 12px 32px #121c2d14}.notch{width:72px;height:5px;background:#121c2d;border-radius:8px;margin:0 auto 24px}.sender{font-size:12px;color:#606b85;padding-bottom:16px;border-bottom:1px solid #e1e3ea}.bubble{background:#ebf4ff;border-radius:12px;padding:12px;margin-top:24px;text-align:left;white-space:pre-wrap;overflow-wrap:anywhere;min-height:70px}.caption{font-size:12px;color:#606b85}.prepared{padding:24px;background:#fff;border:1px solid #e1e3ea;border-radius:8px;margin-top:24px}.prepared p{white-space:pre-wrap;overflow-wrap:anywhere}.status{color:#606b85;font-size:12px}.foot{font-size:12px;color:#606b85;margin-top:24px}@media(max-width:650px){header{padding:16px}main{padding:24px 16px}.layout{grid-template-columns:1fr}.phone{max-width:250px;min-height:300px}form{padding:20px}.intro{margin-bottom:24px}}
</style><header><span class="brand">Paste / Message studio</span><small>Local preview</small></header><main><h1>Notification draft</h1><p class="intro">Write the message. Review the copy. Keep a prepared version.</p><div class="layout"><div><form id="composer" novalidate><h2>Compose your message</h2><label for="message">Message</label><textarea id="message" aria-describedby="count error">Your appointment is confirmed for Thursday at 10:00.</textarea><p id="count" class="count"></p><div class="review"><input id="reviewed" type="checkbox"><label for="reviewed">I reviewed this draft</label></div><p id="error" class="error" role="alert"></p><button>Prepare local draft</button></form><section class="prepared"><h2>Prepared copy</h2><p id="snapshot">No draft prepared yet.</p><p class="status" id="status" role="status">Nothing has been sent.</p></section></div><aside><div class="phone" aria-label="Illustrative phone preview"><div class="notch"></div><div class="sender">Sample service · Preview</div><div class="bubble" id="bubble"></div></div><p class="caption">Live preview of the editable message</p></aside></div><p class="foot">HTML interpretation of upstream Paste · Counts Unicode code points, not SMS segments · No messaging connection</p></main><script>
const $=id=>document.getElementById(id);function update(){$('bubble').textContent=$('message').value||'Your message will appear here.';$('count').textContent=Array.from($('message').value).length+' Unicode code points. Not an SMS segment estimate.'}$('message').oninput=()=>{update();$('reviewed').checked=false};$('composer').onsubmit=e=>{e.preventDefault();$('error').textContent='';$('message').removeAttribute('aria-invalid');if(!$('message').value.trim()){$('error').textContent='Write a message before preparing a draft.';$('message').setAttribute('aria-invalid','true');$('message').focus();return}if(!$('reviewed').checked){$('error').textContent='Confirm that you reviewed the message.';$('reviewed').focus();return}$('snapshot').textContent=$('message').value.trim();$('status').textContent='Draft prepared locally. Nothing was sent.'};update();
</script></html>
Le panneau du téléphone affiche un instantané du brouillon. Aucun SMS n’est envoyé ; le comportement natif de Paste Theme et Button nécessite l’exemple distinct React.
Un brouillon local avec le véritable thème Paste et l’état de bouton
Theme.Provider englobe l’ensemble du compositeur. L’état secondary pressed modifie le thème de l’aperçu ; un bouton d’envoi primary prépare un instantané après validation par l’application. Le libellé, la zone de texte et la case à cocher sont explicitement des commandes natives de l’application.
jsx
// npm install @twilio-paste/button @twilio-paste/theme react react-dom
import React, {useState} from 'react';
import {createRoot} from 'react-dom/client';
import {Theme} from '@twilio-paste/theme';
import {Button} from '@twilio-paste/button';
// Native textarea and labels are application-owned; this is not Paste TextArea.
function Composer() {
const [message,setMessage] = useState('Your appointment is confirmed for Thursday at 10:00.');
const [snapshot,setSnapshot] = useState('');
const [error,setError] = useState('');
const [confirmed,setConfirmed] = useState(false);
const [mode,setMode] = useState('default');
const length = Array.from(message).length;
const background = mode === 'dark' ? '#121c2d' : '#ffffff';
const foreground = mode === 'dark' ? '#ffffff' : '#121c2d';
function prepare(event) {
event.preventDefault();
if (!message.trim()) return setError('Write a message before preparing a draft.');
if (!confirmed) return setError('Confirm that you reviewed the message.');
setError(''); setSnapshot(message.trim());
}
return <Theme.Provider theme={mode}>
<main style={{padding:24,background,color:foreground,maxWidth:760,margin:'auto'}}>
<h1>Notification draft</h1>
<Button variant="secondary" pressed={mode==='dark'} onClick={() => setMode(mode==='dark'?'default':'dark')}>Dark preview</Button>
<form onSubmit={prepare}>
<label htmlFor="message" style={{display:'block',marginTop:24}}>Message</label>
<textarea id="message" rows={5} value={message} onChange={e=>{setMessage(e.target.value);setConfirmed(false);}}
aria-describedby="count error" aria-invalid={!!error}
style={{width:'100%',padding:12,margin:'8px 0',font:'inherit',borderRadius:4}} />
<p id="count">{length} Unicode code points. This is not an SMS segment estimate.</p>
<label><input type="checkbox" checked={confirmed} onChange={e=>setConfirmed(e.target.checked)} /> I reviewed this draft</label>
<p id="error" role="alert">{error}</p>
<Button variant="primary" type="submit">Prepare local draft</Button>
</form>
<section aria-label="Prepared draft" style={{marginTop:24}}>
<h2>Prepared copy</h2>
<p style={{whiteSpace:'pre-wrap'}}>{snapshot || 'No draft prepared yet.'}</p>
<p role="status">{snapshot ? 'Draft prepared locally. Nothing was sent.' : ''}</p>
</section>
</main>
</Theme.Provider>;
}
createRoot(document.getElementById('root')).render(<Composer />);
Cet exemple ne prétend délibérément pas que les commandes natives sont le composant Paste TextArea.
Le compteur de caractères dénombre les points de code Unicode, et non les segments SMS, les unités d’encodage ou l’utilisation facturable.
L’exemple du package natif est vérifié à partir des sources ; l’aperçu hors ligne HTML fait l’objet de tests distincts.
04
Configuration de l’agent IA du système de design Twilio Paste
Point de départ de l’implémentation
Utilisez l’entrée complète React ci-dessus avec un élément racine. Les packages modulaires fournissent le fournisseur natif et le bouton ; choisissez des dépendances homologues compatibles et verrouillez les versions résolues dans le fichier de verrouillage de l’application.
Créez un éditeur de brouillons de notification à l’aide de Paste Theme.Provider et Button. Conservez la sémantique de bascule secondaire à l’état enfoncé, l’espacement en rem, les rôles textuels étayés par les sources, ainsi que des états distincts pour le brouillon et l’instantané. N’inventez ni décompte de segments SMS ni résultat d’envoi.
05
Sources et périmètre du système de design Twilio Paste
Référence indépendante d’OpenDesign consacrée au projet Paste en amont. Paste DSys est un fork distinct et non affilié. Cet exemple n’envoie aucun message.