diff --git a/js/tests/visual/floating-label.html b/js/tests/visual/floating-label.html index 734b31569808..4d993d9bca9e 100644 --- a/js/tests/visual/floating-label.html +++ b/js/tests/visual/floating-label.html @@ -10,380 +10,380 @@
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
+ -
+ -
+ -
+ -
- +
- +
- +
+ -
- +
- +
- +
+ -
- +
- +
- +
- +
+ -
+ -
+ -
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
+ -
+ -
+ -
+ -
- +
- +
- +
+ -
- +
- +
- +
+ -
- +
- +
- +
- +
+ -
+ -
+ -
diff --git a/scss/forms/_floating-labels.scss b/scss/forms/_floating-labels.scss index 1c15be2b3cd2..8f9b79aa805c 100644 --- a/scss/forms/_floating-labels.scss +++ b/scss/forms/_floating-labels.scss @@ -9,9 +9,9 @@ $form-floating-tokens: () !default; // stylelint-disable-next-line scss/dollar-variable-default $form-floating-tokens: defaults( ( - --form-floating-height: calc(3.5rem + (var(--border-width) * 2)), + --form-floating-height: calc(3.75rem + (var(--border-width) * 2)), --form-floating-line-height: 1.25, - --form-floating-padding-x: var(--btn-input-padding-x), + --form-floating-padding-x: calc(var(--btn-input-padding-x) * 1.25), --form-floating-padding-y: 1rem, --form-floating-input-padding-t: 1.625rem, --form-floating-input-padding-b: .625rem, @@ -54,13 +54,13 @@ $form-floating-tokens: defaults( text-overflow: ellipsis; white-space: nowrap; pointer-events: none; - border: var(--input-btn-border-width) solid transparent; // Required for aligning label's text with the input as it affects inner box model + border: var(--border-width) solid transparent; // Required for aligning label's text with the input as it affects inner box model transform-origin: 0 0; @include transition(var(--form-floating-transition)); } // Anchor the label to the top for textareas so it floats correctly at any height - > textarea ~ label { + > label:has(~ textarea) { align-items: flex-start; } @@ -87,23 +87,23 @@ $form-floating-tokens: defaults( } } - > .form-control:focus, - > .form-control:not(:placeholder-shown), - > .form-control-plaintext { - ~ label { - transform: var(--form-floating-label-transform); - } + // The label precedes the control in the DOM so screen readers announce it + // before the field's value, so we look forward with `:has()` to react to the + // control's state (focus, value, disabled, etc.). + > label:has(~ .form-control:focus), + > label:has(~ .form-control:not(:placeholder-shown)), + > label:has(~ .form-control-plaintext) { + transform: var(--form-floating-label-transform); } // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped - > .form-control:-webkit-autofill { - ~ label { - transform: var(--form-floating-label-transform); - } + > label:has(~ .form-control:-webkit-autofill) { + transform: var(--form-floating-label-transform); } - > textarea:focus, - > textarea:not(:placeholder-shown) { - ~ label::after { + + > label:has(~ textarea:focus), + > label:has(~ textarea:not(:placeholder-shown)) { + &::after { position: absolute; inset: var(--form-floating-padding-y) calc(var(--form-floating-padding-x) * .5); z-index: -1; @@ -113,18 +113,16 @@ $form-floating-tokens: defaults( @include border-radius(var(--btn-input-border-radius)); } } - > textarea:disabled ~ label::after { + > label:has(~ textarea:disabled)::after { background-color: var(--form-floating-label-disabled-bg); } - > .form-control-plaintext { - ~ label { - border-width: var(--control-border-width) 0; // Required to properly position label text - as explained above - } + > label:has(~ .form-control-plaintext) { + border-width: var(--control-border-width) 0; // Required to properly position label text - as explained above } - > :disabled ~ label, - > .form-control:disabled ~ label { // Required for `.form-control`s because of specificity + > label:has(~ :disabled), + > label:has(~ .form-control:disabled) { // Required for `.form-control`s because of specificity color: var(--form-floating-label-disabled-color); } } diff --git a/scss/forms/_form-control.scss b/scss/forms/_form-control.scss index cd01f82954d7..9eedb19866e5 100644 --- a/scss/forms/_form-control.scss +++ b/scss/forms/_form-control.scss @@ -168,6 +168,13 @@ $form-control-sizes: defaults( // text (without any border, background color, focus indicator) .form-control-plaintext { + // Plaintext is a standalone class (not combined with `.form-control`), so it + // needs its own copy of the control tokens. Without them the `var(--control-*)` + // references below are invalid and fall back to their initial values (e.g. + // `border-width: medium`), which adds phantom inline borders and misaligns the + // text from a floating label. + @include tokens($form-control-tokens); + display: block; width: 100%; padding: var(--control-padding-y) 0; diff --git a/site/src/assets/examples/cheatsheet/index.astro b/site/src/assets/examples/cheatsheet/index.astro index 707d73b797bd..315f6e543cb9 100644 --- a/site/src/assets/examples/cheatsheet/index.astro +++ b/site/src/assets/examples/cheatsheet/index.astro @@ -505,12 +505,12 @@ export const body_class = 'bg-body-tertiary'
- +
- +
`} /> diff --git a/site/src/assets/examples/dialogs/index.astro b/site/src/assets/examples/dialogs/index.astro index 22261de5f350..22b75c2802ac 100644 --- a/site/src/assets/examples/dialogs/index.astro +++ b/site/src/assets/examples/dialogs/index.astro @@ -109,12 +109,12 @@ export const extra_css = ['dialogs.css']
- +
- +
By clicking Sign up, you agree to the terms of use. diff --git a/site/src/assets/examples/heroes/index.astro b/site/src/assets/examples/heroes/index.astro index a49b2df6ecc7..f518f6469540 100644 --- a/site/src/assets/examples/heroes/index.astro +++ b/site/src/assets/examples/heroes/index.astro @@ -67,12 +67,12 @@ export const extra_css = ['heroes.css']
- +
- +
diff --git a/site/src/assets/examples/sign-in/index.astro b/site/src/assets/examples/sign-in/index.astro index bbf3e0c5fd8a..cfd2436a3ac8 100644 --- a/site/src/assets/examples/sign-in/index.astro +++ b/site/src/assets/examples/sign-in/index.astro @@ -12,12 +12,12 @@ export const body_class = 'd-flex align-items-center py-4 bg-body-tertiary'

Please sign in

- +
- +
diff --git a/site/src/content/docs/forms/floating-labels.mdx b/site/src/content/docs/forms/floating-labels.mdx index 36d780d281e1..c648ad9fdb5b 100644 --- a/site/src/content/docs/forms/floating-labels.mdx +++ b/site/src/content/docs/forms/floating-labels.mdx @@ -11,29 +11,29 @@ Wrap a pair of `` and `
- +
`} /> When there’s a `value` already defined, `
`} /> To set a custom height on your ` +
`} /> ## Selects @@ -57,13 +57,13 @@ To set a custom height on your ` +
- +
+ -
`} /> ## Readonly plaintext @@ -97,12 +97,12 @@ Add the `disabled` boolean attribute on an input, a textarea or a select to give Floating labels also support `.form-control-plaintext`, which can be helpful for toggling from an editable `` to a plaintext value without affecting the page layout. - +
- +
`} /> ## Input groups @@ -112,8 +112,8 @@ Floating labels also support `.input-group`. @
- +
`} /> @@ -123,8 +123,8 @@ When using `.input-group` and `.form-floating` along with form validation, place
@
- +
@@ -139,19 +139,19 @@ When working with the Bootstrap grid system, be sure to place form elements with
- +
+ -
`} /> diff --git a/site/src/content/docs/forms/validation.mdx b/site/src/content/docs/forms/validation.mdx index 43dee7092d70..6984a7b5a15f 100644 --- a/site/src/content/docs/forms/validation.mdx +++ b/site/src/content/docs/forms/validation.mdx @@ -351,8 +351,8 @@ Validation styles are available for the following form controls and components:
- +
Example invalid floating label feedback