diff --git a/scss/_variables.scss b/scss/_variables.scss index a7fdcf9c6e..2da092a7a0 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -942,8 +942,6 @@ $form-label-font-style: null !default; $form-label-font-weight: null !default; $form-label-color: null !default; $form-label-disabled-color: var(--#{$prefix}color-content-disabled) !default; // OUDS mod -$form-label-required-margin-left: .1875rem !default; // OUDS mod -$form-label-required-color: var(--#{$prefix}primary) !default; // OUDS mod // scss-docs-end form-label-variables // scss-docs-start form-helper-variables diff --git a/scss/forms/_labels.scss b/scss/forms/_labels.scss index 7a761ac3bb..d99439f7b0 100644 --- a/scss/forms/_labels.scss +++ b/scss/forms/_labels.scss @@ -18,8 +18,9 @@ .is-required::after { position: absolute; - margin-left: $form-label-required-margin-left; - color: $form-label-required-color; + margin-left: 4px; + font-weight: $ouds-font-weight-system-web-strong; + color: $ouds-color-content-status-negative; content: "*"; } diff --git a/scss/forms/_select-input.scss b/scss/forms/_select-input.scss index 3189c49ad6..a3d40acf7f 100644 --- a/scss/forms/_select-input.scss +++ b/scss/forms/_select-input.scss @@ -124,7 +124,7 @@ position: absolute; top: 50%; z-index: 1; - max-width: calc(100% - var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-padding-x) - var(--#{$prefix}text-input-trailing-action-width) - var(--#{$prefix}text-input-column-gap)); + width: calc(100% - var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-padding-x) - var(--#{$prefix}text-input-trailing-action-width) - var(--#{$prefix}text-input-column-gap)); max-height: 100%; overflow: hidden; text-overflow: ellipsis; diff --git a/scss/forms/_text-input.scss b/scss/forms/_text-input.scss index 2fccce3d93..1fb6014668 100644 --- a/scss/forms/_text-input.scss +++ b/scss/forms/_text-input.scss @@ -201,6 +201,19 @@ text-overflow: ellipsis; white-space: nowrap; @include get-font-size("label-small"); + + // stylelint-disable-next-line selector-no-qualifying-type + &.is-required { + position: relative; + width: fit-content; + max-width: 100%; + padding-right: 7px; + + &::after { + right: 0; + margin-left: 3px; + } + } } } @@ -290,13 +303,7 @@ &:has(> button), &:has(.loading-indeterminate, .loading-determinate) { - padding-right: calc(var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-border-width-left)); - - > .text-input-field, - > .input-container, - > label { - padding-right: calc(var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); - } + padding-right: calc(var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-border-width-left) + var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); } // Invalid text inputs @@ -304,21 +311,11 @@ --#{$prefix}text-input-border-color: var(--#{$prefix}color-action-negative-enabled); --#{$prefix}text-input-label-color: var(--#{$prefix}color-action-negative-enabled); - padding-right: calc(var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-border-width-left)); - - .text-input-field, - .input-container, - label { - padding-right: calc(var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); - } + padding-right: calc(var(--#{$prefix}text-input-trailing-action-padding-right) - var(--#{$prefix}text-input-border-width-left) + var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); &:has(> button), &:has(.loading-indeterminate, .loading-determinate) { - .text-input-field, - .input-container, - label { - padding-right: calc($ouds-button-size-icon-only + var(--#{$prefix}text-input-column-gap-trailing-error) + var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); - } + padding-right: calc($ouds-button-size-icon-only + var(--#{$prefix}text-input-column-gap-trailing-error) + var(--#{$prefix}text-input-trailing-action-width) + var(--#{$prefix}text-input-column-gap)); } &::after { @@ -477,6 +474,19 @@ content: ""; background-color: transparent; } + + // stylelint-disable-next-line selector-no-qualifying-type + &.is-required { + position: relative; + width: fit-content; + max-width: 100%; + padding-right: 7px; + + &::after { + right: 0; + margin-left: 3px; + } + } } .text-area-field { diff --git a/site/src/components/shortcodes/MandatoryFieldIndication.astro b/site/src/components/shortcodes/MandatoryFieldIndication.astro new file mode 100644 index 0000000000..bb7b16deb2 --- /dev/null +++ b/site/src/components/shortcodes/MandatoryFieldIndication.astro @@ -0,0 +1,27 @@ +--- +/* + * Outputs mandatory fields indication + */ + +import {getConfig} from "@libs/config.ts"; +interface Props { + /** + * The component name that should be displayed. + */ + componentName?: string + +} + +import { getVersionedDocsPath } from '@libs/path' + +const { componentName } = Astro.props + +const name = (componentName ? componentName.toLowerCase() : "") + +const link = (componentName ? `https://r.orange.fr/r/S-ouds-doc-${componentName.replace(" ", "-")}` : "") + +--- + +

To indicate that a {name} is mandatory in a form, add the class .is-required to display a red asterisk at the end of the label.

+ +

For general rules about when to add mandatory fields indication, please refer to the {name} design guidelines and to the form validation documentation. In particular, do not forget to handle error messages.

diff --git a/site/src/content/docs/components/checkbox.mdx b/site/src/content/docs/components/checkbox.mdx index cce2a65068..8d17c4b2d0 100644 --- a/site/src/content/docs/components/checkbox.mdx +++ b/site/src/content/docs/components/checkbox.mdx @@ -293,9 +293,9 @@ You can align horizontally up to three checkboxes if their labels are short, add ### Max width -By default checkboxes will span the whole width of their parent container, to limit the width of the checkbox on wider parent container, add a `.component-max-width` to the `.checkbox-item` container. More information on checkbox sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-checkbox-responsiveness). +By default, checkboxes will span the whole width of their parent container, to limit the width of the checkbox on wider parent container, add a `.component-max-width` to the `.checkbox-item` container. More information on checkbox sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-checkbox-responsiveness). - +
@@ -660,3 +660,39 @@ For the standalone checkbox, we provide a completely different architecture to e
`} /> + +## Mandatory field indication + + + + +
+
+ +
+
+ +
+
+
+
+
+ Mandatory checkboxes +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
`} /> + diff --git a/site/src/content/docs/components/password-input.mdx b/site/src/content/docs/components/password-input.mdx index 8bb69e6d43..dc0f9870cc 100644 --- a/site/src/content/docs/components/password-input.mdx +++ b/site/src/content/docs/components/password-input.mdx @@ -124,7 +124,7 @@ A `placeholder` attribute is required on each `` as our CSS-only floating

