Skip to content

Commit 8da6fc6

Browse files
feat(HelperText): consumed Penta updates (#10029)
* feat(HelperText): consumed Penta updates * Updated examples and tests * Fixed example file names * Updated tests per Austin feedback * Updated test to avoid false positive
1 parent f559843 commit 8da6fc6

16 files changed

+114
-201
lines changed

packages/react-core/src/components/HelperText/HelperTextItem.tsx

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,42 @@ import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/excl
66
import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon';
77
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
88

9+
export enum HelperTextItemVariant {
10+
default = 'default',
11+
warning = 'warning',
12+
error = 'error',
13+
success = 'success'
14+
}
15+
916
export interface HelperTextItemProps extends React.HTMLProps<HTMLDivElement | HTMLLIElement> {
1017
/** Content rendered inside the helper text item. */
1118
children?: React.ReactNode;
1219
/** Additional classes applied to the helper text item. */
1320
className?: string;
1421
/** Sets the component type of the helper text item. */
1522
component?: 'div' | 'li';
16-
/** Variant styling of the helper text item. */
23+
/** Variant styling of the helper text item. Will also render a default icon, which can be overridden
24+
* with the icon prop.
25+
*/
1726
variant?: 'default' | 'indeterminate' | 'warning' | 'success' | 'error';
18-
/** Custom icon prefixing the helper text. This property will override the default icon paired with each helper text variant. */
27+
/** Custom icon prefixing the helper text. This property will override the default icon when the variant property is passed in. */
1928
icon?: React.ReactNode;
20-
/** Flag indicating the helper text item is dynamic. This prop should be used when the
21-
* text content of the helper text item will never change, but the icon and styling will
22-
* be dynamically updated via the `variant` prop.
23-
*/
24-
isDynamic?: boolean;
25-
/** Flag indicating the helper text should have an icon. Dynamic helper texts include icons by default while static helper texts do not. */
26-
hasIcon?: boolean;
2729
/** ID for the helper text item. The value of this prop can be passed into a form component's
2830
* aria-describedby prop when you intend for only specific helper text items to be announced to
2931
* assistive technologies.
3032
*/
3133
id?: string;
32-
/** Text that is only accessible to screen readers in order to announce the status of a helper text item.
33-
* This prop can only be used when the isDynamic prop is also passed in.
34+
/** Text that is only accessible to screen readers in order to announce the variant of a helper text item.
35+
* This prop can only be used when the variant prop has a value other than "default".
3436
*/
3537
screenReaderText?: string;
3638
}
3739

38-
const variantStyle = {
39-
default: '',
40-
indeterminate: styles.modifiers.indeterminate,
41-
warning: styles.modifiers.warning,
42-
success: styles.modifiers.success,
43-
error: styles.modifiers.error
40+
const defaultVariantIcons = {
41+
indeterminate: <MinusIcon />,
42+
warning: <ExclamationTriangleIcon />,
43+
success: <CheckCircleIcon />,
44+
error: <ExclamationCircleIcon />
4445
};
4546

4647
export const HelperTextItem: React.FunctionComponent<HelperTextItemProps> = ({
@@ -49,36 +50,28 @@ export const HelperTextItem: React.FunctionComponent<HelperTextItemProps> = ({
4950
component = 'div',
5051
variant = 'default',
5152
icon,
52-
isDynamic = false,
53-
hasIcon = isDynamic,
5453
id,
5554
screenReaderText = `${variant} status`,
5655
...props
5756
}: HelperTextItemProps) => {
5857
const Component = component as any;
58+
const isNotDefaultVariant = variant !== 'default';
59+
const defaultIcon = isNotDefaultVariant && defaultVariantIcons[variant];
5960
return (
6061
<Component
61-
className={css(styles.helperTextItem, variantStyle[variant], isDynamic && styles.modifiers.dynamic, className)}
62+
className={css(styles.helperTextItem, isNotDefaultVariant && styles.modifiers[variant], className)}
6263
id={id}
6364
{...props}
6465
>
65-
{icon && (
66-
<span className={css(styles.helperTextItemIcon)} aria-hidden>
67-
{icon}
68-
</span>
69-
)}
70-
{hasIcon && !icon && (
66+
{(defaultIcon || icon) && (
7167
<span className={css(styles.helperTextItemIcon)} aria-hidden>
72-
{(variant === 'default' || variant === 'indeterminate') && <MinusIcon />}
73-
{variant === 'warning' && <ExclamationTriangleIcon />}
74-
{variant === 'success' && <CheckCircleIcon />}
75-
{variant === 'error' && <ExclamationCircleIcon />}
68+
{icon || defaultIcon}
7669
</span>
7770
)}
7871

7972
<span className={css(styles.helperTextItemText)}>
8073
{children}
81-
{isDynamic && <span className="pf-v5-screen-reader">: {screenReaderText};</span>}
74+
{isNotDefaultVariant && <span className="pf-v5-screen-reader">: {screenReaderText};</span>}
8275
</span>
8376
</Component>
8477
);

packages/react-core/src/components/HelperText/__tests__/HelperTextItem.test.tsx

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ test('Renders custom className', () => {
3030
expect(screen.getByText('help test text 1').parentElement).toHaveClass('custom');
3131
});
3232

33+
test('Does not render screen reader text by default', () => {
34+
render(<HelperTextItem>help test text 1</HelperTextItem>);
35+
36+
expect(screen.queryByText('status', { exact: false })).not.toBeInTheDocument();
37+
});
38+
3339
Object.values(['indeterminate', 'warning', 'success', 'error']).forEach((variant) => {
3440
test(`Renders with class ${styles.modifiers[variant]} when variant = ${variant}`, () => {
3541
render(
@@ -39,6 +45,26 @@ Object.values(['indeterminate', 'warning', 'success', 'error']).forEach((variant
3945
);
4046
expect(screen.getByText('text').parentElement).toHaveClass(styles.modifiers[variant]);
4147
});
48+
49+
test(`Renders default screenreader text when variant = ${variant}`, () => {
50+
render(
51+
<HelperTextItem variant={variant as 'default' | 'indeterminate' | 'warning' | 'success' | 'error'}>
52+
text
53+
</HelperTextItem>
54+
);
55+
expect(screen.getByText(`: ${variant} status;`)).toBeInTheDocument();
56+
});
57+
});
58+
59+
test('Renders custom screen reader text', () => {
60+
render(
61+
<HelperTextItem variant="error" screenReaderText="danger">
62+
help test text 1
63+
</HelperTextItem>
64+
);
65+
66+
expect(screen.queryByText(': error status;')).not.toBeInTheDocument();
67+
expect(screen.getByText(': danger;')).toBeInTheDocument();
4268
});
4369

4470
test('Renders id when id is passed', () => {
@@ -56,38 +82,26 @@ test('Renders with element passed to component prop', () => {
5682
expect(screen.getByText('help test text 1').parentElement?.tagName).toBe('LI');
5783
});
5884

59-
test('Renders custom icon', () => {
60-
render(<HelperTextItem icon={<div>test</div>}>help test text</HelperTextItem>);
61-
expect(screen.getByText('test').parentElement).toHaveClass(styles.helperTextItemIcon);
62-
});
63-
64-
test('Renders default icon when hasIcon = true and icon is not passed', () => {
65-
render(<HelperTextItem hasIcon>help test text</HelperTextItem>);
66-
expect(screen.getByText('help test text').parentElement?.querySelector('span')).toHaveClass(
67-
styles.helperTextItemIcon
68-
);
85+
test('Does not render an icon by default', () => {
86+
render(<HelperTextItem>help test text</HelperTextItem>);
87+
expect(screen.queryByText('help test text')?.previousSibling).not.toBeInTheDocument();
6988
});
7089

71-
test('Renders custom icon when icon is passed and hasIcon = true', () => {
72-
render(
73-
<HelperTextItem hasIcon icon={<div>test</div>}>
74-
help test text
75-
</HelperTextItem>
76-
);
77-
expect(screen.getByText('test').parentElement).toHaveClass(styles.helperTextItemIcon);
90+
test('Renders a default icon when variant is passed and icon is not passed', () => {
91+
render(<HelperTextItem variant="success">help test text</HelperTextItem>);
92+
expect(screen.getByText('help test text').previousSibling).toHaveClass(styles.helperTextItemIcon);
7893
});
7994

80-
test('Renders dynamic helper text', () => {
81-
render(<HelperTextItem isDynamic>help test text</HelperTextItem>);
82-
expect(screen.getByText('help test text').parentElement).toHaveClass(styles.modifiers.dynamic);
83-
expect(screen.getByText('help test text').querySelector('span')).toHaveClass('pf-v5-screen-reader');
95+
test('Renders custom icon when icon prop is passed', () => {
96+
render(<HelperTextItem icon={<div>icon content</div>}>help test text</HelperTextItem>);
97+
expect(screen.getByText('icon content').parentElement).toHaveClass(styles.helperTextItemIcon);
8498
});
8599

86-
test('Renders custom screenreader text when isDynamic = true and screenReaderText is passed', () => {
100+
test('Renders custom icon instead of variant icon when icon and variant are passed', () => {
87101
render(
88-
<HelperTextItem isDynamic screenReaderText="sr test">
102+
<HelperTextItem icon={<div>icon content</div>} variant="success">
89103
help test text
90104
</HelperTextItem>
91105
);
92-
expect(screen.getByText('help test text').querySelector('span')).toHaveTextContent('sr test');
106+
expect(screen.getByText('icon content').parentElement).toHaveClass(styles.helperTextItemIcon);
93107
});

packages/react-core/src/components/HelperText/examples/HelperText.md

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,22 @@ import ExclamationIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-
1313

1414
## Examples
1515

16-
### Static
16+
### Basic
1717

18-
```ts file="HelperTextStatic.tsx"
19-
```
20-
21-
### Static with default icons
18+
```ts file="HelperTextBasic.tsx"
2219

23-
```ts file="HelperTextStaticWithDefaultIcon.tsx"
2420
```
2521

26-
### Static with custom icons
22+
### With custom icons
2723

28-
```ts file="HelperTextStaticWithCustomIcon.tsx"
29-
```
24+
```ts file="HelperTextWithCustomIcon.tsx"
3025

31-
### Multiple static
32-
33-
```ts file="HelperTextMultipleStatic.tsx"
3426
```
3527

36-
### Dynamic
28+
### Multiple items
3729

38-
```ts file="HelperTextDynamic.tsx"
39-
```
30+
You can pass multiple `<HelperTextItem>` components inside a single `<Helpertext>` container.
4031

41-
### Dynamic list
32+
```ts file="HelperTextMultipleItems.tsx"
4233

43-
```ts file="HelperTextDynamicList.tsx"
4434
```

packages/react-core/src/components/HelperText/examples/HelperTextStatic.tsx renamed to packages/react-core/src/components/HelperText/examples/HelperTextBasic.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { HelperText, HelperTextItem } from '@patternfly/react-core';
33

4-
export const HelperTextStatic: React.FunctionComponent = () => (
4+
export const HelperTextBasic: React.FunctionComponent = () => (
55
<React.Fragment>
66
<HelperText>
77
<HelperTextItem>This is default helper text</HelperTextItem>

packages/react-core/src/components/HelperText/examples/HelperTextDynamic.tsx

Lines changed: 0 additions & 41 deletions
This file was deleted.

packages/react-core/src/components/HelperText/examples/HelperTextDynamicList.tsx

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import { HelperText, HelperTextItem } from '@patternfly/react-core';
3+
4+
export const HelperTextMultipleItems: React.FunctionComponent = () => (
5+
<HelperText component="ul">
6+
<HelperTextItem component="li">This is default helper text</HelperTextItem>
7+
<HelperTextItem component="li">This is another default helper text in the same HelperText block</HelperTextItem>
8+
<HelperTextItem component="li">And this is more default text in the same HelperText block</HelperTextItem>
9+
</HelperText>
10+
);

packages/react-core/src/components/HelperText/examples/HelperTextMultipleStatic.tsx

Lines changed: 0 additions & 10 deletions
This file was deleted.

packages/react-core/src/components/HelperText/examples/HelperTextStaticWithDefaultIcon.tsx

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import ExclamationIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-
66
import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
77
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
88

9-
export const HelperTextStaticWithCustomIcon: React.FunctionComponent = () => (
9+
export const HelperTextWithCustomIcon: React.FunctionComponent = () => (
1010
<React.Fragment>
1111
<HelperText>
1212
<HelperTextItem icon={<InfoIcon />}>This is default helper text</HelperTextItem>

0 commit comments

Comments
 (0)