Skip to content

Commit 3932ea3

Browse files
Merge branch 'support-slds-2' into support-slds-2-date-input-datepicker
2 parents 32b8fca + 2014326 commit 3932ea3

File tree

8 files changed

+115
-57
lines changed

8 files changed

+115
-57
lines changed

src/scripts/Checkbox.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import React, {
22
FC,
33
InputHTMLAttributes,
44
Ref,
5+
useId,
56
useContext,
67
ReactNode,
78
} from 'react';
89
import classnames from 'classnames';
9-
import { FormElement, FormElementProps } from './FormElement';
10+
import { FormElement } from './FormElement';
1011
import { CheckboxGroupContext, CheckboxValueType } from './CheckboxGroup';
1112

1213
/**
@@ -15,7 +16,6 @@ import { CheckboxGroupContext, CheckboxValueType } from './CheckboxGroup';
1516
export type CheckboxProps = {
1617
label?: string;
1718
required?: boolean;
18-
error?: FormElementProps['error'];
1919
cols?: number;
2020
name?: string;
2121
value?: CheckboxValueType;
@@ -33,10 +33,10 @@ export type CheckboxProps = {
3333
export const Checkbox: FC<CheckboxProps> = (props) => {
3434
const {
3535
type, // eslint-disable-line @typescript-eslint/no-unused-vars
36+
id: id_,
3637
className,
3738
label,
3839
required,
39-
error,
4040
cols,
4141
tooltip,
4242
tooltipIcon,
@@ -45,22 +45,35 @@ export const Checkbox: FC<CheckboxProps> = (props) => {
4545
children,
4646
...rprops
4747
} = props;
48-
const { grouped } = useContext(CheckboxGroupContext);
48+
49+
const prefix = useId();
50+
const id = id_ ?? `${prefix}-id`;
51+
52+
const { grouped, error, errorId } = useContext(CheckboxGroupContext);
4953
const formElemProps = {
5054
required,
5155
error,
56+
errorId,
5257
cols,
5358
tooltip,
5459
tooltipIcon,
5560
elementRef,
5661
};
5762
const checkClassNames = classnames(className, 'slds-checkbox');
5863
const check = (
59-
<label className={checkClassNames}>
60-
<input ref={inputRef} type='checkbox' {...rprops} />
61-
<span className='slds-checkbox_faux' />
62-
<span className='slds-form-element__label'>{label || children}</span>
63-
</label>
64+
<div className={checkClassNames}>
65+
<input
66+
ref={inputRef}
67+
type='checkbox'
68+
{...rprops}
69+
id={id}
70+
aria-describedby={error ? errorId : undefined}
71+
/>
72+
<label className='slds-checkbox__label' htmlFor={id}>
73+
<span className='slds-checkbox_faux' />
74+
<span className='slds-form-element__label'>{label || children}</span>
75+
</label>
76+
</div>
6477
);
6578
return grouped ? (
6679
check

src/scripts/CheckboxGroup.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, {
2+
useId,
23
createContext,
34
FieldsetHTMLAttributes,
45
Ref,
@@ -23,7 +24,11 @@ export type CheckboxValueType = string | number;
2324
/**
2425
*
2526
*/
26-
export const CheckboxGroupContext = createContext<{ grouped?: boolean }>({});
27+
export const CheckboxGroupContext = createContext<{
28+
grouped?: boolean;
29+
error?: FormElementProps['error'];
30+
errorId?: string;
31+
}>({});
2732

2833
/**
2934
*
@@ -107,19 +112,25 @@ export const CheckboxGroup = createFC<
107112
? error.message
108113
: undefined
109114
: undefined;
110-
const grpCtx = useMemo(() => ({ grouped: true }), []);
115+
116+
const errorId = useId();
117+
const grpCtx = useMemo(
118+
() => ({ grouped: true, error, errorId }),
119+
[error, errorId]
120+
);
111121

112122
return (
113123
<fieldset
114124
ref={elementRef}
115125
className={grpClassNames}
116126
style={grpStyles}
127+
aria-required={required}
117128
{...rprops}
118129
onChange={onChange}
119130
>
120131
<legend className='slds-form-element__label'>
121132
{required ? (
122-
<abbr className='slds-required' title='required'>
133+
<abbr className='slds-required' title='required' aria-hidden='true'>
123134
*
124135
</abbr>
125136
) : undefined}
@@ -135,7 +146,12 @@ export const CheckboxGroup = createFC<
135146
{children}
136147
</CheckboxGroupContext.Provider>
137148
{errorMessage ? (
138-
<div className='slds-form-element__help'>{errorMessage}</div>
149+
<div
150+
className='slds-form-element__help'
151+
id={error ? errorId : undefined}
152+
>
153+
{errorMessage}
154+
</div>
139155
) : undefined}
140156
</div>
141157
</fieldset>

src/scripts/Form.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC, FormHTMLAttributes } from 'react';
1+
import React, { FC, HTMLAttributes } from 'react';
22
import classnames from 'classnames';
33
import { FormElement } from './FormElement';
44

@@ -7,7 +7,7 @@ import { FormElement } from './FormElement';
77
*/
88
export type FormProps = {
99
type?: 'stacked' | 'horizontal' | 'inline' | 'compound';
10-
} & FormHTMLAttributes<HTMLFormElement>;
10+
} & HTMLAttributes<HTMLDivElement>;
1111

