Progettazione di prodotti aziendali · Nuova risorsa
Sistema di design Duet.
Esamina le scale cromatiche e di spaziatura di LocalTapiola di Duet attraverso un flusso di selezione di un intervallo di date, con valori ISO, convalida esplicita dell’intervallo, metodi di gestione del focus dei componenti e un confine distinto per il selettore open source.
Interpretazione offline di HTML che usa campi data nativi e valori verificati del tema predefinito di Duet; non è il runtime del calendario Duet. · Riferimento per l’implementazione
02
Riferimento di progettazione di sistema di design Duet
Istantanea della documentazione pubblica di Duet: componenti del sistema principale, token predefiniti di LocalTapiola e integrazione documentata 10.7.0/CDN. Non è il pacchetto distinto @duetds/date-picker 1.x. Alcuni token del raggio sono ancora contrassegnati In Review.
Sistema di design Duet Il sistema principale Duet e il selettore open source sono distinti
Mantieni il contratto del pacchetto insieme all'esempio
Duet offre componenti e basi grafiche con tema per LocalTapiola e Turva. Il progetto @duetds/date-picker, pubblicato separatamente, è una distribuzione open source più circoscritta. Il fatto che condividano il nome di un tag non rende intercambiabili le proprietà, la configurazione della localizzazione o le variabili CSS con quelle dell'attuale sistema di progettazione principale.
Il codice di integrazione di questa pagina è destinato al sistema principale. L'anteprima offline usa campi data nativi e uno stile originale basato sui token Duet collegati. Mostra le regole degli intervalli senza dichiarare di eseguire il popup del calendario Duet o il suo modello di navigazione da tastiera.
Sistema di design Duet Il blu del marchio e il rosso di stato hanno funzioni diverse
Usa un tema invece di sostituire un singolo colore d'accento
Il tema predefinito di LocalTapiola abbina un'azione blu a un testo del corpo blu scuro. Turva ha una propria azione rossa e un ruolo di testo secondario. Cambiare solo il colore dell'azione non tiene conto delle altre relazioni del tema. La tabella attuale contrassegna inoltre come deprecate le vecchie tinte di Turva; copiare tutte le voci storiche della palette manterrebbe indicazioni obsolete.
Il nostro esempio originale di pianificazione delle date di viaggio usa il blu per l'azione successiva e il rosso solo quando occorre correggere il periodo selezionato. È una dimostrazione di pianificazione, non un consiglio assicurativo, un preventivo o un acquisto.
Sistema di design Duet Il testo del corpo da 16px ancora la gerarchia
La scala non richiede sempre un titolo enorme
La tabella di Duet passa per 16, 20, 24, 36, 48 e 72px ai livelli più grandi. Un pannello di pianificazione incorporato usa il livello da 24px per dare risalto all'azione e alle etichette delle date. Il livello da 72px, adatto alle dimensioni di una pagina promozionale, non è predefinito per un modulo compatto.
I pacchetti di font di LocalTapiola e Turva sono asset distinti. L'interpretazione offline usa un font di sistema alternativo e non include i file dei font del marchio. Un'applicazione autorizzata dovrebbe caricare la famiglia scelta tramite il percorso dei font documentato e poi usare i relativi token di peso.
Sistema di design Duet Usa gli incrementi effettivi da 20px e 28px
Duet non usa una scala generica di otto pixel
Oltre alle potenze di due più note, la scala include 12, 20, 28 e 36px. Questi intervalli intermedi sono importanti per riprodurre il ritmo dei moduli del sistema. Nel layout largo, lascia 20px tra i due campi e, quando li disponi in colonna, mantieni ogni etichetta insieme al relativo campo. Il breakpoint dell'esempio dipende dall'applicazione.
Gli angoli dei controlli predefiniti hanno un raggio di 4px, mentre i pulsanti usano un raggio a capsula. Alcuni valori più recenti del raggio dei contenitori sono esplicitamente contrassegnati In Review nel riferimento dei token; questa guida ne mantiene lo stato invece di presentare come approvato ogni token elencato.
Sistema di design Duet Memorizza valori ISO e descrivi il formato visualizzato
Non analizzare come dati le stringhe localizzate visualizzate
Il valore e i limiti del componente usano il formato YYYY-MM-DD. L'evento della data selezionata include sia una stringa sia un oggetto Date. Usa la stringa per i confronti e l'archiviazione; la visualizzazione localizzata nel campo riguarda la presentazione. La lingua del documento è il punto di accesso attuale per la localizzazione, mentre la vecchia proprietà language è deprecata.
L'esempio consente date solo durante il mese di giugno 2027. Questo intervallo fisso rende i test deterministici ed è indicato chiaramente come vincolo dell'esempio. In un modulo di produzione, l'intervallo consentito dovrebbe derivare dalla regola del prodotto, che andrebbe spiegata accanto al campo.
Sistema di design Duet Una data valida non implica necessariamente un intervallo valido
Verifica la relazione dopo aver convalidato ciascun campo
L'oggetto validity del componente descrive gli errori dei singoli campi. Una data di ritorno precedente alla partenza può comunque essere una data di calendario valida, quindi l'applicazione deve verificare la coppia separatamente. L'esempio nativo assegna un errore chiaro e usa setFocus(), il metodo documentato che porta il focus sul campo interno.
Il conteggio è inclusivo: se la partenza e il ritorno avvengono lo stesso giorno, il risultato è un giorno di calendario. Convertire le date ISO alla mezzanotte UTC evita che il passaggio all'ora legale trasformi un intervallo di calendario in una durata frazionaria. Questo calcolo è una logica originale dell'applicazione, non una regola di prezzo Duet.
Rifiuta gli estremi mancanti, malformati o fuori dai limiti.
Rifiuta una data di ritorno precedente a quella di partenza.
Sposta il focus sul campo da correggere.
Calcola l'intervallo inclusivo solo dopo aver superato entrambi i controlli.
Sistema di design Duet L'azione principale non implica l'invio
Duet usa una proprietà esplicita per l'invio
Il pulsante del sistema principale attiva l’invio del modulo con submit; il valore predefinito è false. La composizione fornita usa un’azione click che prepara un risultato locale, quindi non ha bisogno di questa proprietà. La destinazione va specificata in url, che imposta la semantica di un’ancora.
L’anteprima cancella il messaggio preparato ogni volta che cambia uno dei due campi. Altrimenti il messaggio potrebbe sembrare confermare valori che il visitatore ha già sostituito. Non viene mostrato alcuno spinner perché non ci sono operazioni asincrone.
Usa una sola azione primaria di preparazione.
Specifica che il risultato è locale.
Non riutilizzare un messaggio di successo per far intendere che sia stata creata una polizza.
Sistema di design Duet Fissa gli asset del sistema principale come insieme compatibile
L’esempio è uno snapshot documentato, non una promessa di usare la versione più recente
La pagina di utilizzo esaminata fornisce i componenti 10.7.0 con CSS 5.1.4; gli snapshot dell’indice di ricerca menzionano già versioni successive. L’esempio mantiene intenzionalmente insieme la coppia esaminata direttamente. Per l’adozione in produzione, scegli una release e verifica la corrispondenza di CSS, dei font e del comportamento dei componenti.
I campi data sono elementi personalizzati. Attendi che vengano definiti prima di chiamarne i metodi, associa gli ascoltatori a duetChange e leggi il payload documentato invece di presupporre un evento change nativo. Non combinare nella stessa pagina il modulo CDN del sistema principale con il selettore autonomo: entrambi definiscono lo stesso tag.
Sistema di design Duet Esempi di componenti del sistema di progettazione
Esempio interattivo completo e autonomo
Salva l’intero documento come index.html e aprilo in un browser. Interpretazione di HTML offline con campi data nativi e valori verificati del tema predefinito Duet; non è il runtime del calendario 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>
Questo documento usa controlli data nativi del browser. L’esempio Duet separato usa il selettore del sistema principale; non va confuso con il pacchetto autonomo open source del selettore data.
Convalida una coppia di selettori data del sistema principale
Due campi con etichette, date di giugno con limiti, estremi in ordine, focus sul selettore non valido e conteggio inclusivo dei giorni.
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>
Usa @duetds/components tramite il CDN del sistema principale, non @duetds/date-picker 1.x.
Gli intervalli che comprendono un solo giorno contengono un giorno di calendario, estremi inclusi.
Il calcolo in UTC evita gli scarti dovuti all’ora legale.
04
Sistema di design Duet Configurazione dell’agente AI
Punto di partenza per l’implementazione
Composizione completa tramite CDN del sistema principale, con le versioni indicate esplicitamente nella pagina di integrazione esaminata. Gli snapshot pubblici della ricerca mostrano anche versioni più recenti; fissa una release compatibile invece di presumere che questa sia la più recente. I font non sono ridistribuiti qui.
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 per il tuo progetto
Prompt per l’agente
Crea un intervallo di date Duet del sistema principale usando due selettori data con etichette, valori ISO e controlli di validità. Convalida separatamente l’ordine degli estremi, chiama setFocus in caso di errori e usa un’azione primaria esplicita per la preparazione locale. Non includere nella stessa pagina il pacchetto del selettore autonomo.
05
Sistema di design Duet Fonti e ambito
Riferimento indipendente a OpenDesign. Pianificatore originale; non vengono create polizze, prenotazioni né preventivi. Duet del sistema principale e il suo selettore data open source separato hanno contratti diversi.