跳到内容
菜单
语言,当前是简体中文
EnglishGaeilge简体中文Españolहिन्दीPortuguêsবাংলাРусский日本語廣東話Tiếng Việtالعربية

rastrillo 设计系统

设计系统所提供内容的总览。主题:signal。语言:简体中文

表单

每一个控件,处在真实表单会让它处于的状态里。每个都放在有内边距的 rst-box 中,因为这些片段就是这么假定的。

预先做好、彼此一致的界面元素,在服务器端渲染。

框架自己的词汇把它们叫作 partial:ui.Templates() 返回的是 partial,docs/site/templates.md 也用这个名字。这页上的说法换了,代码里的没换。

这里的链接不可点

链接不可点,示例源码另行提供。

下面每个示例都在自己的框里。

示例内容为英文,示例外壳已翻译。

field

标签、输入框、可选提示、帮助文本和错误。通用的类文本控件,带一个显式 ID。

最简

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_bare">Title</label>
<input rst-input type="text" id="f_bare" name="f_bare">
</div></form></section>

带一条提示

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_hint">Slug <span rst-field-hint>(lowercase, no spaces)</span></label>
<input rst-input type="text" id="f_hint" name="f_hint">
</div></form></section>

控件下方带一行帮助文字

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_help">Email</label>
<input rst-input type="email" id="f_help" name="f_help" autocomplete="email" aria-describedby="f_help-help">
<p rst-field-help id="f_help-help">We only use this to send you replies.</p>
</div></form></section>

必填

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_required">Full name</label>
<input rst-input type="text" id="f_required" name="f_required" required>
</div></form></section>

带一个错误

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_error">Email</label>
<input rst-input type="email" id="f_error" name="f_error" value="grace@" aria-invalid="true" aria-describedby="f_error-error">
<p rst-field-error id="f_error-error" role="alert">That does not look like an email address.</p>
</div></form></section>

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_short">Postcode</label>
<input rst-input="short" type="text" id="f_short" name="f_short" value="D02 XY45">
</div></form></section>

主字段

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="f_primary">Title</label>
<input rst-input="primary" type="text" id="f_primary" name="f_primary" value="Quarterly board meeting">
</div></form></section>

field-text

一个带标签的文本输入框,id 由 Name 推导而来。必填标记的星号是 aria-hidden,输入框的 required 属性才是程序可读的信号。

最简

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ft_bare">Title</label>
  <input rst-input id="ft_bare" name="ft_bare" type="text">
</div></form></section>

带一条提示

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ft_hint">Headline</label>
  <input rst-input id="ft_hint" name="ft_hint" type="text" aria-describedby="ft_hint-hint">
  <small rst-field-hint id="ft_hint-hint">Shown in the list.</small>
</div></form></section>

必填

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ft_required">Display name <span rst-field-required aria-hidden="true">*</span></label>
  <input rst-input id="ft_required" name="ft_required" type="text" autocomplete="nickname" required>
</div></form></section>

带一个错误

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ft_error">Title</label>
  <input rst-input id="ft_error" name="ft_error" type="text" value="Release notes" aria-invalid="true" aria-describedby="ft_error-error">
  <small rst-field-error id="ft_error-error">A post with that title already exists.</small>
</div></form></section>

主字段

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ft_primary">What is it?</label>
  <input rst-input="primary" id="ft_primary" name="ft_primary" type="text" value="Quarterly board meeting">
</div></form></section>

给表单的主字段(例如标题或名称)加上 Primary,输入框会更醒目。

field-textarea

field-text 的外壳,包住一个 textarea。

最简

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ta_bare">Notes</label>
  <textarea rst-textarea id="ta_bare" name="ta_bare" rows="3"></textarea>
</div></form></section>

带一条提示

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ta_hint">Bio</label>
  <textarea rst-textarea id="ta_hint" name="ta_hint" rows="3" aria-describedby="ta_hint-hint"></textarea>
  <small rst-field-hint id="ta_hint-hint">Shown on your profile.</small>
</div></form></section>

带一个错误

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ta_error">Summary</label>
  <textarea rst-textarea id="ta_error" name="ta_error" rows="3" aria-invalid="true" aria-describedby="ta_error-error">…</textarea>
  <small rst-field-error id="ta_error-error">A summary needs at least twenty characters.</small>