1212
/**
1313
*
@@ -16,7 +16,7 @@ export const Form: FC<FormProps> = (props) => {
1616
const { className, type = 'stacked', children, ...rprops } = props;
1717
const formClassNames = classnames(className, `slds-form_${type}`);
1818
return (
19-
<form className={formClassNames} {...rprops}>
19+
<div className={formClassNames} {...rprops}>
2020
{React.Children.map(children, (child) => {
2121
if (
2222
React.isValidElement(child) &&
@@ -26,6 +26,6 @@ export const Form: FC<FormProps> = (props) => {
2626
}
2727
return child;
2828
})}
29-
</form>
29+
</div>
3030
);
3131
};

src/scripts/Notification.tsx

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export type NotificationProps = {
1616
alt?: string;
1717
icon?: string;
1818
iconSize?: IconSize;
19-
alertTexture?: boolean;
2019
onClose?: EventHandler<MouseEvent<HTMLButtonElement>>;
2120
} & HTMLAttributes<HTMLDivElement>;
2221

@@ -26,7 +25,6 @@ export const Notification: FC<NotificationProps> = (props) => {
2625
type,
2726
level,
2827
alt,
29-
alertTexture = true,
3028
icon,
3129
iconSize = 'small',
3230
onClose,
@@ -46,16 +44,20 @@ export const Notification: FC<NotificationProps> = (props) => {
4644
'slds-notify',
4745
typeClassName,
4846
levelClassName,
49-
alertTexture ? 'slds-theme_alert-texture' : null
47+
{
48+
[`slds-alert_${level}`]: type === 'alert' && level && level !== 'info',
49+
}
5050
);
5151

5252
const iconEl = icon ? (
5353
<Icon
54-
className={
55-
type === 'toast' ? 'slds-m-right_small' : 'slds-m-right_x-small'
56-
}
54+
container={true}
55+
containerClassName={classnames(
56+
type === 'toast' ? 'slds-m-right_small' : 'slds-m-right_x-small',
57+
type === 'alert' ? ['slds-no-flex', 'slds-align-top'] : null
58+
)}
5759
icon={icon}
58-
size={iconSize}
60+
size={iconSize ?? (type === 'toast' ? 'small' : 'x-small')}
5961
fillColor='none'
6062
textColor={level === 'warning' ? 'default' : null}
6163
/>
@@ -65,27 +67,23 @@ export const Notification: FC<NotificationProps> = (props) => {
6567
<div className={alertClassNames} role='alert' {...pprops}>
6668
{alt ? <span className='slds-assistive-text'>{alt}</span> : undefined}
6769
{onClose ? (
68-
<Button
69-
className='slds-notify__close'
70-
type='icon-inverse'
71-
icon='close'
72-
iconSize={type === 'toast' ? 'large' : 'small'}
73-
alt='Close'
74-
onClick={onClose}
75-
/>
70+
<div className='slds-notify__close'>
71+
<Button
72+
type='icon-inverse'
73+
icon='close'
74+
size={type === 'toast' ? undefined : 'small'}
75+
alt='Close'
76+
onClick={onClose}
77+
/>
78+
</div>
7679
) : undefined}
80+
{iconEl}
7781
{type === 'toast' ? (
78-
<div className='slds-notify__content slds-grid'>
79-
{iconEl}
80-
<div className='slds-col slds-align-middle'>
81-
<h2 className='slds-text-heading_small'>{children}</h2>
82-
</div>
82+
<div className='slds-notify__content'>
83+
<h2 className='slds-text-heading_small'>{children}</h2>
8384
</div>
8485
) : (
85-
<h2>
86-
{iconEl}
87-
{children}
88-
</h2>
86+
<h2>{children}</h2>
8987
)}
9088
</div>
9189
);

src/scripts/Radio.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC, InputHTMLAttributes, Ref, useContext } from 'react';
1+
import React, { FC, InputHTMLAttributes, Ref, useId, useContext } from 'react';
22
import classnames from 'classnames';
33
import { RadioGroupContext, RadioValueType } from './RadioGroup';
44
import { useEventCallback } from './hooks';
@@ -17,6 +17,7 @@ export type RadioProps = {
1717
*
1818
*/
1919
export const Radio: FC<RadioProps> = ({
20+
id: id_,
2021
className,
2122
label,
2223
name,
@@ -26,7 +27,16 @@ export const Radio: FC<RadioProps> = ({
2627
children,
2728
...props
2829
}) => {
29-
const { name: grpName, onValueChange } = useContext(RadioGroupContext);
30+
const {
31+
name: grpName,
32+
error,
33+
errorId,
34+
onValueChange,
35+
} = useContext(RadioGroupContext);
36+
37+
const prefix = useId();
38+
const id = id_ ?? `${prefix}-id`;
39+
3040
const onChange = useEventCallback(
3141
(e: React.ChangeEvent<HTMLInputElement>) => {
3242
onChange_?.(e);
@@ -37,17 +47,21 @@ export const Radio: FC<RadioProps> = ({
3747
);
3848
const radioClassNames = classnames(className, 'slds-radio');
3949
return (
40-
<label className={radioClassNames}>
50+
<span className={radioClassNames}>
4151
<input
4252
ref={inputRef}
4353
type='radio'
4454
name={name ?? grpName}
4555
value={value}
4656
onChange={onChange}
4757
{...props}
58+
id={id}
59+
aria-describedby={error ? errorId : undefined}
4860
/>
49-
<span className='slds-radio_faux' />
50-
<span className='slds-form-element__label'>{label || children}</span>
51-
</label>
61+
<label className='slds-radio__label' htmlFor={id}>
62+
<span className='slds-radio_faux' />
63+
<span className='slds-form-element__label'>{label || children}</span>
64+
</label>
65+
</span>
5266
);
5367
};

src/scripts/RadioGroup.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, {
2+
useId,
23
HTMLAttributes,
34
Ref,
45
createContext,
@@ -9,6 +10,7 @@ import React, {
910
import classnames from 'classnames';
1011
import { FieldSetColumnContext } from './FieldSet';
1112
import { TooltipContent } from './TooltipContent';
13+
import { FormElementProps } from './FormElement';
1214
import { createFC } from './common';
1315
import { Bivariant } from './typeUtils';
1416

@@ -22,6 +24,8 @@ export type RadioValueType = string | number;
2224
*/
2325
export const RadioGroupContext = createContext<{
2426
name?: string;
27+
error?: FormElementProps['error'];
28+
errorId?: string;
2529
onValueChange?: Bivariant<(value: RadioValueType) => void>;
2630
}>({});
2731

@@ -83,21 +87,25 @@ export const RadioGroup = createFC<RadioGroupProps, { isFormElement: boolean }>(
8387
? error.message
8488
: undefined
8589
: undefined;
90+
91+
const errorId = useId();
8692
const grpCtx = useMemo(
87-
() => ({ name, onValueChange }),
88-
[name, onValueChange]
93+
() => ({ name, error, errorId, onValueChange }),
94+
[name, error, errorId, onValueChange]
8995
);
9096

9197
return (
9298
<fieldset
9399
ref={elementRef}
94100
className={grpClassNames}
95101
style={grpStyles}
102+
role='radiogroup'
103+
aria-required={required}
96104
{...rprops}
97105
>
98106
<legend className='slds-form-element__label'>
99107
{required ? (
100-
<abbr className='slds-required' title='required'>
108+
<abbr className='slds-required' title='required' aria-hidden='true'>
101109
*
102110
</abbr>
103111
) : undefined}
@@ -112,7 +120,12 @@ export const RadioGroup = createFC<RadioGroupProps, { isFormElement: boolean }>(
112120
<RadioGroupContext.Provider value={grpCtx}>
113121
{children}
114122
{errorMessage ? (
115-
<div className='slds-form-element__help'>{errorMessage}</div>
123+
<div
124+
className='slds-form-element__help'
125+
id={error ? errorId : undefined}
126+
>
127+
{errorMessage}
128+
</div>
116129
) : undefined}
117130
</RadioGroupContext.Provider>
118131
</div>

0 commit comments

Comments
 (0)