ds-tis 1.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +49 -0
- package/README.md +125 -0
- package/css/base/forced-colors.css +62 -0
- package/css/base/icons.css +73 -0
- package/css/base/index.css +4 -0
- package/css/base/reset.css +80 -0
- package/css/base/typography.css +211 -0
- package/css/components/accordion.css +153 -0
- package/css/components/alert.css +161 -0
- package/css/components/avatar.css +76 -0
- package/css/components/badge.css +83 -0
- package/css/components/breadcrumb.css +58 -0
- package/css/components/button.css +364 -0
- package/css/components/card.css +159 -0
- package/css/components/checkbox.css +296 -0
- package/css/components/combobox.css +330 -0
- package/css/components/divider.css +20 -0
- package/css/components/form-field.css +137 -0
- package/css/components/index.css +28 -0
- package/css/components/input.css +356 -0
- package/css/components/link.css +67 -0
- package/css/components/menu.css +246 -0
- package/css/components/modal.css +236 -0
- package/css/components/pagination.css +132 -0
- package/css/components/radio.css +280 -0
- package/css/components/select.css +399 -0
- package/css/components/skeleton.css +52 -0
- package/css/components/spinner.css +59 -0
- package/css/components/tabs.css +79 -0
- package/css/components/textarea.css +218 -0
- package/css/components/toggle.css +202 -0
- package/css/components/tooltip.css +116 -0
- package/css/design-system.css +13 -0
- package/css/tokens/generated/component.css +720 -0
- package/css/tokens/generated/foundation.css +282 -0
- package/css/tokens/generated/index.css +5 -0
- package/css/tokens/generated/theme-dark.css +243 -0
- package/css/tokens/generated/theme-light.css +244 -0
- package/css/tokens/index.css +6 -0
- package/css/utilities/elevation.css +24 -0
- package/css/utilities/index.css +2 -0
- package/css/utilities/layout.css +132 -0
- package/docs/agent-consumer-usage.en.md +322 -0
- package/docs/agent-consumer-usage.md +294 -0
- package/docs/api/adrs.json +186 -0
- package/docs/api/components.json +2071 -0
- package/docs/api/consumer-context.json +66 -0
- package/docs/api/foundations.json +94 -0
- package/docs/api/tokens.json +6839 -0
- package/docs/llms-full.txt +23699 -0
- package/docs/llms.txt +109 -0
- package/docs/templates/contact.html +364 -0
- package/docs/templates/dashboard.html +318 -0
- package/docs/templates/index.html +232 -0
- package/docs/templates/login.html +286 -0
- package/docs/templates/settings.html +365 -0
- package/docs/templates/signup.html +350 -0
- package/js/accordion.js +192 -0
- package/js/combobox.js +263 -0
- package/js/menu.js +301 -0
- package/js/modal.js +256 -0
- package/js/package.json +3 -0
- package/js/tabs.js +200 -0
- package/js/theme/apply.js +75 -0
- package/js/theme/brand-contrast-audit.js +133 -0
- package/js/theme/color.js +149 -0
- package/js/theme/config-schema.js +40 -0
- package/js/theme/contrast.js +76 -0
- package/js/theme/export.js +118 -0
- package/js/theme/index.js +21 -0
- package/js/theme/overlay.js +29 -0
- package/js/theme/package.json +3 -0
- package/js/theme/palette.js +103 -0
- package/js/theme/radius.js +76 -0
- package/js/theme/semantic-mapper.js +138 -0
- package/js/theme/typography.js +33 -0
- package/js/theme/url-state.js +52 -0
- package/js/tooltip.js +227 -0
- package/package.json +139 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="pt">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Cadastro — Design System</title>
|
|
7
|
+
<link rel="stylesheet" href="../../css/design-system.css">
|
|
8
|
+
<link rel="stylesheet" href="../layout.css">
|
|
9
|
+
<script>
|
|
10
|
+
(function(){var l=localStorage.getItem('ds-lang');if(l)document.documentElement.setAttribute('lang',l)})();
|
|
11
|
+
</script>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
|
|
15
|
+
<header class="ds-site-header">
|
|
16
|
+
<div style="display:flex;align-items:center;gap:var(--ds-dimension-16)">
|
|
17
|
+
<button class="ds-menu-toggle" id="menu-toggle" aria-label="Toggle navigation" aria-expanded="false">
|
|
18
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
|
19
|
+
</button>
|
|
20
|
+
<a href="../../index.html" class="ds-site-header__brand" aria-label="TIS Design System">
|
|
21
|
+
<img class="ds-site-header__logo" src="../assets/logo-tis-mark.svg" alt="TIS" width="36" height="36">
|
|
22
|
+
<span class="ds-site-header__title ds-site-header__title--brand">TIS</span>
|
|
23
|
+
<span class="ds-site-header__brand-separator" aria-hidden="true"></span>
|
|
24
|
+
<span class="ds-site-header__title ds-site-header__title--product">Design System</span>
|
|
25
|
+
</a>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="ds-site-header__actions">
|
|
28
|
+
<select class="ds-theme-switcher__select" id="lang-switcher" aria-label="Language">
|
|
29
|
+
<option value="pt">PT</option>
|
|
30
|
+
<option value="en">EN</option>
|
|
31
|
+
</select>
|
|
32
|
+
<button class="ds-button ds-button--ghost ds-button--sm" id="mode-toggle" aria-pressed="false" aria-label="Toggle dark mode"><svg class="ds-button__icon ds-site-header__mode-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></svg><span class="ds-button__label">Dark</span></button>
|
|
33
|
+
</div>
|
|
34
|
+
</header>
|
|
35
|
+
<div class="ds-sidebar-overlay" id="sidebar-overlay"></div>
|
|
36
|
+
|
|
37
|
+
<nav class="ds-sidebar" id="sidebar" aria-label="Main navigation"></nav>
|
|
38
|
+
|
|
39
|
+
<main class="ds-main">
|
|
40
|
+
|
|
41
|
+
<!-- 1. HEADER -->
|
|
42
|
+
<div class="ds-section">
|
|
43
|
+
<h1 class="ds-section__title"><span data-lang="pt">Cadastro</span><span data-lang="en">Sign Up</span></h1>
|
|
44
|
+
<p class="ds-section__subtitle">
|
|
45
|
+
<span data-lang="pt">Formulário de criação de conta com validação em linha, feedback de erro via Alert e aceite de termos. Usa Form Field para estrutura acessível.</span>
|
|
46
|
+
<span data-lang="en">Account creation form with inline validation, Alert error feedback, and terms acceptance. Uses Form Field for accessible structure.</span>
|
|
47
|
+
</p>
|
|
48
|
+
<div style="display:flex;flex-wrap:wrap;gap:var(--ds-dimension-8);margin-top:var(--ds-dimension-16)">
|
|
49
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Input</span>
|
|
50
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Select</span>
|
|
51
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Checkbox</span>
|
|
52
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Alert</span>
|
|
53
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Button</span>
|
|
54
|
+
<span class="ds-badge ds-badge--neutral ds-badge--subtle">Form Field</span>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- 2. PREVIEW -->
|
|
59
|
+
<div class="ds-subsection">
|
|
60
|
+
<h2 class="ds-subsection__title">Preview</h2>
|
|
61
|
+
<div class="ds-preview">
|
|
62
|
+
<div class="ds-preview__tabs">
|
|
63
|
+
<button class="ds-preview__tab ds-preview__tab--active" data-tab="preview">Preview</button>
|
|
64
|
+
<button class="ds-preview__tab" data-tab="code">Code</button>
|
|
65
|
+
<button type="button" class="ds-button ds-button--ghost ds-button--sm ds-preview__action" onclick="openPreviewInNewTab()" aria-label="Abrir preview em nova aba"><svg class="ds-button__icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg><span class="ds-button__label">Abrir em nova aba</span></button>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="ds-preview__canvas" style="padding:0;display:block">
|
|
68
|
+
<div style="min-height:660px;display:flex;align-items:center;justify-content:center;background:var(--ds-background-subtle);padding:var(--ds-dimension-40)">
|
|
69
|
+
<div style="background:var(--ds-surface-default);border-radius:var(--ds-radius-lg);padding:var(--ds-dimension-40);width:100%;max-width:440px;box-shadow:0 8px 32px rgba(0,0,0,.08);box-sizing:border-box">
|
|
70
|
+
|
|
71
|
+
<div style="text-align:center;margin-bottom:var(--ds-dimension-32)">
|
|
72
|
+
<div style="width:48px;height:48px;background:var(--ds-brand-background-default);border-radius:var(--ds-radius-md);display:inline-flex;align-items:center;justify-content:center;margin-bottom:var(--ds-dimension-16)">
|
|
73
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
74
|
+
<rect x="3" y="3" width="8" height="8" rx="1.5" fill="var(--ds-brand-content-default)"/>
|
|
75
|
+
<rect x="13" y="3" width="8" height="8" rx="1.5" fill="var(--ds-brand-content-default)" opacity=".55"/>
|
|
76
|
+
<rect x="3" y="13" width="8" height="8" rx="1.5" fill="var(--ds-brand-content-default)" opacity=".55"/>
|
|
77
|
+
<rect x="13" y="13" width="8" height="8" rx="1.5" fill="var(--ds-brand-content-default)"/>
|
|
78
|
+
</svg>
|
|
79
|
+
</div>
|
|
80
|
+
<h2 style="font-size:var(--ds-body-font-size-xl);font-weight:var(--ds-body-font-weight-bold);color:var(--ds-content-strong);margin:0 0 var(--ds-dimension-4)">
|
|
81
|
+
<span data-lang="pt">Crie sua conta</span><span data-lang="en">Create your account</span>
|
|
82
|
+
</h2>
|
|
83
|
+
<p style="font-size:var(--ds-body-font-size-md);color:var(--ds-content-default);margin:0">
|
|
84
|
+
<span data-lang="pt">Gratuito para começar, sem cartão de crédito</span>
|
|
85
|
+
<span data-lang="en">Free to start, no credit card required</span>
|
|
86
|
+
</p>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="ds-alert ds-alert--info ds-alert--subtle" style="margin-bottom:var(--ds-dimension-24)" role="status">
|
|
90
|
+
<div class="ds-alert__content">
|
|
91
|
+
<span class="ds-alert__description">
|
|
92
|
+
<span data-lang="pt">Use um e-mail corporativo para desbloquear recursos de equipe.</span>
|
|
93
|
+
<span data-lang="en">Use a work email to unlock team features.</span>
|
|
94
|
+
</span>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<form novalidate>
|
|
99
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--ds-dimension-12);margin-bottom:var(--ds-dimension-16)">
|
|
100
|
+
<div class="ds-field" style="min-width:0">
|
|
101
|
+
<div class="ds-field__label-row">
|
|
102
|
+
<label class="ds-field__label" for="su-fname"><span data-lang="pt">Nome</span><span data-lang="en">First name</span></label>
|
|
103
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="ds-input ds-input--lg">
|
|
106
|
+
<input class="ds-input__field" type="text" id="su-fname" autocomplete="given-name" required>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="ds-field" style="min-width:0">
|
|
110
|
+
<div class="ds-field__label-row">
|
|
111
|
+
<label class="ds-field__label" for="su-lname"><span data-lang="pt">Sobrenome</span><span data-lang="en">Last name</span></label>
|
|
112
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="ds-input ds-input--lg">
|
|
115
|
+
<input class="ds-input__field" type="text" id="su-lname" autocomplete="family-name" required>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div class="ds-field" style="margin-bottom:var(--ds-dimension-16)">
|
|
121
|
+
<div class="ds-field__label-row">
|
|
122
|
+
<label class="ds-field__label" for="su-email">E-mail</label>
|
|
123
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
124
|
+
</div>
|
|
125
|
+
<div class="ds-input ds-input--lg">
|
|
126
|
+
<input class="ds-input__field" type="email" id="su-email" placeholder="seu@email.com" autocomplete="email" required>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<div class="ds-field ds-field--error" style="margin-bottom:var(--ds-dimension-16)">
|
|
131
|
+
<div class="ds-field__label-row">
|
|
132
|
+
<label class="ds-field__label" for="su-password"><span data-lang="pt">Senha</span><span data-lang="en">Password</span></label>
|
|
133
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="ds-input ds-input--lg ds-input--error">
|
|
136
|
+
<input class="ds-input__field" type="password" id="su-password" placeholder="••••••••" autocomplete="new-password" aria-describedby="su-password-error" required>
|
|
137
|
+
</div>
|
|
138
|
+
<span class="ds-field__error" id="su-password-error" role="alert">
|
|
139
|
+
<span data-lang="pt">Use ao menos 8 caracteres com letras e números.</span>
|
|
140
|
+
<span data-lang="en">Use at least 8 characters with letters and numbers.</span>
|
|
141
|
+
</span>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div class="ds-field" style="margin-bottom:var(--ds-dimension-24)">
|
|
145
|
+
<div class="ds-field__label-row">
|
|
146
|
+
<label class="ds-field__label" for="su-country"><span data-lang="pt">País</span><span data-lang="en">Country</span></label>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="ds-select ds-select--lg">
|
|
149
|
+
<select class="ds-select__field" id="su-country" autocomplete="country-name">
|
|
150
|
+
<option value="">Selecione...</option>
|
|
151
|
+
<option>Brasil</option>
|
|
152
|
+
<option>Portugal</option>
|
|
153
|
+
<option>United States</option>
|
|
154
|
+
<option>Spain</option>
|
|
155
|
+
</select>
|
|
156
|
+
<span class="ds-select__arrow" aria-hidden="true"></span>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<label class="ds-checkbox-label" style="margin-bottom:var(--ds-dimension-24)">
|
|
161
|
+
<input class="ds-checkbox" type="checkbox" id="su-terms" required>
|
|
162
|
+
<span class="ds-checkbox__content">
|
|
163
|
+
<span class="ds-checkbox__label">
|
|
164
|
+
<span data-lang="pt">Concordo com os <a class="ds-link" href="#">Termos de uso</a> e a <a class="ds-link" href="#">Política de privacidade</a></span>
|
|
165
|
+
<span data-lang="en">I agree to the <a class="ds-link" href="#">Terms of service</a> and <a class="ds-link" href="#">Privacy policy</a></span>
|
|
166
|
+
</span>
|
|
167
|
+
</span>
|
|
168
|
+
</label>
|
|
169
|
+
|
|
170
|
+
<button class="ds-button ds-button--brand ds-button--lg ds-button--full" type="submit">
|
|
171
|
+
<span class="ds-button__label"><span data-lang="pt">Criar conta</span><span data-lang="en">Create account</span></span>
|
|
172
|
+
</button>
|
|
173
|
+
</form>
|
|
174
|
+
|
|
175
|
+
<p style="text-align:center;font-size:var(--ds-body-font-size-sm);color:var(--ds-content-default);margin:var(--ds-dimension-24) 0 0">
|
|
176
|
+
<span data-lang="pt">Já tem uma conta? <a class="ds-link" href="#">Entrar</a></span>
|
|
177
|
+
<span data-lang="en">Already have an account? <a class="ds-link" href="#">Sign in</a></span>
|
|
178
|
+
</p>
|
|
179
|
+
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="ds-preview__code" style="display:none">
|
|
184
|
+
<button class="ds-preview__copy">Copy</button>
|
|
185
|
+
<pre tabindex="0"><code><!DOCTYPE html>
|
|
186
|
+
<html lang="pt-BR">
|
|
187
|
+
<head>
|
|
188
|
+
<meta charset="UTF-8">
|
|
189
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
190
|
+
<title>Cadastro</title>
|
|
191
|
+
<link rel="stylesheet" href="css/design-system.css">
|
|
192
|
+
<style>
|
|
193
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
194
|
+
body {
|
|
195
|
+
min-height: 100vh;
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
justify-content: center;
|
|
199
|
+
background: var(--ds-background-subtle);
|
|
200
|
+
padding: var(--ds-dimension-40);
|
|
201
|
+
}
|
|
202
|
+
.signup-card {
|
|
203
|
+
background: var(--ds-surface-default);
|
|
204
|
+
border-radius: var(--ds-radius-lg);
|
|
205
|
+
padding: var(--ds-dimension-40);
|
|
206
|
+
width: 100%; max-width: 440px;
|
|
207
|
+
box-shadow: 0 8px 32px rgba(0,0,0,.08);
|
|
208
|
+
}
|
|
209
|
+
.signup-name-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ds-dimension-12); margin-bottom: var(--ds-dimension-16); }
|
|
210
|
+
.signup-name-row > * { min-width: 0; }
|
|
211
|
+
</style>
|
|
212
|
+
</head>
|
|
213
|
+
<body>
|
|
214
|
+
|
|
215
|
+
<div class="signup-card">
|
|
216
|
+
|
|
217
|
+
<div style="text-align:center;margin-bottom:var(--ds-dimension-32)">
|
|
218
|
+
<h1 style="font-size:var(--ds-body-font-size-xl);font-weight:var(--ds-body-font-weight-bold);color:var(--ds-content-strong);margin:0 0 var(--ds-dimension-4)">Crie sua conta</h1>
|
|
219
|
+
<p style="font-size:var(--ds-body-font-size-md);color:var(--ds-content-default);margin:0">Gratuito para começar, sem cartão de crédito</p>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<div class="ds-alert ds-alert--info ds-alert--subtle" style="margin-bottom:var(--ds-dimension-24)" role="status">
|
|
223
|
+
<div class="ds-alert__content">
|
|
224
|
+
<span class="ds-alert__description">Use um e-mail corporativo para desbloquear recursos de equipe.</span>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<form novalidate>
|
|
229
|
+
<div class="signup-name-row">
|
|
230
|
+
<div class="ds-field">
|
|
231
|
+
<div class="ds-field__label-row">
|
|
232
|
+
<label class="ds-field__label" for="fname">Nome</label>
|
|
233
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="ds-input ds-input--lg">
|
|
236
|
+
<input class="ds-input__field" type="text" id="fname" autocomplete="given-name" required>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="ds-field">
|
|
240
|
+
<div class="ds-field__label-row">
|
|
241
|
+
<label class="ds-field__label" for="lname">Sobrenome</label>
|
|
242
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
243
|
+
</div>
|
|
244
|
+
<div class="ds-input ds-input--lg">
|
|
245
|
+
<input class="ds-input__field" type="text" id="lname" autocomplete="family-name" required>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
|
|
250
|
+
<div class="ds-field" style="margin-bottom:var(--ds-dimension-16)">
|
|
251
|
+
<div class="ds-field__label-row">
|
|
252
|
+
<label class="ds-field__label" for="email">E-mail</label>
|
|
253
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
254
|
+
</div>
|
|
255
|
+
<div class="ds-input ds-input--lg">
|
|
256
|
+
<input class="ds-input__field" type="email" id="email" placeholder="seu@email.com" autocomplete="email" required>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
|
|
260
|
+
<div class="ds-field" style="margin-bottom:var(--ds-dimension-16)">
|
|
261
|
+
<div class="ds-field__label-row">
|
|
262
|
+
<label class="ds-field__label" for="password">Senha</label>
|
|
263
|
+
<span class="ds-field__required" aria-hidden="true">*</span>
|
|
264
|
+
</div>
|
|
265
|
+
<div class="ds-input ds-input--lg">
|
|
266
|
+
<input class="ds-input__field" type="password" id="password"
|
|
267
|
+
placeholder="••••••••" autocomplete="new-password" required>
|
|
268
|
+
</div>
|
|
269
|
+
<span class="ds-field__helper">Mínimo 8 caracteres com letras e números.</span>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<div class="ds-field" style="margin-bottom:var(--ds-dimension-24)">
|
|
273
|
+
<div class="ds-field__label-row">
|
|
274
|
+
<label class="ds-field__label" for="country">País</label>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="ds-select ds-select--lg">
|
|
277
|
+
<select class="ds-select__field" id="country" autocomplete="country-name">
|
|
278
|
+
<option value="">Selecione...</option>
|
|
279
|
+
<option>Brasil</option>
|
|
280
|
+
<option>Portugal</option>
|
|
281
|
+
</select>
|
|
282
|
+
<span class="ds-select__arrow" aria-hidden="true"></span>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<label class="ds-checkbox-label" style="margin-bottom:var(--ds-dimension-24)">
|
|
287
|
+
<input class="ds-checkbox" type="checkbox" id="terms" required>
|
|
288
|
+
<span class="ds-checkbox__content">
|
|
289
|
+
<span class="ds-checkbox__label">
|
|
290
|
+
Concordo com os <a class="ds-link" href="/terms">Termos de uso</a>
|
|
291
|
+
e a <a class="ds-link" href="/privacy">Política de privacidade</a>
|
|
292
|
+
</span>
|
|
293
|
+
</span>
|
|
294
|
+
</label>
|
|
295
|
+
|
|
296
|
+
<button class="ds-button ds-button--brand ds-button--lg ds-button--full" type="submit">
|
|
297
|
+
<span class="ds-button__label">Criar conta</span>
|
|
298
|
+
</button>
|
|
299
|
+
</form>
|
|
300
|
+
|
|
301
|
+
<p style="text-align:center;font-size:var(--ds-body-font-size-sm);color:var(--ds-content-default);margin:var(--ds-dimension-24) 0 0">
|
|
302
|
+
Já tem uma conta? <a class="ds-link" href="/login">Entrar</a>
|
|
303
|
+
</p>
|
|
304
|
+
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
</body>
|
|
308
|
+
</html></code></pre>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
|
|
313
|
+
<!-- 3. USAGE -->
|
|
314
|
+
<div class="ds-subsection">
|
|
315
|
+
<h2 class="ds-subsection__title"><span data-lang="pt">Notas de uso</span><span data-lang="en">Usage notes</span></h2>
|
|
316
|
+
<table class="ds-token-table">
|
|
317
|
+
<thead><tr><th><span data-lang="pt">Padrão</span><span data-lang="en">Pattern</span></th><th><span data-lang="pt">Decisão</span><span data-lang="en">Decision</span></th></tr></thead>
|
|
318
|
+
<tbody>
|
|
319
|
+
<tr><td><span data-lang="pt">Campo de senha com estado de erro</span><span data-lang="en">Password field with error state</span></td><td><span data-lang="pt">Mostra <code>ds-field--error</code> + <code>ds-input--error</code> + <code>ds-field__error</code> juntos — o preview demonstra a composição completa.</span><span data-lang="en">Shows <code>ds-field--error</code> + <code>ds-input--error</code> + <code>ds-field__error</code> together — the preview demonstrates the full composition.</span></td></tr>
|
|
320
|
+
<tr><td><code>ds-alert--info--subtle</code></td><td><span data-lang="pt">Dica contextual não bloqueia o fluxo — use <code>role="status"</code> para que leitores de tela anunciem sem interromper.</span><span data-lang="en">Contextual tip doesn't block the flow — use <code>role="status"</code> so screen readers announce without interrupting.</span></td></tr>
|
|
321
|
+
<tr><td><span data-lang="pt">Grid de nome em 2 colunas</span><span data-lang="en">Two-column name grid</span></td><td><span data-lang="pt">Reduz a altura do formulário e agrupa campos relacionados. No mobile, colapse para 1 coluna via media query.</span><span data-lang="en">Reduces form height and groups related fields. On mobile, collapse to 1 column via media query.</span></td></tr>
|
|
322
|
+
</tbody>
|
|
323
|
+
</table>
|
|
324
|
+
</div>
|
|
325
|
+
|
|
326
|
+
<!-- 4. RELATED -->
|
|
327
|
+
<div class="ds-subsection">
|
|
328
|
+
<h2 class="ds-subsection__title"><span data-lang="pt">Templates relacionados</span><span data-lang="en">Related templates</span></h2>
|
|
329
|
+
<div class="ds-related">
|
|
330
|
+
<a href="login.html" class="ds-related__link">Login</a>
|
|
331
|
+
<a href="index.html" class="ds-related__link"><span data-lang="pt">Ver todos os templates</span><span data-lang="en">All templates</span></a>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
|
|
335
|
+
</main>
|
|
336
|
+
|
|
337
|
+
<script src="../../js/main.js"></script>
|
|
338
|
+
<script>
|
|
339
|
+
function openPreviewInNewTab() {
|
|
340
|
+
var code = document.querySelector('.ds-preview__code pre code').textContent;
|
|
341
|
+
var cssUrl = new URL('../../css/design-system.css', window.location.href).href;
|
|
342
|
+
var html = code.replace(/"css\/design-system\.css"/, '"' + cssUrl + '"');
|
|
343
|
+
var blob = new Blob([html], { type: 'text/html' });
|
|
344
|
+
var url = URL.createObjectURL(blob);
|
|
345
|
+
window.open(url, '_blank');
|
|
346
|
+
setTimeout(function() { URL.revokeObjectURL(url); }, 30000);
|
|
347
|
+
}
|
|
348
|
+
</script>
|
|
349
|
+
</body>
|
|
350
|
+
</html>
|
package/js/accordion.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
accordion.js — runtime público para Accordion (required)
|
|
3
|
+
|
|
4
|
+
Anatomia e estados visuais: css/components/accordion.css
|
|
5
|
+
Uso:
|
|
6
|
+
<div class="ds-accordion" data-accordion-mode="single">
|
|
7
|
+
<div class="ds-accordion__item" data-state="closed">
|
|
8
|
+
<button class="ds-accordion__trigger" type="button"
|
|
9
|
+
aria-expanded="false" aria-controls="panel-1">…</button>
|
|
10
|
+
<div class="ds-accordion__panel" id="panel-1" role="region" hidden>…</div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
Ciclo de vida:
|
|
15
|
+
const instances = initAccordions(root);
|
|
16
|
+
destroyAccordions(root); // ou instance.destroy()
|
|
17
|
+
============================================================ */
|
|
18
|
+
|
|
19
|
+
const instances = new Set();
|
|
20
|
+
|
|
21
|
+
function getTriggers(accordion) {
|
|
22
|
+
return [...accordion.querySelectorAll('.ds-accordion__trigger[aria-controls]')].filter(
|
|
23
|
+
(trigger) => trigger.closest('.ds-accordion') === accordion,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function emit(accordion, name, detail) {
|
|
28
|
+
accordion.dispatchEvent(new CustomEvent(name, { bubbles: true, detail }));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function setItemState(trigger, expanded) {
|
|
32
|
+
const panelId = trigger.getAttribute('aria-controls');
|
|
33
|
+
const panel = panelId ? document.getElementById(panelId) : null;
|
|
34
|
+
const item = trigger.closest('.ds-accordion__item');
|
|
35
|
+
|
|
36
|
+
trigger.setAttribute('aria-expanded', String(expanded));
|
|
37
|
+
if (panel) panel.hidden = !expanded;
|
|
38
|
+
if (item) item.setAttribute('data-state', expanded ? 'open' : 'closed');
|
|
39
|
+
|
|
40
|
+
return { item, panel };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createInstance(accordion) {
|
|
44
|
+
const triggers = getTriggers(accordion);
|
|
45
|
+
if (!triggers.length) return null;
|
|
46
|
+
|
|
47
|
+
const cleanups = [];
|
|
48
|
+
const on = (target, type, handler, options) => {
|
|
49
|
+
target.addEventListener(type, handler, options);
|
|
50
|
+
cleanups.push(() => target.removeEventListener(type, handler, options));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const inst = {
|
|
54
|
+
root: accordion,
|
|
55
|
+
open(trigger) {
|
|
56
|
+
if (!trigger || !triggers.includes(trigger)) return;
|
|
57
|
+
if (trigger.disabled || trigger.getAttribute('aria-disabled') === 'true') return;
|
|
58
|
+
if (trigger.getAttribute('aria-expanded') === 'true') return;
|
|
59
|
+
|
|
60
|
+
if (accordion.getAttribute('data-accordion-mode') === 'single') {
|
|
61
|
+
for (const other of triggers) {
|
|
62
|
+
if (other !== trigger && other.getAttribute('aria-expanded') === 'true') {
|
|
63
|
+
const closed = setItemState(other, false);
|
|
64
|
+
emit(accordion, 'ds-accordion-close', { trigger: other, ...closed });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const opened = setItemState(trigger, true);
|
|
70
|
+
emit(accordion, 'ds-accordion-open', { trigger, ...opened });
|
|
71
|
+
},
|
|
72
|
+
close(trigger) {
|
|
73
|
+
if (!trigger || !triggers.includes(trigger)) return;
|
|
74
|
+
if (trigger.getAttribute('aria-expanded') !== 'true') return;
|
|
75
|
+
const closed = setItemState(trigger, false);
|
|
76
|
+
emit(accordion, 'ds-accordion-close', { trigger, ...closed });
|
|
77
|
+
},
|
|
78
|
+
toggle(trigger) {
|
|
79
|
+
if (!trigger || !triggers.includes(trigger)) return;
|
|
80
|
+
if (trigger.getAttribute('aria-expanded') === 'true') inst.close(trigger);
|
|
81
|
+
else inst.open(trigger);
|
|
82
|
+
},
|
|
83
|
+
destroy() {
|
|
84
|
+
while (cleanups.length) cleanups.pop()();
|
|
85
|
+
delete accordion.dataset.dsAccordionInit;
|
|
86
|
+
instances.delete(inst);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
function moveFocus(current, direction) {
|
|
91
|
+
const currentIndex = triggers.indexOf(current);
|
|
92
|
+
if (currentIndex === -1) return;
|
|
93
|
+
|
|
94
|
+
const nextIndex = direction === 'first'
|
|
95
|
+
? 0
|
|
96
|
+
: direction === 'last'
|
|
97
|
+
? triggers.length - 1
|
|
98
|
+
: (currentIndex + direction + triggers.length) % triggers.length;
|
|
99
|
+
|
|
100
|
+
triggers[nextIndex].focus();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const trigger of triggers) {
|
|
104
|
+
const panel = document.getElementById(trigger.getAttribute('aria-controls'));
|
|
105
|
+
const expanded = trigger.getAttribute('aria-expanded') === 'true' && !(panel && panel.hidden);
|
|
106
|
+
setItemState(trigger, expanded);
|
|
107
|
+
|
|
108
|
+
on(trigger, 'click', () => {
|
|
109
|
+
if (trigger.disabled || trigger.getAttribute('aria-disabled') === 'true') return;
|
|
110
|
+
inst.toggle(trigger);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
on(trigger, 'keydown', (e) => {
|
|
114
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
moveFocus(trigger, 1);
|
|
117
|
+
} else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
moveFocus(trigger, -1);
|
|
120
|
+
} else if (e.key === 'Home') {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
moveFocus(trigger, 'first');
|
|
123
|
+
} else if (e.key === 'End') {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
moveFocus(trigger, 'last');
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return inst;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isInside(root, node) {
|
|
134
|
+
return root === document || root === node || (typeof root.contains === 'function' && root.contains(node));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getAccordions(root) {
|
|
138
|
+
const accordions = [];
|
|
139
|
+
if (root?.matches?.('.ds-accordion')) accordions.push(root);
|
|
140
|
+
if (typeof root?.querySelectorAll === 'function') {
|
|
141
|
+
accordions.push(...root.querySelectorAll('.ds-accordion'));
|
|
142
|
+
}
|
|
143
|
+
return accordions;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {ParentNode} [root]
|
|
148
|
+
*/
|
|
149
|
+
export function initAccordions(root = document) {
|
|
150
|
+
const created = [];
|
|
151
|
+
|
|
152
|
+
getAccordions(root).forEach((accordion) => {
|
|
153
|
+
if (accordion.dataset.dsAccordionInit === 'true') return;
|
|
154
|
+
const inst = createInstance(accordion);
|
|
155
|
+
if (inst) {
|
|
156
|
+
accordion.dataset.dsAccordionInit = 'true';
|
|
157
|
+
instances.add(inst);
|
|
158
|
+
created.push(inst);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return created;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {ParentNode} [root]
|
|
167
|
+
*/
|
|
168
|
+
export function destroyAccordions(root = document) {
|
|
169
|
+
for (const inst of [...instances]) {
|
|
170
|
+
if (isInside(root, inst.root)) inst.destroy();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @param {HTMLElement} trigger
|
|
176
|
+
*/
|
|
177
|
+
export function openAccordionItem(trigger) {
|
|
178
|
+
const accordion = trigger?.closest?.('.ds-accordion');
|
|
179
|
+
const inst = [...instances].find((item) => item.root === accordion);
|
|
180
|
+
inst?.open(trigger);
|
|
181
|
+
return inst;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @param {HTMLElement} trigger
|
|
186
|
+
*/
|
|
187
|
+
export function closeAccordionItem(trigger) {
|
|
188
|
+
const accordion = trigger?.closest?.('.ds-accordion');
|
|
189
|
+
const inst = [...instances].find((item) => item.root === accordion);
|
|
190
|
+
inst?.close(trigger);
|
|
191
|
+
return inst;
|
|
192
|
+
}
|