Previews

No matching results.

x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<div class="callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>MASKED INPUT:</strong> Format-as-you-type on a plain .form-control<br>
<strong>VARIANTS:</strong> UK phone | UK postcode | UPN | Custom mask | Invalid error | Disabled<br>
<strong>COMPOSES:</strong> .form-control + .form-label + .form-text + .is-invalid/.invalid-feedback
</p>
<p class="tw:mb-0 tw:text-sm">
Formatted identifiers take their canonical shape while the user types — group separators
are inserted automatically, letters uppercase where the format demands it, and messy
pasted values are stripped and reformatted. The caret is preserved through mid-value
edits, Backspace always deletes a real character (never bounces off a separator), and
partial input is never rejected (C05). Requires
<code>data-controller="masked-input"</code> with a declarative
<code>data-masked-input-mask-value</code> template (<code>#</code> digit,
<code>A</code> letter, <code>*</code> either; anything else is a literal).
</p>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UK phone number</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Mask <code>"##### ######"</code>:</strong> UK mobile grouping (5+6). Typing
<code>07123456789</code> renders <code>07123 456789</code>; pasting
<code>"Tel: 07123-456-789"</code> strips to digits and reformats. The optional hidden
<code>data-masked-input-target="raw"</code> input carries the unformatted digits
(<code>07123456789</code>) for systems that want the canonical value — the visible
input is the submitted field.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="##### ######">
<label class="form-label" for="masked-phone">Parent's mobile number</label>
<input type="tel" id="masked-phone" name="parent_phone" class="form-control"
autocomplete="tel" aria-describedby="masked-phone-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<input type="hidden" name="parent_phone_raw" data-masked-input-target="raw">
<p class="form-text" id="masked-phone-help">UK mobile number, e.g. 07123 456789. We'll format it as you type.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="##### ######"><input type="tel" class="form-control" autocomplete="tel" aria-describedby="…" data-masked-input-target="input" data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input"><input type="hidden" data-masked-input-target="raw"></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UK postcode</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Format <code>"uk-postcode"</code>:</strong> the one named algorithmic formatter —
UK postcodes are variable-geometry (outward part 2–4 characters, inward always 3)
and can't be expressed as a fixed template. Letters uppercase as typed
(<code>sw1a1aa</code><code>SW1A1AA</code>) and the canonical space appears once
the shape completes (<code>SW1A 1AA</code>) — mid-entry the space never hops around and
partial input is never fought.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-format-value="uk-postcode">
<label class="form-label" for="masked-postcode">Home postcode</label>
<input type="text" id="masked-postcode" name="home_postcode" class="form-control"
autocomplete="postal-code" aria-describedby="masked-postcode-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-postcode-help">For example SW1A 1AA. Used to check your catchment area.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-format-value="uk-postcode"><input class="form-control" autocomplete="postal-code" ></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UPN (Unique Pupil Number)</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Mask <code>"A############"</code>:</strong> one letter (uppercased on entry)
followed by 12 digits — no literals, so the formatted and raw values are identical.
A digit typed in the leading letter slot is discarded (character-class enforcement),
and characters beyond 13 are dropped.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="A############">
<label class="form-label" for="masked-upn">Child's UPN</label>
<input type="text" id="masked-upn" name="child_upn" class="form-control"
autocomplete="off" aria-describedby="masked-upn-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-upn-help">A letter followed by 12 digits, e.g. A123456789012. You'll find it on your child's school report or by asking their current school.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="A############"><input class="form-control" ></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Custom masks</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>The mask is declarative:</strong> any fixed-shape code works by supplying a
template — nothing is hardcoded in the controller. Here a bank sort code
(<code>"##-##-##"</code>) shows non-space literals being inserted and deleted
transparently: Backspace after a dash deletes the digit before it in one keypress.
</p>
</div>
<div class="masked-input tw:max-w-xs" data-controller="masked-input"
data-masked-input-mask-value="##-##-##">
<label class="form-label" for="masked-sort-code">Sort code</label>
<input type="text" id="masked-sort-code" name="sort_code" class="form-control"
inputmode="numeric" autocomplete="off" aria-describedby="masked-sort-code-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-sort-code-help">6 digits, e.g. 20-45-67. Shown on your bank card or statement.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="##-##-##"><input class="form-control" inputmode="numeric" ></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Invalid error</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Error state:</strong> markup-only <code>.is-invalid</code> +
<code>aria-invalid="true"</code> on the input (reusing
<code>.form-control.is-invalid</code> — no bespoke error CSS), with
<code>aria-describedby</code> pointing at the <code>.invalid-feedback</code> text.
The controller never <em>sets</em> the error (validity is the form's decision at
submit); the first correcting keystroke clears it and hides the error text (C08).
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-format-value="uk-postcode">
<label class="form-label" for="masked-postcode-invalid">Home postcode</label>
<input type="text" id="masked-postcode-invalid" name="home_postcode_invalid"
class="form-control is-invalid" value="SW99" aria-invalid="true"
autocomplete="postal-code" aria-describedby="masked-postcode-invalid-error"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="invalid-feedback" id="masked-postcode-invalid-error" data-masked-input-target="error">Enter a full UK postcode, e.g. SW1A 1AA.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><input class="form-control is-invalid" aria-invalid="true" aria-describedby="postcode-error" ><p class="invalid-feedback" id="postcode-error" data-masked-input-target="error">Enter a full UK postcode, e.g. SW1A 1AA.</p></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Disabled</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Disabled:</strong> real <code>[disabled]</code> attribute — greys out via the
shared <code>.form-control:disabled</code> rule, no masked-input-specific disabled CSS.
A server-rendered value is formatted once on connect.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="##### ######">
<label class="form-label" for="masked-phone-disabled">Parent's mobile number</label>
<input type="tel" id="masked-phone-disabled" name="parent_phone_locked" class="form-control"
value="07123456789" disabled aria-describedby="masked-phone-disabled-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-phone-disabled-help">This number is verified — contact the school office to change it.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><input type="tel" class="form-control" value="07123456789" disabled data-masked-input-target="input" ></code>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<%# Introductory callout %>
<div class="callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>MASKED INPUT:</strong> Format-as-you-type on a plain .form-control<br>
<strong>VARIANTS:</strong> UK phone | UK postcode | UPN | Custom mask | Invalid error | Disabled<br>
<strong>COMPOSES:</strong> .form-control + .form-label + .form-text + .is-invalid/.invalid-feedback
</p>
<p class="tw:mb-0 tw:text-sm">
Formatted identifiers take their canonical shape while the user types — group separators
are inserted automatically, letters uppercase where the format demands it, and messy
pasted values are stripped and reformatted. The caret is preserved through mid-value
edits, Backspace always deletes a real character (never bounces off a separator), and
partial input is never rejected (C05). Requires
<code>data-controller="masked-input"</code> with a declarative
<code>data-masked-input-mask-value</code> template (<code>#</code> digit,
<code>A</code> letter, <code>*</code> either; anything else is a literal).
</p>
</div>
<%# UK phone %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UK phone number</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Mask <code>"##### ######"</code>:</strong> UK mobile grouping (5+6). Typing
<code>07123456789</code> renders <code>07123 456789</code>; pasting
<code>"Tel: 07123-456-789"</code> strips to digits and reformats. The optional hidden
<code>data-masked-input-target="raw"</code> input carries the unformatted digits
(<code>07123456789</code>) for systems that want the canonical value — the visible
input is the submitted field.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="##### ######">
<label class="form-label" for="masked-phone">Parent's mobile number</label>
<input type="tel" id="masked-phone" name="parent_phone" class="form-control"
autocomplete="tel" aria-describedby="masked-phone-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<input type="hidden" name="parent_phone_raw" data-masked-input-target="raw">
<p class="form-text" id="masked-phone-help">UK mobile number, e.g. 07123 456789. We'll format it as you type.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="##### ######"><input type="tel" class="form-control" autocomplete="tel" aria-describedby="…" data-masked-input-target="input" data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input"><input type="hidden" data-masked-input-target="raw"></div></code>
</div>
</div>
<%# UK postcode %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UK postcode</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Format <code>"uk-postcode"</code>:</strong> the one named algorithmic formatter —
UK postcodes are variable-geometry (outward part 2–4 characters, inward always 3)
and can't be expressed as a fixed template. Letters uppercase as typed
(<code>sw1a1aa</code><code>SW1A1AA</code>) and the canonical space appears once
the shape completes (<code>SW1A 1AA</code>) — mid-entry the space never hops around and
partial input is never fought.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-format-value="uk-postcode">
<label class="form-label" for="masked-postcode">Home postcode</label>
<input type="text" id="masked-postcode" name="home_postcode" class="form-control"
autocomplete="postal-code" aria-describedby="masked-postcode-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-postcode-help">For example SW1A 1AA. Used to check your catchment area.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-format-value="uk-postcode"><input class="form-control" autocomplete="postal-code" ></div></code>
</div>
</div>
<%# UPN %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">UPN (Unique Pupil Number)</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Mask <code>"A############"</code>:</strong> one letter (uppercased on entry)
followed by 12 digits — no literals, so the formatted and raw values are identical.
A digit typed in the leading letter slot is discarded (character-class enforcement),
and characters beyond 13 are dropped.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="A############">
<label class="form-label" for="masked-upn">Child's UPN</label>
<input type="text" id="masked-upn" name="child_upn" class="form-control"
autocomplete="off" aria-describedby="masked-upn-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-upn-help">A letter followed by 12 digits, e.g. A123456789012. You'll find it on your child's school report or by asking their current school.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="A############"><input class="form-control" ></div></code>
</div>
</div>
<%# Custom mask %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Custom masks</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>The mask is declarative:</strong> any fixed-shape code works by supplying a
template — nothing is hardcoded in the controller. Here a bank sort code
(<code>"##-##-##"</code>) shows non-space literals being inserted and deleted
transparently: Backspace after a dash deletes the digit before it in one keypress.
</p>
</div>
<div class="masked-input tw:max-w-xs" data-controller="masked-input"
data-masked-input-mask-value="##-##-##">
<label class="form-label" for="masked-sort-code">Sort code</label>
<input type="text" id="masked-sort-code" name="sort_code" class="form-control"
inputmode="numeric" autocomplete="off" aria-describedby="masked-sort-code-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-sort-code-help">6 digits, e.g. 20-45-67. Shown on your bank card or statement.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div class="masked-input" data-controller="masked-input" data-masked-input-mask-value="##-##-##"><input class="form-control" inputmode="numeric" ></div></code>
</div>
</div>
<%# Invalid error %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Invalid error</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Error state:</strong> markup-only <code>.is-invalid</code> +
<code>aria-invalid="true"</code> on the input (reusing
<code>.form-control.is-invalid</code> — no bespoke error CSS), with
<code>aria-describedby</code> pointing at the <code>.invalid-feedback</code> text.
The controller never <em>sets</em> the error (validity is the form's decision at
submit); the first correcting keystroke clears it and hides the error text (C08).
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-format-value="uk-postcode">
<label class="form-label" for="masked-postcode-invalid">Home postcode</label>
<input type="text" id="masked-postcode-invalid" name="home_postcode_invalid"
class="form-control is-invalid" value="SW99" aria-invalid="true"
autocomplete="postal-code" aria-describedby="masked-postcode-invalid-error"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="invalid-feedback" id="masked-postcode-invalid-error" data-masked-input-target="error">Enter a full UK postcode, e.g. SW1A 1AA.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><input class="form-control is-invalid" aria-invalid="true" aria-describedby="postcode-error" ><p class="invalid-feedback" id="postcode-error" data-masked-input-target="error">Enter a full UK postcode, e.g. SW1A 1AA.</p></code>
</div>
</div>
<%# Disabled %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Disabled</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Disabled:</strong> real <code>[disabled]</code> attribute — greys out via the
shared <code>.form-control:disabled</code> rule, no masked-input-specific disabled CSS.
A server-rendered value is formatted once on connect.
</p>
</div>
<div class="masked-input tw:max-w-sm" data-controller="masked-input"
data-masked-input-mask-value="##### ######">
<label class="form-label" for="masked-phone-disabled">Parent's mobile number</label>
<input type="tel" id="masked-phone-disabled" name="parent_phone_locked" class="form-control"
value="07123456789" disabled aria-describedby="masked-phone-disabled-help"
data-masked-input-target="input"
data-action="input->masked-input#input keydown->masked-input#keydown compositionend->masked-input#input">
<p class="form-text" id="masked-phone-disabled-help">This number is verified — contact the school office to change it.</p>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><input type="tel" class="form-control" value="07123456789" disabled data-masked-input-target="input" ></code>
</div>
</div>
</div>