From 84645302b3d0b355f9ac1f5c6de85264edb73ca3 Mon Sep 17 00:00:00 2001 From: Borghild Selle <104756130+BorghildSelle@users.noreply.github.com> Date: Mon, 4 Nov 2024 08:14:58 +0100 Subject: [PATCH] :art: more accessibility for forms #2505 (#2510) * :art: more accessibility * :art: add tel type * :art: remove logs * :art: update documentation with eds feature request link * :art: fix typo * :art:update to small text and remove placeholders --- sanityv3/schemas/textSnippets.ts | 16 +- web/components/src/Form/FormSelect.tsx | 3 + web/components/src/Form/FormTextField.tsx | 4 +- web/core/TextField/TextArea.tsx | 65 ++ web/core/TextField/TextField.tsx | 141 +++++ .../topicPages/Form/CareerFairForm.tsx | 151 +++-- .../topicPages/Form/ContactEquinorForm.tsx | 128 ++-- .../topicPages/Form/OrderReportsForm.tsx | 593 +++++++++--------- .../topicPages/Form/SubscribeForm.tsx | 458 +++++++------- .../careersContactForm/CareersContactForm.tsx | 160 ++--- 10 files changed, 970 insertions(+), 749 deletions(-) create mode 100644 web/core/TextField/TextArea.tsx create mode 100644 web/core/TextField/TextField.tsx diff --git a/sanityv3/schemas/textSnippets.ts b/sanityv3/schemas/textSnippets.ts index 8f2e973bb..dd15a9442 100644 --- a/sanityv3/schemas/textSnippets.ts +++ b/sanityv3/schemas/textSnippets.ts @@ -16,8 +16,8 @@ export const groups = { } const snippets: textSnippet = { country_code_format: { - title: 'e.g. +47', - defaultValue: 'e.g. +47', + title: 'Enter country code with phone number', + defaultValue: 'Enter country code with phone number', group: groups.form, }, all_fields_mandatory: { @@ -671,7 +671,7 @@ const snippets: textSnippet = { careers_contact_form_supporting_documents: { title: 'Supporting Documents checkbox', defaultValue: 'Tick the box if you would like to send supporting documents, and we will get in touch with you', - group: groups.careerFairForm, + group: groups.careerContactForm, }, form_sending: { @@ -719,6 +719,16 @@ const snippets: textSnippet = { defaultValue: 'Reopen the form', group: groups.form, }, + form_validation_maxChars: { + title: 'Max X chars', + defaultValue: 'Max {maxChars} characters', + group: groups.form, + }, + form_antirobot_validation_required: { + title: 'Anti-Robot verification is required', + defaultValue: 'Anti-Robot verification is required', + group: groups.form, + }, newsroom_topic_filter: { title: 'Topic filter heading', defaultValue: 'Topic', diff --git a/web/components/src/Form/FormSelect.tsx b/web/components/src/Form/FormSelect.tsx index d555058b0..47e31f322 100644 --- a/web/components/src/Form/FormSelect.tsx +++ b/web/components/src/Form/FormSelect.tsx @@ -8,6 +8,9 @@ const StyledEdsNativeSelectField = styled(EdsNativeSelect)` select { font-size: var(--typeScale-1); } + label { + color: var(--default-text); + } ` export const FormSelect = forwardRef(function EdsNativeSelect( diff --git a/web/components/src/Form/FormTextField.tsx b/web/components/src/Form/FormTextField.tsx index 98177612a..0f33fe599 100644 --- a/web/components/src/Form/FormTextField.tsx +++ b/web/components/src/Form/FormTextField.tsx @@ -3,7 +3,6 @@ import styled from 'styled-components' import { TextField as EdsTextField, TextFieldProps } from '@equinor/eds-core-react' export const TextFieldWrapper = styled.div` - padding: var(--space-small) 0px var(--space-medium) 0px; p { color: var(--clear-red-100); font-size: var(--typeScale-0); @@ -15,6 +14,9 @@ const StyledEdsTextField = styled(EdsTextField)` textarea { font-size: var(--typeScale-1); } + label { + color: var(--default-text); + } ` export const FormTextField = forwardRef(function TextField({ children, ...rest }, ref) { diff --git a/web/core/TextField/TextArea.tsx b/web/core/TextField/TextArea.tsx new file mode 100644 index 000000000..6a9f41d4f --- /dev/null +++ b/web/core/TextField/TextArea.tsx @@ -0,0 +1,65 @@ +import { forwardRef, useState, TextareaHTMLAttributes, useCallback, CSSProperties } from 'react' +import { mergeRefs, useAutoResize } from '@equinor/eds-utils' +import { SharedTextFieldProps } from './TextField' +import { Input } from '@equinor/eds-core-react' + +export type TextareaProps = { + /** Type */ + type?: string + /** Read Only */ + readOnly?: boolean + /** Specifies max rows for multiline */ + rowsMax?: number +} & SharedTextFieldProps & + TextareaHTMLAttributes + +/** Temporary. Until feature request, + * https://github.com/equinor/design-system/issues/3622, + * is resolved */ +export const Textarea = forwardRef(function Textarea( + { variant, disabled = false, type = 'text', rowsMax = 10, className = '', ...other }, + ref, +) { + const [textareaEl, setTextareaEl] = useState(null) + let fontSize = 16 + + if (textareaEl) { + fontSize = parseInt(window.getComputedStyle(textareaEl).fontSize) + } + + const padding = 12 //6px from InputToken in EDS + const maxHeight = parseFloat('1.5') * fontSize * rowsMax + padding + //@ts-ignore: textareaEl is required, null is handled in hook + useAutoResize(textareaEl, rowsMax ? maxHeight : undefined) + + const combinedRef = useCallback(() => mergeRefs(ref, setTextareaEl), [setTextareaEl, ref])() + + const inputProps = { + ref: combinedRef, + type, + disabled, + variant, + ...other, + style: { height: 'auto' }, + className, + } + + const leftAdornmentStyles = { + style: { alignItems: 'flex-start' }, + } + const rightAdornmentStyles = { + style: { + alignItems: 'flex-start', + pointerEvents: 'none' as CSSProperties['pointerEvents'], + }, + } + + return ( + + ) +}) diff --git a/web/core/TextField/TextField.tsx b/web/core/TextField/TextField.tsx new file mode 100644 index 000000000..49c5079ca --- /dev/null +++ b/web/core/TextField/TextField.tsx @@ -0,0 +1,141 @@ +import { InputProps, Input } from '@equinor/eds-core-react' +import { ReactNode, InputHTMLAttributes, forwardRef, ForwardedRef, useId, TextareaHTMLAttributes } from 'react' +import envisTwMerge from '../../twMerge' +import { Textarea } from './TextArea' + +export type Variants = 'error' | 'warning' | 'success' + +export type SharedTextFieldProps = { + /** Variants */ + variant?: Variants + /** Description,shown below label */ + description?: ReactNode + /** Input unique id. This is required to ensure accesibility */ + id: string + /** Label text */ + label?: ReactNode + /** Meta text */ + meta?: ReactNode + /** Unit text */ + unit?: string + /** Helper text */ + helperText?: string + /** Input ref */ + inputRef?: ForwardedRef + /** InputIcon */ + inputIcon?: ReactNode + /** HelperIcon */ + helperIcon?: ReactNode + helperTextClassName?: string + /** If `true` a `textarea` is rendered for multiline support. Make sure to use `textareaRef` if you need to access reference element */ + multiline?: boolean + /** Maximum number of rows if `multiline` is set to `true` */ + rowsMax?: number + /** Textarea ref when multiline is set to `true` */ + textareaRef?: ForwardedRef +} & InputProps + +type TextFieldProps = SharedTextFieldProps & + (TextareaHTMLAttributes | InputHTMLAttributes) + +type FieldProps = SharedTextFieldProps & { + multiline: boolean +} & React.HTMLAttributes +/** Proxy component for working around typescript and element type switching */ +const Field = forwardRef(function Field(props, ref) { + return props.multiline ? ( +