semantic-forms 5.1.11 → 5.1.12

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.
@@ -106,6 +106,32 @@
106
106
  </dl>
107
107
  </form>
108
108
 
109
+ <h5>Add inline buttons</h5>
110
+
111
+ <p>Include a button or input with the type "submit" in the <code><!--#<dd>--></code> element to place it next to the input:</p>
112
+
113
+ <pre><code class='language-html' lang='html'><escape>
114
+ <form class="semanticForms" method="post">
115
+ <dl>
116
+ <dt><label for="email">Email address</label></dt>
117
+ <dd>
118
+ <input id="email" name="email" type="email" placeholder="Enter an email address" autocomplete="off">
119
+ <button type="submit">Sign up</button>
120
+ </dd>
121
+ </dl>
122
+ </form>
123
+ </escape></code></pre>
124
+
125
+ <form class="semanticForms" method="post">
126
+ <dl>
127
+ <dt><label for="email">Email address</label></dt>
128
+ <dd>
129
+ <input id="email" name="email" type="email" placeholder="Enter an email address" autocomplete="off">
130
+ <button type="submit">Sign up!</button>
131
+ </dd>
132
+ </dl>
133
+ </form>
134
+
109
135
  <h5 id="custominputfields">Customizing input fields</h5>
110
136
 
111
137
  <p>By default, input fields will display an X icon to clear the text and password fields will also display a show/hide toggle for displaying the password in plain text. You can customize this behavior as follows:</p>
@@ -121,6 +147,13 @@
121
147
  <li>Note that checkboxes and radios should have a <code>title</code> attribute on the label instead of the inputs.</li>
122
148
  </ul>
123
149
  </li>
150
+ <li><p>Allow fixed-width inputs to grow/shrink to their longest content by applying a <code>data-max-content</code> attribute to the input.</p></li>
151
+ <li>
152
+ <p>Create a one-line text input that grows in height by applying a <code>data-auto-grow</code> attribute to a <code>textarea</code> or <code>input</code> (with type "text") element.</p>
153
+ <ul>
154
+ <li>Note that pressing <kbd>Enter</kbd> with this attribute will attempt to submit the form. Use <kbd>Shift + Enter</kbd> to add new lines.</li>
155
+ </ul>
156
+ </li>
124
157
  </ul>
125
158
 
126
159
  <p>You can also disable float labels on a per-field basis with the <code>no-float-label</code> class:</p>
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "url": "https://github.com/rooseveltframework/semantic-forms/graphs/contributors"
9
9
  }
10
10
  ],