</div></form></section>

必填

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field>
  <label rst-field-label for="ta_required">Reason for refund <span rst-field-required aria-hidden="true">*</span></label>
  <textarea rst-textarea id="ta_required" name="ta_required" rows="3" required></textarea>
</div></form></section>

field-select

field 的外壳包住一个原生 select。超过十个选项时,这个 select 会启用 select.js 里可筛选的组合框;但表单提交的仍然是那个原生 select。

三个选项:原生 select

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="sel_few">Role</label>
<select rst-input id="sel_few" name="sel_few"><option value="Admin" selected>Admin</option><option value="Editor">Editor</option><option value="Member">Member</option></select>
</div></form></section>

十二个选项:可筛选的组合框

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="sel_many">City</label>
<select rst-input id="sel_many" name="sel_many" data-rst-select data-rst-select-filter="输入以筛选" data-rst-select-results="{n} 个结果" data-rst-select-result-one="1 个结果" aria-describedby="sel_many-help"><option value="Dublin" selected>Dublin</option><option value="Lisbon">Lisbon</option><option value="Madrid">Madrid</option><option value="Berlin">Berlin</option><option value="Rome">Rome</option><option value="Athens">Athens</option><option value="Helsinki">Helsinki</option><option value="Reykjavík">Reykjavík</option><option value="Warsaw">Warsaw</option><option value="Zagreb">Zagreb</option><option value="Tallinn">Tallinn</option><option value="Valletta">Valletta</option></select>
<p rst-field-help id="sel_many-help">Start typing to filter.</p>
</div></form></section>

超过十个选项,片段就会启用 select.js;不到十个就不会:在几项之间搜索只是摆设,不是帮助。

十二个选项,Plain——明确不要增强

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="sel_plain">City</label>
<select rst-input id="sel_plain" name="sel_plain"><option value="Dublin" selected>Dublin</option><option value="Lisbon">Lisbon</option><option value="Madrid">Madrid</option><option value="Berlin">Berlin</option><option value="Rome">Rome</option><option value="Athens">Athens</option><option value="Helsinki">Helsinki</option><option value="Reykjavík">Reykjavík</option><option value="Warsaw">Warsaw</option><option value="Zagreb">Zagreb</option><option value="Tallinn">Tallinn</option><option value="Valletta">Valletta</option></select>
</div></form></section>

必填,并带错误

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="sel_error">Role</label>
<select rst-input id="sel_error" name="sel_error" required aria-invalid="true" aria-describedby="sel_error-error"><option value="Admin" selected>Admin</option><option value="Editor">Editor</option><option value="Member">Member</option></select>
<p rst-field-error id="sel_error-error" role="alert">Pick a role for this person.</p>
</div></form></section>

手写的,带 optgroup 分组

预览
<section rst-box><form rst-form method="post" action="#"><div rst-field><label rst-field-label for="sel_grouped">Region</label>
<select rst-input id="sel_grouped" name="sel_grouped" data-rst-select data-rst-select-filter="输入以筛选" data-rst-select-results="{n} 个结果" data-rst-select-result-one="1 个结果">
<optgroup label="Europe"><option value="dublin" selected>Dublin</option><option value="lisbon">Lisbon</option><option value="warsaw">Warsaw</option></optgroup>
<optgroup label="Americas"><option value="montreal">Montréal</option><option value="lima">Lima</option><option value="austin">Austin</option></optgroup>
<optgroup label="Asia"><option value="osaka">Osaka</option><option value="hanoi">Hanoi</option><option value="dhaka">Dhaka</option></optgroup>
<optgroup label="Africa"><option value="accra">Accra</option><option value="nairobi">Nairobi</option><option value="tunis">Tunis</option></optgroup>
</select>
</div></form></section>

这里的 Options 是一个扁平列表,所以分组的选项要由应用自己写成标记。select.js 会把分组渲染出来而不是丢掉;手写的 select 也可以用 data-rst-select="false" 彻底拒绝增强。

field-check

唯一的一种开关做法:一个真正的复选框,外观做成开关,键盘和读屏器都照常可用。