Enter a password with at least 8 characters (without the DEV- prefix).

Password must be at least 8 characters (without the DEV- prefix).

-
+

Enter a password with at least 8 characters (without the DEV- prefix).

Password must be at least 8 characters (without the DEV- prefix).

+
+
+
+ + + +
`} /> diff --git a/site/src/content/docs/components/radio-button.mdx b/site/src/content/docs/components/radio-button.mdx index afaee0307f..e9a03ce27b 100644 --- a/site/src/content/docs/components/radio-button.mdx +++ b/site/src/content/docs/components/radio-button.mdx @@ -330,9 +330,9 @@ You can align horizontally up to three radio buttons if their labels are short, ### Max width -By default radio buttons will span the whole width of their parent container, to limit the width of the radio button on wider parent container, add a `.component-max-width` to the `.radio-button-item` container. More information on radio button sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-radio-button-responsiveness). +By default, radio buttons will span the whole width of their parent container, to limit the width of the radio button on wider parent container, add a `.component-max-width` to the `.radio-button-item` container. More information on radio button sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-radio-button-responsiveness). - +
@@ -604,3 +604,39 @@ For the standalone radio button, we provide a completely different architecture
`} /> + + +## Mandatory field indication + + + + +
+
+ +
+
+ +
+
+
+
+
+ Mandatory radio buttons +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
`} /> diff --git a/site/src/content/docs/components/select-input.mdx b/site/src/content/docs/components/select-input.mdx index 43ffbd4f53..06e5b76ee4 100644 --- a/site/src/content/docs/components/select-input.mdx +++ b/site/src/content/docs/components/select-input.mdx @@ -51,7 +51,7 @@ When there’s a value already defined, `
`} /> - + @@ -218,9 +218,9 @@ To display a helper link below selects, use a standard small link [with `.link` ### Max width -By default select inputs will span the whole width of their parent container, to limit the width of the select input on wider parent container, add a `.component-max-width` to the `.select-input` container. +By default, select inputs will span the whole width of their parent container, to limit the width of the select input on wider parent container, add a `.component-max-width` to the `.select-input` container. - +
`} /> + +## Mandatory field indication + + + + +
+ + +
+ `} /> + diff --git a/site/src/content/docs/components/switch.mdx b/site/src/content/docs/components/switch.mdx index f3884b2eda..478c0b7206 100644 --- a/site/src/content/docs/components/switch.mdx +++ b/site/src/content/docs/components/switch.mdx @@ -241,9 +241,9 @@ Put your switches on the opposite side with the `.form-check-reverse` modifier c ### Max width -By default switches will span the whole width of their parent container, to limit the width of the switch on wider parent container, add a `.component-max-width` to the `.switch-item` container. More information on switch sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-switch-responsiveness). +By default, switches will span the whole width of their parent container, to limit the width of the switch on wider parent container, add a `.component-max-width` to the `.switch-item` container. More information on switch sizing in the [design guidelines](https://r.orange.fr/r/S-ouds-doc-switch-responsiveness). - +
@@ -490,3 +490,43 @@ Progressively enhance your switches for mobile Safari (iOS 17.4+) by adding a `s `} /> Be sure to read more about [the switch attribute on the WebKit blog](https://webkit.org/blog/15054/an-html-switch-control/). Safari 17.4+ on macOS and iOS both have native-style switches in HTML while other browsers simply fall back to the standard checkbox appearance. Applying the attribute to a non-OUDS Web checkbox in more recent versions of Safari will render a native switch. + +## Mandatory field indication + + + + +
+
+ +
+
+ +
+
+ +
+
+ Mandatory switches +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
`} /> + + + + + diff --git a/site/src/content/docs/components/text-area.mdx b/site/src/content/docs/components/text-area.mdx index 5a0f101118..022174966d 100644 --- a/site/src/content/docs/components/text-area.mdx +++ b/site/src/content/docs/components/text-area.mdx @@ -123,9 +123,9 @@ To display a helper link below text areas, use a standard small link [with `.lin ### Max width -By default text areas will span the whole width of their parent container, to limit the width of the text area on wider parent container, add a `.component-max-width` to the `.text-input` container. +By default, text areas will span the whole width of their parent container, to limit the width of the text area on wider parent container, add a `.component-max-width` to the `.text-input` container. - +
@@ -223,3 +223,14 @@ To manually mark a text area as invalid, add `aria-invalid="true"` to a `.text-
`} /> + +## Mandatory field indication + + + + +
+ + +
+ `} /> diff --git a/site/src/content/docs/components/text-input.mdx b/site/src/content/docs/components/text-input.mdx index e351bd4816..dfcf4ba548 100644 --- a/site/src/content/docs/components/text-input.mdx +++ b/site/src/content/docs/components/text-input.mdx @@ -73,7 +73,7 @@ Add `.text-input-container-outlined` for a minimalist input with a transparent b `} /> - + `} /> @@ -203,7 +203,7 @@ To display a helper text below inputs, add a `.helper-text` as a sibling of a `. Form text below inputs can be styled with `.form-text`. If a block-level element will be used, a top margin is added for easy spacing from the inputs above. - Password + Password
Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji. @@ -211,7 +211,7 @@ To display a helper text below inputs, add a `.helper-text` as a sibling of a `. Inline text can use any typical inline HTML element (be it a ``, ``, or something else) with nothing more than the `.form-text` class. - +
@@ -323,9 +323,9 @@ A textual prefix or suffix can be added to an input by wrapping the `` in ### Max width -By default text inputs will span the whole width of their parent container, to limit the width of the text input on wider parent container, add a `.component-max-width` to the `.text-input` container. +By default, text inputs will span the whole width of their parent container, to limit the width of the text input on wider parent container, add a `.component-max-width` to the `.text-input` container. - +
@@ -398,7 +398,7 @@ Add the `disabled` boolean attribute on an input to give it a grayed out appeara Add the `disabled` boolean attribute on an input to give it a grayed out appearance, remove pointer events, and prevent focusing. - + `} /> @@ -450,7 +450,7 @@ Add the `readonly` boolean attribute on an input to prevent modification of the Add the `readonly` boolean attribute on an input to prevent modification of the input’s value. `readonly` inputs can still be focused and selected, while `disabled` inputs cannot. - `} /> + `} /> ### Invalid @@ -706,3 +706,13 @@ You may also set the [trailing action on loading]([[docsref:/components/buttons#
`} /> + +## Mandatory field indication + + + +
+ + +
+ `} /> diff --git a/site/src/content/docs/foundation/form-validation.mdx b/site/src/content/docs/foundation/form-validation.mdx index 70b9bd8b21..95aebb1576 100644 --- a/site/src/content/docs/foundation/form-validation.mdx +++ b/site/src/content/docs/foundation/form-validation.mdx @@ -300,3 +300,108 @@ For invalid fields, ensure that the invalid feedback/error message is associated

`} /> + +## Mandatory fields indication + +### Single field forms or obvious mandatory fields + +If there is only one field in the form, or if the mandatory nature of the fields is obvious (such as login/password in a sign-in form), no mention is necessary since the fields are essential to the form's functionality. + + +
+
+ + +
+
+ +
+
+ + + +
+
+ `} /> + +### Forms with only mandatory fields + +In a form having several fields and where all fields are mandatory, it is sufficient to indicate this in the form instructions, by stating "**All fields are mandatory.**" at the top. This way, assistive technologies can communicate this information to users without the need for additional mention on each form control. + + + + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ `} /> + + +### Forms with optional fields + +In a form having several fields and where not all fields are mandatory, you have to display a message "**All fields marked with an * are mandatory.**" at the top, and hide it from assistive technologies with `aria-hidden="true"`, since the mandatory nature of the fields will be explicitely indicated by the `required` attribute. Then, you have to explicitely indicate which fields are mandatory to other users, by adding the class `.is-required` on the label. This adds a red asterisk at the end of the label. + + + + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ `} /> diff --git a/site/src/types/auto-import.d.ts b/site/src/types/auto-import.d.ts index 9ee21688e6..45a7b0c06e 100644 --- a/site/src/types/auto-import.d.ts +++ b/site/src/types/auto-import.d.ts @@ -19,6 +19,7 @@ export declare global { export const Example: typeof import('@shortcodes/Example.astro').default export const JsDismiss: typeof import('@shortcodes/JsDismiss.astro').default export const JsDocs: typeof import('@shortcodes/JsDocs.astro').default + export const MandatoryFieldIndication: typeof import('@shortcodes/MandatoryFieldIndication.astro').default export const Placeholder: typeof import('@shortcodes/Placeholder.astro').default export const ScssDocs: typeof import('@shortcodes/ScssDocs.astro').default export const SkeletonRedirect: typeof import('@shortcodes/SkeletonRedirect.astro').default