Design de produits d’entreprise · Nouvelle ressource
Système de design Duet.
Étudiez les échelles de couleurs et d’espacement de Duet et LocalTapiola à travers un parcours de sélection de dates, avec valeurs de date ISO, validation explicite de la plage, méthodes de focus du composant et distinction claire avec le sélecteur open source.
Interprétation hors ligne de HTML à l’aide de champs de date natifs et de valeurs vérifiées du thème Duet par défaut ; il ne s’agit pas de l’environnement d’exécution du calendrier Duet. · Référence de mise en œuvre
02
Système de design Duet Référence de conception
Instantané de la documentation publique Duet : composants du système principal, jetons par défaut de LocalTapiola et intégration documentée avec la version 10.7.0/le CDN. Il ne s’agit pas du package distinct @duetds/date-picker 1.x. Certains jetons de rayon sont toujours indiqués comme étant en cours d’évaluation.
Système de design Duet Le système principal Duet et le sélecteur open source sont distincts
Associez le contrat du package à l’exemple
Duet propose à LocalTapiola et à Turva des composants thématisés et des fondations. Le projet @duetds/date-picker, publié séparément, est une distribution open source plus ciblée. Le fait qu’ils partagent un nom de balise ne rend pas leurs propriétés, leur configuration de localisation ni leurs variables CSS interchangeables avec celles du système de design principal actuel.
Le code d’intégration de cette page cible le système principal. Son aperçu hors ligne utilise des champs de date natifs et un style d’origine fondé sur les jetons Duet associés. Il illustre les règles de sélection d’une période sans prétendre exécuter la fenêtre contextuelle du calendrier Duet ni reproduire son modèle de navigation au clavier.
Système de design Duet Le bleu de marque et le rouge d’état ont des rôles distincts
Utilisez un thème au lieu de remplacer une seule couleur d’accentuation
Le thème LocalTapiola par défaut associe une action bleue à un texte courant bleu foncé. Turva possède sa propre action rouge et un rôle de texte secondaire. Remplacer uniquement la couleur de l’action ne préserverait pas les autres relations du thème. Le tableau actuel indique également que les anciennes teintes Turva sont obsolètes ; reprendre toutes les entrées historiques de la palette perpétuerait des indications dépassées.
Notre spécimen original de dates de voyage utilise le bleu pour l’action suivante et le rouge uniquement lorsqu’une période choisie doit être corrigée. Il s’agit d’une démonstration de planification, et non d’une recommandation d’assurance, d’un devis ou d’un achat.
Système de design Duet Le texte courant de 16px structure la hiérarchie
Il n’est pas nécessaire d’utiliser partout un titre immense
L’échelle Duet passe par 16, 20, 24, 36, 48 et 72px pour les niveaux les plus grands. Un panneau de planification intégré utilise le niveau de 24px afin de mettre en évidence l’action et les libellés des dates. La taille de 72px, conçue pour le marketing, n’est pas adaptée par défaut à un formulaire compact.
Les packages de polices LocalTapiola et Turva sont des ressources distinctes. L’interprétation hors ligne utilise une police système de remplacement ; elle n’inclut pas les fichiers de polices de ces marques. Une application autorisée doit charger la famille choisie en suivant la méthode documentée, puis utiliser les jetons de graisse correspondants.
Système de design Duet Utilisez les valeurs réelles de 20px et 28px
Duet ne suit pas une échelle générique de huit pixels
Outre les puissances de deux habituelles, l’échelle comprend 12, 20, 28 et 36px. Ces intervalles intermédiaires sont importants pour respecter le rythme des formulaires du système. Dans la mise en page large, prévoyez un espacement de 20px entre les deux champs et, lorsque vous les empilez, gardez chaque libellé associé à son champ. Le seuil de rupture du spécimen relève du choix de l’application.
Les contrôles par défaut ont des coins de 4px, tandis que les boutons utilisent un rayon en forme de pilule. Certaines valeurs de rayon de conteneur plus récentes dans la référence des jetons sont explicitement indiquées comme étant en cours d’évaluation. Ce guide conserve cette mention au lieu de présenter tous les jetons répertoriés comme approuvés.
Système de design Duet Stockez les valeurs ISO et décrivez le format affiché
Ne traitez pas les chaînes localisées affichées comme des données
La valeur et les limites du composant utilisent le format YYYY-MM-DD. Son événement de date sélectionnée contient une chaîne et un objet Date. Conservez la chaîne pour les comparaisons et le stockage ; l’affichage localisé du champ relève de la présentation. La langue du document est le point d’entrée actuel de la localisation, tandis que l’ancienne propriété language est obsolète.
L’exemple autorise uniquement les dates de juin 2027. Cet intervalle fixe rend les tests déterministes et constitue clairement une contrainte du spécimen. Dans un formulaire de production, l’intervalle autorisé serait défini selon les règles du produit, lesquelles seraient expliquées à côté du champ.
Système de design Duet Une date valide ne garantit pas une période valide
Vérifiez la relation entre les champs dès que chacun est valide
L’objet de validité du composant décrit les erreurs de chaque champ. Une date de retour antérieure à la date de départ peut être une date valide du calendrier ; l’application doit donc vérifier séparément la paire. L’exemple natif affiche un message d’erreur explicite et utilise setFocus(), la méthode documentée qui place le focus sur le champ de saisie interne.
Le décompte inclut les deux bornes : un départ et un retour le même jour correspondent à une journée calendaire. Convertir les dates ISO à minuit UTC évite qu’un changement d’heure transforme un intervalle calendaire en durée fractionnaire. Ce calcul relève de la logique applicative d’origine, et non d’une règle tarifaire Duet.
Rejetez les bornes manquantes, mal formées ou hors limites.
Rejetez une date de retour antérieure à la date de départ.
Placez le focus sur le champ à corriger.
Calculez la période, bornes incluses, uniquement après la réussite des deux vérifications.
Système de design Duet L’action principale ne vaut pas soumission
Duet utilise une propriété de soumission explicite
Le bouton du système principal active l’envoi du formulaire avec submit ; cette option est désactivée par défaut. La composition fournie utilise une action au clic qui prépare un résultat local : cette propriété est donc inutile. Pour définir une destination, utilisez url, qui confère au bouton la sémantique d’un lien.
L’aperçu efface le message préparé dès que l’un des champs change. Sinon, le message pourrait sembler confirmer des valeurs que la personne a déjà remplacées. Aucun indicateur de chargement n’est affiché, car aucune opération asynchrone n’a lieu.
Utilisez une seule action principale pour préparer le résultat.
Précisez que le résultat est local.
Ne réutilisez pas une formulation de réussite qui laisserait entendre qu’une police a été créée.
Système de design Duet Verrouillez les ressources du système principal en un ensemble compatible
L’exemple est un instantané documenté, pas une promesse de version la plus récente
La page d’utilisation consultée indique les composants en version 10.7.0 et CSS en version 5.1.4 ; les instantanés de l’index de recherche mentionnent déjà des versions ultérieures. L’exemple conserve volontairement les versions consultées ensemble. Pour une mise en production, choisissez une version et vérifiez la compatibilité de CSS, des polices et du comportement des composants.
Les champs de date sont des éléments personnalisés. Attendez que leur définition soit chargée avant d’appeler leurs méthodes, ajoutez les écouteurs à duetChange et lisez la charge utile documentée au lieu de supposer qu’il s’agit d’un événement change natif. Ne mélangez pas le module CDN du système principal et le sélecteur autonome sur la même page : tous deux définissent la même balise.
Exemples de composants du système de design système de design Duet
Exemple interactif autonome complet
Enregistrez le document complet sous le nom index.html, puis ouvrez-le dans un navigateur. Interprétation de HTML hors ligne, à l’aide de champs de date natifs et des valeurs du thème par défaut de Duet vérifiées ; il ne s’agit pas de l’exécution du calendrier Duet.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Duet travel period interpretation</title><style>*{box-sizing:border-box}body{margin:0;background:#f0f7fa;color:#082a4d;font:16px/1.5 system-ui,sans-serif}main{max-width:1000px;margin:auto;padding:36px 28px}.eyebrow{font-size:12px;letter-spacing:2px;text-transform:uppercase;margin-bottom:12px}h1{font-size:36px;line-height:1.2;font-weight:600;margin:0 0 20px}p{margin:0 0 20px}.hero{display:grid;grid-template-columns:1fr 300px;gap:28px;align-items:center;margin-bottom:28px}.art{height:170px;position:relative;overflow:hidden;border-radius:50%;background:#c6e1ee}.sun{position:absolute;top:25px;right:60px;width:36px;height:36px;border-radius:50%;background:white}.hill{position:absolute;background:#0077b3;width:210px;height:170px;bottom:-95px;left:-10px;transform:rotate(25deg);border-radius:24px}.hill.two{left:135px;background:#00619b;bottom:-110px;transform:rotate(-25deg)}.road{position:absolute;width:150px;height:200px;border:12px solid white;border-radius:50%;top:65px;left:95px;transform:rotate(25deg)}.card{background:white;border-radius:4px;padding:28px;box-shadow:0 2px 8px #082a4d0d;display:grid;grid-template-columns:1fr 230px;gap:28px}h2{font-size:24px;line-height:1.3;margin:0 0 20px}.fields{display:grid;grid-template-columns:1fr 1fr;gap:20px}label{display:block;font-weight:600;margin-bottom:8px}input{width:100%;max-width:100%;min-width:0;border:1px solid #909599;border-radius:4px;font:inherit;color:inherit;padding:12px;background:white}input[aria-invalid=true]{border-color:#d61c52}button{background:#0077b3;color:white;border:0;border-radius:20rem;padding:12px 36px;font:600 16px/1.5 system-ui;cursor:pointer}button:hover{background:#004b81}button:focus-visible,input:focus-visible{outline:3px solid #082a4d;outline-offset:3px}.error{font-size:14px;color:#d61c52;min-height:24px;margin:8px 0 20px}.calendar{background:#f0f7fa;border-radius:4px;padding:20px}.calendar strong{display:block;margin-bottom:12px}.grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;font-size:12px;text-align:center}.grid span{padding:3px 0}.grid .in-range{background:#c6e1ee}.grid .endpoint{background:#0077b3;color:white;border-radius:50%}.caption{font-size:12px;margin:12px 0 0}.result{margin-top:20px;background:#e4f1f7;padding:20px;border-radius:4px}.result:empty{display:none}.boundary{font-size:12px;margin-top:28px}.hint{font-size:14px}@media(max-width:650px){main{padding:24px 16px}.hero{grid-template-columns:1fr}.art{display:none}h1{font-size:28px}.card{grid-template-columns:1fr;padding:20px}.fields{grid-template-columns:1fr;gap:16px}.calendar{max-width:300px;width:100%}button{width:100%;padding:12px 20px}}
</style><main><div class="hero"><div><div class="eyebrow">Travel period planner</div><h1>Make time for a change of scenery.</h1><p>Choose a departure and return date to explore an inclusive calendar-day count.</p></div><div class="art" aria-hidden="true"><div class="sun"></div><div class="hill"></div><div class="hill two"></div><div class="road"></div></div></div><div class="card"><section><h2>When will you travel?</h2><p class="hint" id="hint">Use dates from 1–30 June 2027. This fixed month is for demonstration.</p><form novalidate><div class="fields"><div><label for="start">Departure</label><input id="start" type="date" min="2027-06-01" max="2027-06-30" value="2027-06-10" required aria-describedby="hint error"></div><div><label for="end">Return</label><input id="end" type="date" min="2027-06-01" max="2027-06-30" value="2027-06-17" required aria-describedby="hint error"></div></div><div class="error" id="error" role="alert"></div><button type="submit">Prepare date range</button></form></section><aside class="calendar"><strong>June 2027</strong><div class="grid" id="calendar" aria-hidden="true"></div><p class="caption" id="range-caption">10–17 June selected</p></aside></div><div class="result" id="result" role="status"></div><p class="boundary">Independent HTML interpretation of Duet tokens with native date fields. The calendar image is a non-interactive range overview. No insurance quote, booking or policy is created.</p></main><script>const start=document.querySelector('#start'),end=document.querySelector('#end'),result=document.querySelector('#result'),error=document.querySelector('#error');function valid(){return start.validity.valid&&end.validity.valid&&start.value&&end.value&&end.value>=start.value}function draw(){let days=['M','T','W','T','F','S','S'].map(d=>'<span>'+d+'</span>').join('')+'<span></span>';for(let i=1;i<=30;i++){let iso='2027-06-'+String(i).padStart(2,'0'),range=valid()&&iso>=start.value&&iso<=end.value,edge=range&&(iso===start.value||iso===end.value);days+='<span class="'+(edge?'endpoint':range?'in-range':'')+'">'+i+'</span>'}document.querySelector('#calendar').innerHTML=days;document.querySelector('#range-caption').textContent=valid()?start.value+' to '+end.value:'Choose a valid range to highlight it.'}function changed(){result.textContent='';error.textContent='';start.removeAttribute('aria-invalid');end.removeAttribute('aria-invalid');draw()}[start,end].forEach(el=>el.oninput=changed);document.querySelector('form').onsubmit=e=>{e.preventDefault();let bad;if(!start.value||!start.validity.valid){error.textContent='Choose a departure date in June 2027.';bad=start}else if(!end.value||!end.validity.valid){error.textContent='Choose a return date in June 2027.';bad=end}else if(end.value<start.value){error.textContent='Return must be on or after departure.';bad=end}if(bad){bad.setAttribute('aria-invalid','true');bad.focus();result.textContent='';return}const days=(Date.parse(end.value+'T00:00:00Z')-Date.parse(start.value+'T00:00:00Z'))/86400000+1;result.textContent=days+' calendar '+(days===1?'day':'days')+', including departure and return. Local draft: '+start.value+' to '+end.value+'. No policy created.'};draw();</script></html>
Ce document utilise les contrôles de date natifs du navigateur. L’exemple Duet distinct utilise le sélecteur du système principal ; il ne faut pas le confondre avec le package autonome open source de sélecteur de date.
Valider une paire de sélecteurs de date du système principal
Deux champs avec libellés, des dates de juin limitées, des dates de début et de fin dans le bon ordre, le focus sur le sélecteur invalide et le décompte inclusif des jours.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Date range draft</title>
<link rel="stylesheet" href="https://cdn.duetds.com/api/css/5.1.4/lib/duet.min.css">
<script type="module" src="https://cdn.duetds.com/api/components/10.7.0/lib/duet/duet.esm.js"></script>
<style>main{max-width:680px;margin:auto;padding:28px}.range{display:grid;grid-template-columns:1fr 1fr;gap:20px}@media(max-width:576px){.range{grid-template-columns:1fr}}</style>
<main><h1>Choose a travel period</h1><p>Demonstration only. No insurance is quoted or purchased.</p><div class="range">
<duet-date-picker id="start" label="Departure" required expand value="2027-06-10" min="2027-06-01" max="2027-06-30"></duet-date-picker>
<duet-date-picker id="end" label="Return" required expand value="2027-06-17" min="2027-06-01" max="2027-06-30"></duet-date-picker></div>
<duet-button id="prepare" variation="primary">Prepare date range</duet-button>
<p id="result" role="status"></p></main><script type="module">
await customElements.whenDefined('duet-date-picker');
const start=document.querySelector('#start'),end=document.querySelector('#end'),result=document.querySelector('#result');
function error(picker){const v=picker.validity;if(!picker.value)return 'Choose a date.';if(v&&!v.valid)return 'Choose a valid date in June 2027.';return '';}
function validate(){start.error=error(start);end.error=error(end);if(!start.error&&!end.error&&end.value<start.value)end.error='Return must be on or after departure.';return !start.error&&!end.error;}
[start,end].forEach(p=>p.addEventListener('duetChange',()=>{result.textContent='';validate()}));
document.querySelector('#prepare').addEventListener('click',async()=>{if(!validate()){await(start.error?start:end).setFocus();return;}const a=Date.parse(start.value+'T00:00:00Z'),b=Date.parse(end.value+'T00:00:00Z');result.textContent=`Local range: ${start.value} to ${end.value}, ${(b-a)/86400000+1} calendar days inclusive. No policy created.`;});
</script></html>
Cet exemple utilise @duetds/components via le CDN du système principal, et non @duetds/date-picker 1.x.
Une période allant d’un jour à l’autre compte un jour calendaire inclusif.
Le calcul en UTC évite les décalages liés à l’heure d’été.
04
Configuration de l’agent système de design Duet
Point de départ de l’implémentation
Composition complète via le CDN du système principal, utilisant les versions explicitement indiquées sur la page d’intégration consultée. Les instantanés publics des résultats de recherche montrent aussi des versions plus récentes ; verrouillez une version compatible au lieu de supposer qu’il s’agit de la dernière. Les polices ne sont pas redistribuées ici.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Date range draft</title>
<link rel="stylesheet" href="https://cdn.duetds.com/api/css/5.1.4/lib/duet.min.css">
<script type="module" src="https://cdn.duetds.com/api/components/10.7.0/lib/duet/duet.esm.js"></script>
<style>main{max-width:680px;margin:auto;padding:28px}.range{display:grid;grid-template-columns:1fr 1fr;gap:20px}@media(max-width:576px){.range{grid-template-columns:1fr}}</style>
<main><h1>Choose a travel period</h1><p>Demonstration only. No insurance is quoted or purchased.</p><div class="range">
<duet-date-picker id="start" label="Departure" required expand value="2027-06-10" min="2027-06-01" max="2027-06-30"></duet-date-picker>
<duet-date-picker id="end" label="Return" required expand value="2027-06-17" min="2027-06-01" max="2027-06-30"></duet-date-picker></div>
<duet-button id="prepare" variation="primary">Prepare date range</duet-button>
<p id="result" role="status"></p></main><script type="module">
await customElements.whenDefined('duet-date-picker');
const start=document.querySelector('#start'),end=document.querySelector('#end'),result=document.querySelector('#result');
function error(picker){const v=picker.validity;if(!picker.value)return 'Choose a date.';if(v&&!v.valid)return 'Choose a valid date in June 2027.';return '';}
function validate(){start.error=error(start);end.error=error(end);if(!start.error&&!end.error&&end.value<start.value)end.error='Return must be on or after departure.';return !start.error&&!end.error;}
[start,end].forEach(p=>p.addEventListener('duetChange',()=>{result.textContent='';validate()}));
document.querySelector('#prepare').addEventListener('click',async()=>{if(!validate()){await(start.error?start:end).setFocus();return;}const a=Date.parse(start.value+'T00:00:00Z'),b=Date.parse(end.value+'T00:00:00Z');result.textContent=`Local range: ${start.value} to ${end.value}, ${(b-a)/86400000+1} calendar days inclusive. No policy created.`;});
</script></html>
Un prompt pour votre projet
Prompt pour l’agent IA
Créez une période avec le sélecteur de date du système principal Duet, à l’aide de deux sélecteurs avec libellés, de valeurs ISO et de contrôles de validité. Vérifiez séparément l’ordre des dates de début et de fin, appelez setFocus en cas d’erreur et utilisez une action principale explicite pour préparer le résultat local. N’incluez pas le package autonome de sélecteur sur la même page.
05
Sources et périmètre système de design Duet
Référence indépendante à OpenDesign. Planificateur original ; aucune police, réservation ni estimation n’est créée. Le système principal Duet et son sélecteur de date open source distinct ont des contrats différents.