预览
<section rst-box><form rst-form method="post" action="#"><label rst-switch><input type="checkbox" name="notify_on" checked><span rst-switch-track aria-hidden="true"></span> Email me about replies</label></form></section>

预览
<section rst-box><form rst-form method="post" action="#"><label rst-switch><input type="checkbox" name="notify_off"><span rst-switch-track aria-hidden="true"></span> Email me about mentions</label></form></section>

已禁用

预览
<section rst-box><form rst-form method="post" action="#"><label rst-switch><input type="checkbox" name="notify_disabled" disabled><span rst-switch-track aria-hidden="true"></span> Email me a weekly digest</label></form></section>

choice-field

选项卡片——推荐的单选或多选分组。Title 保持简短,解释交给 Desc。

只能选一个

预览
<section rst-box><form rst-form method="post" action="#"><fieldset rst-choice><legend>Plan</legend><div rst-choice-cards><label><input type="radio" name="plan" value="free"><span><span rst-choice-title>Free</span><span rst-choice-desc>One project, community support.</span></span></label><label><input type="radio" name="plan" value="pro" checked><span><span rst-choice-title>Pro</span><span rst-choice-desc>Unlimited projects and a support inbox.</span></span></label></div></fieldset></form></section>

可多选

预览
<section rst-box><form rst-form method="post" action="#"><fieldset rst-choice><legend>Send me</legend><div rst-choice-cards><label><input type="checkbox" name="digest" value="replies" checked><span><span rst-choice-title>Replies</span><span rst-choice-desc>As they happen.</span></span></label><label><input type="checkbox" name="digest" value="weekly"><span><span rst-choice-title>Weekly digest</span><span rst-choice-desc>Monday mornings.</span></span></label></div></fieldset></form></section>

form-foot

表单的收尾行:一个主提交按钮,外加可选的取消链接。取消是一个链接,因为离开表单是导航。

保存和取消

预览
<section rst-box><form rst-form method="post" action="#"><div rst-form-foot>
  <button rst-btn="primary" type="submit">Save post</button>
  <a rst-btn href="/posts">Back to posts</a>
</div></form></section>

只有提交

预览
<section rst-box><form rst-form method="post" action="#"><div rst-form-foot>
  <button rst-btn="primary" type="submit">Send invitation</button>
</div></form></section>

空闲——任何事情发生之前的按钮

预览
<section rst-box><form rst-form method="post" action="#"><div rst-form-foot>
  <button rst-btn="primary" type="submit">Publish</button>
  <a rst-btn href="/posts">Back to posts</a>
</div></form></section>

会改变什么的按钮有加载状态;只是展开什么的按钮(例如折叠、下拉、标签页)没有。rastrillo.js 对每个表单里的每个提交按钮都套用这条规则,无需选择启用。

工作中——表单送出时 rastrillo.js 写下的样子

预览
<section rst-box><form rst-form method="post" action="#"><div rst-form-foot>
<button rst-btn="primary" type="submit" aria-busy="true" data-idle-label="Publish" disabled><span rst-spin aria-hidden="true"></span>Publishing…</button>
<a rst-btn href="/posts">Back to posts</a>
</div></form></section>

只有被点击的那个按钮:表单里其他提交按钮都保留自己的 name 和 value,表单本身也会防住第二次提交。data-busy="false" 可以退出,写在表单上或某一个按钮上;data-busy-label 用来替换文字。关掉脚本,这些都不会发生,表单照旧提交,所以幂等仍然是服务器的事。

confirm-form

确认页的操作行。破坏性操作有自己的路由而不是一个对话框,所以没有什么需要写脚本。

破坏性操作

预览
<section rst-box><form rst-form-actions method="post" action="/posts/1/delete"><input type="hidden" name="csrf" value="tok-123"><input type="hidden" name="id" value="1"><a rst-btn="ghost" href="/posts/1">取消</a><button type="submit" rst-btn="danger">Delete this post</button></form></section>

普通情况,取消用默认措辞

预览
<section rst-box><form rst-form-actions method="post" action="/posts/1/publish"><a rst-btn="ghost" href="/posts/1">取消</a><button type="submit" rst-btn="primary">Publish</button></form></section>

没有 CancelLabel,所以取消链接的措辞取自目录。