11
- "version": "5.1.11",
11
+ "version": "5.1.12",
12
12
  "files": [
13
13
  "dist",
14
14
  "semanticForms.scss",
package/semanticForms.js CHANGED
@@ -7,7 +7,7 @@ const semanticForms = () => {
7
7
 
8
8
  const passwordShow = '<svg fill="none" height="256" viewBox="0 0 24 24" width="256" xmlns="http://www.w3.org/2000/svg"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m1 12s4-8 11-8 11 8 11 8"/><path d="m1 12s4 8 11 8 11-8 11-8"/><circle cx="12" cy="12" r="3"/></g></svg>'
9
9
  const passwordHide = '<svg fill="none" height="256" viewBox="0 0 24 24" width="256" xmlns="http://www.w3.org/2000/svg"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m2 2 20 20"/><path d="m6.71277 6.7226c-3.04798 2.07267-4.71277 5.2774-4.71277 5.2774s3.63636 7 10 7c2.0503 0 3.8174-.7266 5.2711-1.7116m-6.2711-12.23018c.3254-.03809.6588-.05822 1-.05822 6.3636 0 10 7 10 7s-.6918 1.3317-2 2.8335"/><path d="m14 14.2362c-.5308.475-1.2316.7639-2 .7639-1.6569 0-3-1.3431-3-3 0-.8237.33193-1.5698.86932-2.11192"/></g></svg>'
10
- const helpTextIcon = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" version="1.1" style="overflow:visible;margin-top:1px;"><rect width="16" height="16" fill="none"/><path fill="currentColor" d="M8,10.5c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C9,10.948,8.552,10.5,8,10.5z M8,0 C3.582,0,0,3.582,0,8c0,4.418,3.582,8,8,8s8-3.582,8-8C16,3.582,12.418,0,8,0z M12.243,12.243C11.109,13.376,9.603,14,8,14 s-3.109-0.624-4.243-1.757C2.624,11.109,2,9.603,2,8s0.624-3.109,1.757-4.243C4.891,2.624,6.397,2,8,2s3.109,0.624,4.243,1.757 C13.376,4.891,14,6.397,14,8C14,9.603,13.376,11.109,12.243,12.243z M7.927,3.755c-2.248,0-2.76,1.695-2.802,2.906h1.571 c0.028-0.256,0.101-1.418,1.221-1.418c0.672,0,1.206,0.406,1.206,1.175c0,0.695-0.724,1.155-1.303,1.711 C7.241,8.685,7.168,9.325,7.168,9.824V10c0.146,0,1.615,0,1.615,0V9.824c0-1.256,1.967-1.594,1.967-3.541 C10.75,5.059,9.874,3.755,7.927,3.755z"/></svg>'
10
+ const helpTextIcon = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" version="1.1" style="overflow:visible;"><rect width="16" height="16" fill="none"/><path fill="currentColor" d="M8,10.5c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C9,10.948,8.552,10.5,8,10.5z M8,0 C3.582,0,0,3.582,0,8c0,4.418,3.582,8,8,8s8-3.582,8-8C16,3.582,12.418,0,8,0z M12.243,12.243C11.109,13.376,9.603,14,8,14 s-3.109-0.624-4.243-1.757C2.624,11.109,2,9.603,2,8s0.624-3.109,1.757-4.243C4.891,2.624,6.397,2,8,2s3.109,0.624,4.243,1.757 C13.376,4.891,14,6.397,14,8C14,9.603,13.376,11.109,12.243,12.243z M7.927,3.755c-2.248,0-2.76,1.695-2.802,2.906h1.571 c0.028-0.256,0.101-1.418,1.221-1.418c0.672,0,1.206,0.406,1.206,1.175c0,0.695-0.724,1.155-1.303,1.711 C7.241,8.685,7.168,9.325,7.168,9.824V10c0.146,0,1.615,0,1.615,0V9.824c0-1.256,1.967-1.594,1.967-3.541 C10.75,5.059,9.874,3.755,7.927,3.755z"/></svg>'
11
11
 
12
12
  const nodeNameLookup = ['TEXTAREA', 'SELECT']
13
13
  const inputTypeLookup = ['checkbox', 'color', 'date', 'datetime-local', 'email', 'file', 'image', 'month', 'number', 'password', 'radio', 'range', 'search', 'tel', 'text', 'time', 'url', 'week']
@@ -21,7 +21,7 @@ const semanticForms = () => {
21
21
 
22
22
  // update each input in the semantic form
23
23
  const inputs = Array.from(form.querySelectorAll('input, textarea, select'))
24
- for (const input of inputs) {
24
+ for (let input of inputs) {
25
25
  // ignore input if it has previously been formatted
26
26
  if (input.classList.contains('semanticform') || !input.id) continue
27
27
 
@@ -45,7 +45,6 @@ const semanticForms = () => {
45
45
  input.classList.add('semanticform')
46
46
 
47
47
  // #region create labels
48
-
49
48
  if (type === 'checkbox' || type === 'radio') {
50
49
  // recursively find <dd> element
51
50
  let dd = input.parentNode
@@ -122,7 +121,31 @@ const semanticForms = () => {
122
121
  }
123
122
  // #endregion
124
123
 
125
- // standard inputs
124
+ // #region standard inputs
125
+ // check for auto-grow attribute on textareas
126
+ if (input.getAttribute('data-auto-grow') !== null) {
127
+ // progressively enhance inputs into textareas
128
+ if (input.nodeName === 'INPUT' && input.type === 'text') {
129
+ const newInput = document.createElement('textarea')
130
+ newInput.id = input.id
131
+ newInput.class = input.class
132
+ newInput.innerText = input.value
133
+ newInput.setAttribute('data-auto-grow', '')
134
+ input.replaceWith(newInput)
135
+ input = newInput
136
+
137
+ }
138
+
139
+ if (input.nodeName === 'TEXTAREA') {
140
+ // when pressing enter while this input is focused, we want to submit
141
+ input.addEventListener('keypress', (e) => {
142
+ if (e.key !== 'Enter' || (e.key === 'Enter' && e.shiftKey)) return
143
+ e.preventDefault()
144
+ form.requestSubmit()
145
+ })
146
+ }
147
+ }
148
+
126
149
  if (type !== 'checkbox' && type !== 'radio') {
127
150
  if (!input.getAttribute('placeholder')) input.setAttribute('placeholder', ' ')
128
151
 
@@ -139,7 +162,7 @@ const semanticForms = () => {
139
162
  continue
140
163
  }
141
164
 
142
- // #region clear button
165
+ // #region input clear button
143
166
  if (input.nodeName !== 'SELECT' && type !== 'range') {
144
167
  const clearBtn = document.createElement('button')
145
168
  clearBtn.type = 'button'
@@ -171,6 +194,22 @@ const semanticForms = () => {
171
194
  dd.classList.remove(match)
172
195
  div.classList.add(match)
173
196
  }
197
+
198
+ // check for max-content attribute
199
+ // this may be removed once fully supported in Firefox and Safari: https://caniuse.com/wf-field-sizing
200
+ if (input.getAttribute('data-max-content') !== null) {
201
+ if (!('fieldSizing' in document.createElement('input').style)) {
202
+ const adjustWidth = () => {
203
+ const value = input.value !== '' ? input.value : input.placeholder
204
+ const width = value.length * 8 + 40
205
+ input.style.width = width + 'px'
206
+ input.style.maxWidth = '100%'
207
+ div.style.width = width + 'px'
208
+ }
209
+ adjustWidth()
210
+ input.addEventListener('input', adjustWidth)
211
+ }
212
+ }
174
213
 
175
214
  div.append(dt, dd)
176
215
  dl.append(div)
@@ -178,6 +217,7 @@ const semanticForms = () => {
178
217
  // determine visibility of newly created <div>
179
218
  if (dt.style.display === 'none' && dd.style.display === 'none') div.style.display = 'none'
180
219
  }
220
+ // #endregion
181
221
 
182
222
  // handle file input clear btn, cannot be handled with CSS
183
223
  if (type === 'file') {
@@ -301,6 +341,22 @@ const semanticForms = () => {
301
341
  input.dispatchEvent(new Event('input', { bubbles: true }))
302
342
  }
303
343
 
344
+ // progressively enhance textarea for Firefox and Safari
345
+ // this may be removed once fully supported in Firefox and Safari: https://caniuse.com/wf-field-sizing
346
+ if (input.getAttribute('data-auto-grow') !== null) {
347
+ const adjustHeight = () => {
348
+ if (input.value.length) {
349
+ input.style.height = input.scrollHeight + 'px'
350
+ } else {
351
+ input.style.height = window.getComputedStyle(form).getPropertyValue('--semanticFormsInputHeight')
352
+ }
353
+ }
354
+
355
+ // set initial height to semantic-forms CSS variable
356
+ input.style.height = window.getComputedStyle(form).getPropertyValue('--semanticFormsInputHeight')
357
+ input.addEventListener('input', adjustHeight)
358
+ }
359
+
304
360
  // shifts the clear button to the right if a scrollbar is present
305
361
  const shiftClearBtn = () => {
306
362
  const clearBtn = input.parentElement?.querySelector('button.clear')
@@ -96,6 +96,10 @@ table.semanticForms.light {
96
96
  container-type: inline-size;
97
97
  container-name: semanticForm;
98
98
 
99
+ @supports (interpolate-size: allow-keywords) { // https://caniuse.com/wf-interpolate-size
100
+ interpolate-size: allow-keywords;
101
+ }
102
+
99
103
  // due to the specificity of some of these rules, [hidden] won't actually hide things, so we're forcing the issue
100
104
  [hidden] {
101
105
  display: none !important;
@@ -254,6 +258,10 @@ table.semanticForms.light {
254
258
  line-height: 1.5;
255
259
  width: 100%;
256
260
  min-height: 38px;
261
+
262
+ &[data-auto-grow] {
263
+ field-sizing: content;
264
+ }
257
265
  }
258
266
 
259
267
  input[type="search"] {
@@ -439,7 +447,7 @@ table.semanticForms.light {
439
447
  }
440
448
  }
441
449
 
442
- // #region summary
450
+ // #region details
443
451
  details {
444
452
  box-sizing: border-box; // ensure sizings match across browsers
445
453
  position: relative;
@@ -452,14 +460,26 @@ table.semanticForms.light {
452
460
  padding: 20px 10px 10px 10px;
453
461
  margin-bottom: 15px;
454
462
  min-height: calc(var(--semanticFormsFontSize) + 20px);
455
-
463
+
456
464
  &::details-content {
457
465
  visibility: hidden;
458
466
  opacity: 0;
459
467
  transition: opacity 250ms ease-in, visibility 0ms ease-in 250ms;
460
468
  }
469
+
470
+ @supports (interpolate-size: allow-keywords) { // https://caniuse.com/wf-interpolate-size
471
+ transition: opacity 250ms ease-in, visibility 0ms ease-in 250ms, height 250ms;
472
+
473
+ &::details-content {
474
+ height: 0;
475
+ overflow: hidden;
476
+ transition: height 250ms, content-visibility 250ms;
477
+ transition-behavior: allow-discrete;
478
+ }
479
+ }
461
480
 
462
481
  summary {
482
+ cursor: pointer;
463
483
  margin: 0;
464
484
  line-height: 1;
465
485
  position: absolute;
@@ -486,20 +506,24 @@ table.semanticForms.light {
486
506
  transition: 250ms transform ease;
487
507
  }
488
508
  }
489
- }
490
509
 
491
- details[open] {
492
- padding-top: 35px; // TODO: remove this when animated detail label is reintroduced
510
+ &[open] {
511
+ &::details-content {
512
+ visibility: visible;
513
+ opacity: 1;
514
+ transition: opacity 250ms ease-in, visibility 0ms ease-in 0ms;
515
+ }
493
516
 
494
- &::details-content {
495
- visibility: visible;
496
- opacity: 1;
497
- transition: opacity 250ms ease-in, visibility 0ms ease-in 0ms;
498
- }
517
+ @supports (interpolate-size: allow-keywords) {
518
+ &::details-content {
519
+ height: auto;
520
+ }
521
+ }
499
522
 
500
- summary {
501
- &::after {
502
- transform: rotate(90deg);
523
+ summary {
524
+ &::before {
525
+ transform: rotate(90deg);
526
+ }
503
527
  }
504
528
  }
505
529
  }
@@ -507,10 +531,6 @@ table.semanticForms.light {
507
531
  details[open], summary {
508
532
  margin-bottom: 10px;
509
533
  }
510
-
511
- summary {
512
- cursor: pointer;
513
- }
514
534
  // #endregion
515
535
 
516
536
  // update for scrollbars
@@ -565,6 +585,42 @@ table.semanticForms.light {
565
585
  &:not(.singleCheckbox, .singleRadio) {
566
586
  display: flex;
567
587
  flex-direction: column;
588
+
589
+ // unless there is a button present, which will be placed beside the input
590
+ &:has(button:not(.clear, .show), input[type="submit"]:not(.clear, .show)) {
591
+ display: grid;
592
+ grid-template-columns: 2fr 1fr;
593
+
594
+ button.clear, button.show {
595
+ right: 36%; // adjust clear/show button to grid
596
+ }
597
+
598
+ input:not([type="submit"]), select, textarea {
599
+ grid-row: 1 / 2;
600
+ grid-column: 1 / 2;
601
+ }
602
+
603
+ button:not(.clear, .show),
604
+ input[type="submit"]:not(.clear, .show) {
605
+ grid-row: 1 / 2;
606
+ grid-column: 2 / 3;
607
+ width: 100%;
608
+ max-width: 100%;
609
+ padding: 10px; // reduce default padding to allow more button text to show
610
+ margin-top: var(--semanticFormsInputTopMargin);
611
+ height: var(--semanticFormsInputHeight);
612
+ text-overflow: ellipsis;
613
+ white-space: nowrap;
614
+ overflow: hidden;
615
+ display: inline-block;
616
+ }
617
+
618
+ // TODO: handle help text as well (will need to be grid-columns: 0 2 or whatever it is)
619
+ label:nth-of-type(2) {
620
+ grid-row: 2 / 3;
621
+ grid-column: 1 / -1;
622
+ }
623
+ }
568
624
  }
569
625
 
570
626
  &.singleCheckbox,
@@ -581,7 +637,7 @@ table.semanticForms.light {
581
637
  // single checkbox subtext
582
638
  label:nth-of-type(2) {
583
639
  grid-column: 1 / -1;
584
- padding-left: 20px;
640
+ padding: 0 10px;
585
641
  font-size: small;
586
642
  color: var(--semanticFormsTextColor);
587
643
  }
@@ -656,6 +712,8 @@ table.semanticForms.light {
656
712
  }
657
713
 
658
714
  span.help {
715
+ display: grid;
716
+ place-items: center;
659
717
  cursor: help;
660
718
  pointer-events: auto;
661
719
 
@@ -682,16 +740,8 @@ table.semanticForms.light {
682
740
  &:focus:not([type=checkbox], [type=radio], .no-float-label) ~ label:first-of-type,
683
741
  &:not(:placeholder-shown):not(.no-float-label):not([type=checkbox]):not([type=radio]) ~ label:first-of-type {
684
742
  color: var(--semanticFormsTextColor) !important;
685
- // TODO: finish this work on making the help icon responsive
686
- // width: 100%;
687
- // width: calc(100% + 20px);
688
743
  transform: translateY(-150%) scale(0.7);
689
-
690
- // span.required,
691
- // span.help {
692
- // position: static;
693
- // right: auto;
694
- // }
744
+ width: 100%;
695
745
  }
696
746
  }
697
747
 
@@ -732,7 +782,7 @@ table.semanticForms.light {
732
782
  // subtext
733
783
  label:nth-of-type(2) {
734
784
  margin-top: -5px;
735
- padding-left: 20px;
785
+ padding: 0 10px;
736
786
  font-size: small;
737
787
  color: var(--semanticFormsTextColor);
738
788
  }
@@ -795,30 +845,15 @@ table.semanticForms.light {
795
845
  align-items: center;
796
846
  gap: 5px;
797
847
 
798
- // TODO: same as below
799
- // &:has(span.help) {
800
- // width: 80%;
801
- // padding-right: 20px;
802
- // }
803
-
804
- // &:has(span.required) {
805
- // width: 80%;
806
- // padding-right: 10px;
807
- // }
808
-
809
848
  span.required {
810
- // TODO: this places the required asterisk too far to the right when the float label is shrunk
811
- // position: absolute;
812
- // right: 0;
813
849
  cursor: help;
814
850
  pointer-events: auto;
815
851
  color: red;
816
852
  }
817
853
 
818
854
  span.help {
819
- // TODO: this places the help icon too far to the right when the float label is shrunk
820
- // position: absolute;
821
- // right: 0;
855
+ display: grid;
856
+ place-items: center;
822
857
  cursor: help;
823
858
  pointer-events: auto;
824
859
 
@@ -826,16 +861,6 @@ table.semanticForms.light {
826
861
  width: 80%;
827
862
  }
828
863
  }
829
-
830
- // // TODO: cover the case where an input is required AND has help text
831
- // &:has(span.required, span.help) {
832
- // width: 80%;
833
- // padding-right: 30px;
834
-
835
- // span.required {
836
- // right: 18px;
837
- // }
838
- // }
839
864
  }
840
865
  }
841
866
 
@@ -844,6 +869,9 @@ table.semanticForms.light {
844
869
  position: relative;
845
870
 
846
871
  label {
872
+ display: flex;
873
+ align-items: center;
874
+ gap: 5px;
847
875
  z-index: 2; // ensure the hoverable icon is interactable
848
876
  user-select: auto;
849
877
  color: var(--semanticFormsTextColor);
@@ -857,16 +885,11 @@ table.semanticForms.light {
857
885
  overflow: hidden;
858
886
  text-overflow: ellipsis;
859
887
  min-width: 0;
860
- width: calc(100% + 20px);
861
-
862
- // TODO: remove this? // &:has(span.help) {
863
- // width: 100%;
864
- // padding-right: 20px;
865
- // }
888
+ width: 100%;
866
889
 
867
890
  span.help {
868
- // TODO: remove this? // position: absolute;
869
- // right: 0;
891
+ display: grid;
892
+ place-items: center;
870
893
  cursor: help;
871
894
  pointer-events: auto;
872
895
  }
@@ -881,14 +904,28 @@ table.semanticForms.light {
881
904
  }
882
905
 
883
906
  label > span {
884
- // TODO: remove this? // position: absolute;
885
- // right: 0;
886
907
  margin-left: 5px;
887
908
  cursor: help;
888
909
  pointer-events: auto;
889
910
  color: red;
890
911
  }
912
+ }
913
+ }
891
914
 
915
+ // data-max-content CSS
916
+ &:has([data-max-content]) {
917
+ max-width: max-content;
918
+ min-width: 150px;
919
+
920
+ dd {
921
+ width: max-content;
922
+
923
+ input, select {
924
+ // this is not currently supported in FireFox or Safari, and is progressively enhanced with JS
925
+ field-sizing: content;
926
+ min-width: 150px;
927
+ max-width: max-content;
928
+ }
892
929
  }
893
930
  }
894
931
  }
@@ -1196,71 +1233,71 @@ table.semanticForms.light {
1196
1233
 
1197
1234
  // #region low flow form
1198
1235
  &.lowFlow {
1199
- gap: 5px;
1236
+ gap: 5px;
1200
1237
 
1201
- dl {
1202
- grid-auto-flow: dense;
1203
- }
1238
+ dl {
1239
+ grid-auto-flow: dense;
1240
+ }
1204
1241
 
1205
- // 1, 4, 7, ...
1206
- & > dt:nth-of-type(2n + 1),
1207
- & > dd:nth-of-type(2n + 1) {
1208
- grid-column: 1;
1209
- }
1242
+ // 1, 4, 7, ...
1243
+ & > dt:nth-of-type(2n + 1),
1244
+ & > dd:nth-of-type(2n + 1) {
1245
+ grid-column: 1;
1246
+ }
1210
1247
 
1211
- // 2, 5, 8, ...
1212
- & > dt:nth-of-type(2n + 2),
1213
- & > dd:nth-of-type(2n + 2) {
1214
- grid-column: 2;
1215
- }
1248
+ // 2, 5, 8, ...
1249
+ & > dt:nth-of-type(2n + 2),
1250
+ & > dd:nth-of-type(2n + 2) {
1251
+ grid-column: 2;
1252
+ }
1216
1253
 
1217
- dt {
1218
- min-width: var(--semanticFormsInputMinWidth) !important; /* this matches the max-width of js-enabled inputs */
1254
+ dt {
1255
+ min-width: var(--semanticFormsInputMinWidth) !important; /* this matches the max-width of js-enabled inputs */
1219
1256
 
1220
- // add required asterisk
1221
- &:has(+ dd input:required) {
1222
- label::after {
1223
- content: ' *';
1224
- color: red;
1225
- }
1257
+ // add required asterisk
1258
+ &:has(+ dd input:required) {
1259
+ label::after {
1260
+ content: ' *';
1261
+ color: red;
1226
1262
  }
1227
1263
  }
1264
+ }
1228
1265
 
1229
1266
 
1230
- dd {
1231
- margin-bottom: 10px;
1232
- min-width: var(--semanticFormsInputMinWidth) !important; /* this matches the max-width of js-enabled inputs */
1267
+ dd {
1268
+ margin-bottom: 10px;
1269
+ min-width: var(--semanticFormsInputMinWidth) !important; /* this matches the max-width of js-enabled inputs */
1233
1270
 
1234
- // nudge single checkboxes to match checkbox groups
1235
- &:not(.checkboxes) {
1236
- input[type=checkbox] {
1237
- margin-left: 10px;
1238
- }
1271
+ // nudge single checkboxes to match checkbox groups
1272
+ &:not(.checkboxes) {
1273
+ input[type=checkbox] {
1274
+ margin-left: 10px;
1239
1275
  }
1276
+ }
1240
1277
 
1241
- // remove "x" padding
1242
- input:not([type=submit], [type=reset], [type=image], [type=checkbox], [type=radio], [type=range]),
1243
- select,
1244
- textarea {
1245
- padding-right: 6px;
1246
- }
1278
+ // remove "x" padding
1279
+ input:not([type=submit], [type=reset], [type=image], [type=checkbox], [type=radio], [type=range]),
1280
+ select,
1281
+ textarea {
1282
+ padding-right: 6px;
1283
+ }
1247
1284
 
1248
- // subtext
1249
- label {
1250
- margin-top: -5px;
1251
- font-size: small;
1252
- color: var(--semanticFormsPlaceholderColor);
1253
- }
1285
+ // subtext
1286
+ label {
1287
+ margin-top: -5px;
1288
+ font-size: small;
1289
+ color: var(--semanticFormsPlaceholderColor);
1254
1290
  }
1255
1291
  }
1292
+ }
1256
1293
 
1257
- .checkboxes ul,
1258
- .radios ul {
1259
- margin-top: var(--semanticFormsInputTopMargin);
1260
- }
1294
+ .checkboxes ul,
1295
+ .radios ul {
1296
+ margin-top: var(--semanticFormsInputTopMargin);
1261
1297
  }
1262
- // #endregion
1263
1298
  }
1299
+ // #endregion
1300
+ }
1264
1301
 
1265
1302
  // #region tables
1266
1303