Skip to content

Commit 388331a

Browse files
authored
Merge pull request #485 from mashmatrix/support-slds-2
Prepare for SLDS2
2 parents 86ca0fa + e4fa298 commit 388331a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2775
-1376
lines changed

src/scripts/Badge.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,25 @@ import classnames from 'classnames';
55
*
66
*/
77
export type BadgeProps = {
8-
type?: 'default' | 'shade' | 'inverse';
8+
type?: 'inverse' | 'lightest' | 'success' | 'warning' | 'error';
99
label?: string;
1010
} & HTMLAttributes<HTMLSpanElement>;
1111

1212
/**
1313
*
1414
*/
1515
export const Badge: FC<BadgeProps> = ({ type, label, ...props }) => {
16-
const typeClassName = type ? `slds-theme_${type}` : null;
17-
const badgeClassNames = classnames('slds-badge', typeClassName);
16+
const typeClassName = /^(inverse|lightest)$/.test(type ?? '')
17+
? `slds-badge_${type}`
18+
: null;
19+
const themeClassName = /^(success|warning|error)$/.test(type ?? '')
20+
? `slds-theme_${type}`
21+
: null;
22+
const badgeClassNames = classnames(
23+
'slds-badge',
24+
typeClassName,
25+
themeClassName
26+
);
1827
return (
1928
<span className={badgeClassNames} {...props}>
2029
{label || props.children}

src/scripts/BreadCrumbs.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ export const Crumb: FC<CrumbProps> = ({
1818
...props
1919
}) => {
2020
const text = children;
21-
const cClassName = classnames(
22-
'slds-list__item slds-text-heading_label',
23-
className
24-
);
21+
const cClassName = classnames('slds-breadcrumb__item', className);
2522

2623
return (
2724
<li {...props} className={cClassName}>
@@ -33,34 +30,26 @@ export const Crumb: FC<CrumbProps> = ({
3330
/**
3431
*
3532
*/
36-
export type BreadCrumbsProps = {
37-
label?: string;
38-
} & HTMLAttributes<HTMLElement>;
33+
export type BreadCrumbsProps = HTMLAttributes<HTMLElement>;
3934

4035
/**
4136
*
4237
*/
4338
export const BreadCrumbs: FC<BreadCrumbsProps> = ({
44-
label,
4539
className,
4640
children,
4741
...props
4842
}) => {
4943
const oClassName = classnames(
50-
'slds-breadcrumb slds-list_horizontal',
44+
'slds-breadcrumb',
45+
'slds-list_horizontal',
46+
'slds-wrap',
5147
className
5248
);
5349

5450
return (
55-
<nav {...props} role='navigation'>
56-
{label ? (
57-
<p id='bread-crumb-label' className='slds-assistive-text'>
58-
{label}
59-
</p>
60-
) : null}
61-
<ol className={oClassName} aria-labelledby='bread-crumb-label'>
62-
{children}
63-
</ol>
51+
<nav {...props} role='navigation' aria-label='Breadcrumbs'>
52+
<ol className={oClassName}>{children}</ol>
6453
</nav>
6554
);
6655
};

src/scripts/Button.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import React, { FC, ReactNode, ButtonHTMLAttributes, Ref, useRef } from 'react';
22
import classnames from 'classnames';
3-
import { Icon } from './Icon';
3+
import { SvgIcon, IconCategory } from './Icon';
44
import { Spinner } from './Spinner';
55
import { useEventCallback, useMergeRefs } from './hooks';
66

77
export type ButtonType =
88
| 'neutral'
99
| 'brand'
10+
| 'outline-brand'
1011
| 'destructive'
12+
| 'text-destructive'
13+
| 'success'
1114
| 'inverse'
1215
| 'icon'
13-
| 'icon-bare'
1416
| 'icon-container'
1517
| 'icon-inverse'
1618
| 'icon-more'
@@ -31,6 +33,7 @@ export type ButtonIconMoreSize = 'x-small' | 'small' | 'medium' | 'large';
3133
*/
3234
export type ButtonIconProps = {
3335
className?: string;
36+
category?: IconCategory;
3437
icon: string;
3538
align?: ButtonIconAlign;
3639
size?: ButtonIconSize;
@@ -43,9 +46,9 @@ export type ButtonIconProps = {
4346
*/
4447
export const ButtonIcon: FC<ButtonIconProps> = ({
4548
icon,
49+
category = 'utility',
4650
align,
4751
size,
48-
inverse,
4952
className,
5053
style,
5154
...props
@@ -56,19 +59,22 @@ export const ButtonIcon: FC<ButtonIconProps> = ({
5659
: null;
5760
const sizeClassName =
5861
size && ICON_SIZES.indexOf(size) >= 0 ? `slds-button__icon_${size}` : null;
59-
const inverseClassName = inverse ? 'slds-button__icon_inverse' : null;
6062
const iconClassNames = classnames(
6163
'slds-button__icon',
6264
alignClassName,
6365
sizeClassName,
64-
inverseClassName,
6566
className
6667
);
68+
69+
if (icon.indexOf(':') > 0) {
70+
[category, icon] = icon.split(':') as [IconCategory, string];
71+
}
72+
6773
return (
68-
<Icon
74+
<SvgIcon
6975
className={iconClassNames}
7076
icon={icon}
71-
textColor={null}
77+
category={category}
7278
pointerEvents='none'
7379
style={style}
7480
{...props}
@@ -118,6 +124,7 @@ export const Button: FC<ButtonProps> = (props) => {
118124
buttonRef: buttonRef_,
119125
iconMoreSize: iconMoreSize_,
120126
onClick: onClick_,
127+
tabIndex,
121128
...rprops
122129
} = props;
123130

@@ -135,19 +142,24 @@ export const Button: FC<ButtonProps> = (props) => {
135142
onClick_?.(e);
136143
});
137144

145+
const content = children || label;
146+
const isIconOnly = type && /^icon-/.test(type) && icon && !content;
147+
138148
const typeClassName = type ? `slds-button_${type}` : null;
139149
const btnClassNames = classnames(className, 'slds-button', typeClassName, {
140150
'slds-is-selected': selected,
151+
['slds-button_icon']: /^icon-/.test(type ?? ''),
141152
[`slds-button_icon-${size ?? ''}`]:
142153
/^(x-small|small)$/.test(size ?? '') && /^icon-/.test(type ?? ''),
143154
});
144155

145-
const buttonContent = (
146-
// eslint-disable-next-line react/button-has-type
156+
return (
147157
<button
148158
ref={buttonRef}
149159
className={btnClassNames}
150160
type={htmlType}
161+
title={isIconOnly || alt ? alt : undefined}
162+
tabIndex={tabIndex ?? -1}
151163
{...rprops}
152164
onClick={onClick}
153165
>
@@ -159,7 +171,7 @@ export const Button: FC<ButtonProps> = (props) => {
159171
inverse={inverse}
160172
/>
161173
) : undefined}
162-
{children || label}
174+
{content}
163175
{icon && iconAlign === 'right' ? (
164176
<ButtonIcon
165177
icon={icon}
@@ -171,22 +183,10 @@ export const Button: FC<ButtonProps> = (props) => {
171183
{iconMore ? (
172184
<ButtonIcon icon={iconMore} align='right' size={iconMoreSize} />
173185
) : undefined}
174-
{alt ? <span className='slds-assistive-text'>{alt}</span> : undefined}
186+
{isIconOnly || alt ? (
187+
<span className='slds-assistive-text'>{alt ?? icon}</span>
188+
) : undefined}
175189
{loading ? <Spinner /> : undefined}
176190
</button>
177191
);
178-
179-
if (props.tabIndex != null) {
180-
return (
181-
<span
182-
className='react-slds-button-focus-wrapper'
183-
style={{ outline: 0 }}
184-
tabIndex={-1}
185-
>
186-
{buttonContent}
187-
</span>
188-
);
189-
}
190-
191-
return buttonContent;
192192
};

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/DateInput.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ export const DateInput = createFC<DateInputProps, { isFormElement: boolean }>(
322322
});
323323

324324
const formElemProps = {
325-
id,
325+
controlId: id,
326326
cols,
327327
label,
328328
required,
@@ -333,7 +333,16 @@ export const DateInput = createFC<DateInputProps, { isFormElement: boolean }>(
333333
};
334334
return (
335335
<FormElement {...formElemProps}>
336-
<div className={classnames(className, 'slds-dropdown-trigger')}>
336+
<div
337+
className={classnames(
338+
className,
339+
'slds-dropdown-trigger',
340+
'slds-dropdown-trigger_click',
341+
{
342+
'slds-is-open': opened,
343+
}
344+
)}
345+
>
337346
<div className='slds-input-has-icon slds-input-has-icon_right'>
338347
<Input
339348
inputRef={inputRef}

0 commit comments

Comments
 (0)