Basic Input
A labelled text input with helper text wired to it via aria-describedby.
6 個のフレームワーク初級
A parent checkbox that goes mixed when only some of its children are selected.
<!--
THE thing people get wrong: `indeterminate` is a DOM PROPERTY, not an
attribute. There is no `<input indeterminate>` - writing it in the markup does
nothing at all. It can only be set from script, which is why this snippet ships
with one. `aria-checked="mixed"` is set alongside it so the state is announced
and not merely drawn.
A parent whose children are partly selected is neither checked nor unchecked,
and the native mixed glyph (a dash, not a tick) is what says so.
-->
<fieldset class="tree">
<legend class="tree__legend">Notify me about</legend>
<label class="tree__row" for="notify-all">
<input class="tree__input tree__input--parent" type="checkbox" id="notify-all" />
<span class="tree__text">All activity</span>
</label>
<ul class="tree__children">
<li>
<label class="tree__row" for="notify-mentions">
<input class="tree__input tree__input--child" type="checkbox" id="notify-mentions" name="notify" value="mentions" checked />
<span class="tree__text">Mentions and replies</span>
</label>
</li>
<li>
<label class="tree__row" for="notify-assign">
<input class="tree__input tree__input--child" type="checkbox" id="notify-assign" name="notify" value="assignments" />
<span class="tree__text">Assignments</span>
</label>
</li>
<li>
<label class="tree__row" for="notify-deploys">
<input class="tree__input tree__input--child" type="checkbox" id="notify-deploys" name="notify" value="deploys" />
<span class="tree__text">Deploys</span>
</label>
</li>
</ul>
</fieldset>
<script>
document.querySelectorAll('.tree').forEach(function (root) {
var parent = root.querySelector('.tree__input--parent');
var children = Array.prototype.slice.call(root.querySelectorAll('.tree__input--child'));
function syncParent() {
var checked = children.filter(function (child) { return child.checked; }).length;
var all = checked === children.length;
var none = checked === 0;
parent.checked = all;
// Property, not attribute - parent.setAttribute('indeterminate', '') is a
// no-op and is the bug this component exists to prevent.
parent.indeterminate = !all && !none;
parent.setAttribute('aria-checked', parent.indeterminate ? 'mixed' : String(all));
}
// Clicking the parent is all-or-nothing: from mixed it selects everything,
// which is what every file manager on the platform does.
parent.addEventListener('change', function () {
children.forEach(function (child) { child.checked = parent.checked; });
syncParent();
});
children.forEach(function (child) {
child.addEventListener('change', syncParent);
});
syncParent();
});
</script>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
disabled | boolean | false | 操作を無効にし、コントロールを淡色表示にします。 |
className | string | - | ルート要素にマージされる追加クラス。 |
The one thing to take from this component: `indeterminate` is a DOM **property**, not an attribute. There is no `<input indeterminate>`, React has no such prop, and `setAttribute('indeterminate', '')` does nothing - it can only be written to the element instance, which is why every variant here reaches for a ref or a script. `aria-checked="mixed"` is set beside it so the state is announced and not merely drawn. The boxes keep `accent-color` rather than a hand-rolled span precisely so the platform draws its own dash for the mixed state. Clicking a mixed parent selects everything, matching every file manager on the platform; invert that in the `onChange` if your product wants the opposite.