Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(form-field): allow label to be visually hidden #2361

Merged
merged 1 commit into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/components/form-field/form-field/form-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,17 @@

// Moves label down and input up to meet positioning requirements
margin-block-end: var(--sbb-form-field-label-to-input-gap);
}

// To avoid doubled payload, we group the rules.
:is(.sbb-form-field__label, .sbb-form-field__label-spacer) {
:host(:not([data-slot-names~='label'], [label])) & {
display: none;
}

:host([hidden-label]) & {
@include sbb.screen-reader-only;
}
}

.sbb-form-field__label {
Expand All @@ -262,10 +269,6 @@
inset-block-start: 0;
color: var(--sbb-form-field-label-color);

:host(:not([data-slot-names~='label'], [label])) & {
display: none;
}

:host([data-input-type='select']) &,
:host([data-input-type='sbb-select']) & {
padding-inline-end: var(--sbb-form-field-select-inline-padding-end);
Expand Down
24 changes: 24 additions & 0 deletions src/components/form-field/form-field/form-field.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const TemplateInput = ({
borderless,
width,
negative,
'hidden-label': hiddenLabel,
'floating-label': floatingLabel,
...args
}: Args): TemplateResult => html`
Expand All @@ -84,6 +85,7 @@ const TemplateInput = ({
size=${size}
?borderless=${borderless}
width=${width}
?hidden-label=${hiddenLabel}
?floating-label=${floatingLabel}
?negative=${negative}
>
Expand All @@ -99,6 +101,7 @@ const TemplateInputWithSlottedLabel = ({
borderless,
width,
negative,
'hidden-label': hiddenLabel,
'floating-label': floatingLabel,
...args
}: Args): TemplateResult => html`
Expand All @@ -108,6 +111,7 @@ const TemplateInputWithSlottedLabel = ({
size=${size}
?borderless=${borderless}
width=${width}
?hidden-label=${hiddenLabel}
?floating-label=${floatingLabel}
?negative=${negative}
>
Expand All @@ -131,6 +135,7 @@ const TemplateInputWithErrorSpace = (args: Args): TemplateResult => {
size=${args.size}
?borderless=${args.borderless}
width=${args.width}
?hidden-label=${args['hidden-label']}
?floating-label=${args['floating-label']}
?negative=${args.negative}
>
Expand Down Expand Up @@ -205,6 +210,7 @@ const TemplateSelect = (args: Args): TemplateResult => html`
size=${args.size}
?borderless=${args.borderless}
width=${args.width}
?hidden-label=${args['hidden-label']}
?floating-label=${args['floating-label']}
?negative=${args.negative}
>
Expand All @@ -227,6 +233,7 @@ const TemplateSelectWithErrorSpace = (args: Args): TemplateResult => {
size=${args.size}
?borderless=${args.borderless}
width=${args.width}
?hidden-label=${args['hidden-label']}
?floating-label=${args['floating-label']}
?negative=${args.negative}
>
Expand Down Expand Up @@ -354,6 +361,15 @@ const label: InputType = {
},
};

const hiddenLabel: InputType = {
control: {
type: 'boolean',
},
table: {
category: 'Form-field attribute',
},
};

const floatingLabel: InputType = {
control: {
type: 'boolean',
Expand Down Expand Up @@ -412,6 +428,7 @@ const active: InputType = {
const basicArgTypes: ArgTypes = {
'error-space': errorSpace,
label,
'hidden-label': hiddenLabel,
'floating-label': floatingLabel,
optional,
borderless,
Expand All @@ -430,6 +447,7 @@ const basicArgTypes: ArgTypes = {
const basicArgs: Args = {
'error-space': 'none',
label: 'Input name',
'hidden-label': false,
'floating-label': false,
optional: false,
borderless: false,
Expand Down Expand Up @@ -467,6 +485,12 @@ export const InputNoLabel: StoryObj = {
args: { ...basicArgs, label: undefined },
};

export const InputHiddenLabel: StoryObj = {
render: TemplateInput,
argTypes: basicArgTypes,
args: { ...basicArgs, 'hidden-label': true },
};

export const InputWithSlottedLabel: StoryObj = {
render: TemplateInputWithSlottedLabel,
argTypes: basicArgTypes,
Expand Down
19 changes: 7 additions & 12 deletions src/components/form-field/form-field/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,31 +62,26 @@ export class SbbFormFieldElement extends LitElement {
@property({ attribute: 'error-space', reflect: true })
public errorSpace?: 'none' | 'reserve' = 'none';

/**
* Label text for the input which is internally rendered as `<label>`.
*/
/** Label text for the input which is internally rendered as `<label>`. */
@property({ reflect: true }) public label: string;

/**
* Indicates whether the input is optional.
*/
/** Indicates whether the input is optional. */
@property({ type: Boolean }) public optional?: boolean;

/**
* Size variant, either l or m.
*/
/** Size variant, either l or m. */
@property({ reflect: true }) public size?: 'l' | 'm' = 'm';

/**
* Whether to display the form field without a border.
*/
/** Whether to display the form field without a border. */
@property({ reflect: true, type: Boolean }) public borderless = false;

/** Defines the width of the component:
* - `default`: the component has defined width and min-width;
* - `collapse`: the component adapts itself to its inner input content. */
@property({ reflect: true }) public width: 'default' | 'collapse' = 'default';

/** Whether to visually hide the label. If hidden, screen readers will still read it. */
@property({ attribute: 'hidden-label', reflect: true, type: Boolean }) public hiddenLabel = false;

/** Whether the label should float. If activated, the placeholder of the input is hidden. */
@property({ attribute: 'floating-label', reflect: true, type: Boolean }) public floatingLabel =
false;
Expand Down
2 changes: 2 additions & 0 deletions src/components/form-field/form-field/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ form element with the label, by setting an id on the label and referencing this
Please note that only one `<label>` element is supported. Additionally, if you place the `<label>`
element outside the `sbb-form-field`, the automatic assignment is skipped, and it is up to the
consumer to use the correct id references.
If you like to visually hide a label, but still present it with screen readers, use the `hiddenLabel` property.

When you provide informational text via `sbb-form-error`, it automatically adds these elements' IDs
to the form element's `aria-describedby` attribute.
Expand All @@ -124,6 +125,7 @@ technology will announce errors when they appear.
| `size` | `size` | public | `'l' \| 'm' \| undefined` | `'m'` | Size variant, either l or m. |
| `borderless` | `borderless` | public | `boolean` | `false` | Whether to display the form field without a border. |
| `width` | `width` | public | `'default' \| 'collapse'` | `'default'` | Defines the width of the component: - `default`: the component has defined width and min-width; - `collapse`: the component adapts itself to its inner input content. |
| `hiddenLabel` | `hidden-label` | public | `boolean` | `false` | Whether to visually hide the label. If hidden, screen readers will still read it. |
| `floatingLabel` | `floating-label` | public | `boolean` | `false` | Whether the label should float. If activated, the placeholder of the input is hidden. |
| `negative` | `negative` | public | `boolean` | `false` | Negative coloring variant flag. |
| `inputElement` | - | public | `HTMLInputElement \| HTMLSelectElement \| HTMLElement` | | Returns the input element. |
Expand Down