@indico-data/design-system 2.18.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/lib/index.css +55 -33
  2. package/lib/index.d.ts +34 -20
  3. package/lib/index.esm.css +55 -33
  4. package/lib/index.esm.js +1666 -85
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +1669 -86
  7. package/lib/index.js.map +1 -1
  8. package/lib/src/components/forms/input/Input.d.ts +5 -7
  9. package/lib/src/components/forms/passwordInput/PasswordInput.d.ts +5 -7
  10. package/lib/src/components/forms/subcomponents/Label.d.ts +6 -3
  11. package/lib/src/components/forms/textarea/Textarea.d.ts +5 -7
  12. package/lib/src/components/index.d.ts +2 -0
  13. package/lib/src/components/menu/Menu.d.ts +5 -0
  14. package/lib/src/components/menu/Menu.stories.d.ts +6 -0
  15. package/lib/src/components/menu/Menu.test.d.ts +1 -0
  16. package/lib/src/components/menu/index.d.ts +1 -0
  17. package/lib/src/components/popper/Popper.d.ts +12 -0
  18. package/lib/src/components/popper/Popper.stories.d.ts +6 -0
  19. package/lib/src/components/popper/Popper.test.d.ts +1 -0
  20. package/lib/src/components/popper/index.d.ts +1 -0
  21. package/lib/src/hooks/useClickOutside.d.ts +2 -0
  22. package/lib/src/index.d.ts +2 -0
  23. package/lib/src/storybook/labelArgTypes.d.ts +3 -0
  24. package/package.json +2 -1
  25. package/src/components/forms/input/Input.mdx +15 -2
  26. package/src/components/forms/input/Input.stories.tsx +10 -45
  27. package/src/components/forms/input/Input.tsx +22 -15
  28. package/src/components/forms/input/styles/Input.scss +0 -11
  29. package/src/components/forms/passwordInput/PasswordInput.mdx +10 -8
  30. package/src/components/forms/passwordInput/PasswordInput.stories.tsx +3 -44
  31. package/src/components/forms/passwordInput/PasswordInput.tsx +20 -15
  32. package/src/components/forms/passwordInput/styles/PasswordInput.scss +0 -11
  33. package/src/components/forms/subcomponents/Label.tsx +29 -6
  34. package/src/components/forms/subcomponents/__tests__/Label.test.tsx +63 -15
  35. package/src/components/forms/textarea/Textarea.mdx +12 -2
  36. package/src/components/forms/textarea/Textarea.stories.tsx +4 -46
  37. package/src/components/forms/textarea/Textarea.tsx +15 -13
  38. package/src/components/forms/textarea/styles/Textarea.scss +0 -11
  39. package/src/components/index.ts +2 -0
  40. package/src/components/menu/Menu.mdx +15 -0
  41. package/src/components/menu/Menu.stories.tsx +56 -0
  42. package/src/components/menu/Menu.test.tsx +88 -0
  43. package/src/components/menu/Menu.tsx +20 -0
  44. package/src/components/menu/index.ts +1 -0
  45. package/src/components/menu/styles/Menu.scss +19 -0
  46. package/src/components/menu/styles/_variables.scss +15 -0
  47. package/src/components/popper/Popper.mdx +79 -0
  48. package/src/components/popper/Popper.stories.tsx +161 -0
  49. package/src/components/popper/Popper.test.tsx +68 -0
  50. package/src/components/popper/Popper.tsx +57 -0
  51. package/src/components/popper/index.ts +1 -0
  52. package/src/components/popper/styles/Popper.scss +11 -0
  53. package/src/components/popper/styles/_variables.scss +15 -0
  54. package/src/hooks/useClickOutside.tsx +22 -0
  55. package/src/index.ts +2 -0
  56. package/src/legacy/components/buttons/commonStyles.ts +0 -4
  57. package/src/storybook/labelArgTypes.ts +50 -0
  58. package/src/styles/index.scss +2 -0
@@ -1,19 +1,17 @@
1
1
  import React from 'react';
2
2
  import { IconName } from '@/types';
3
- export interface InputProps {
4
- label: string;
5
- name: string;
3
+ import { WithLabelProps } from '../subcomponents/Label';
4
+ export interface InputProps extends WithLabelProps {
6
5
  value?: string | undefined;
7
- placeholder: string;
6
+ placeholder?: string;
8
7
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
9
- isRequired?: boolean;
10
8
  isDisabled?: boolean;
11
9
  errorMessage?: string | undefined;
12
10
  helpText?: string;
13
- hasHiddenLabel?: boolean;
14
11
  iconName?: IconName;
15
12
  isClearable?: boolean;
16
13
  className?: string;
17
14
  defaultValue?: string;
18
15
  }
19
- export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
16
+ declare const LabeledInput: React.ForwardRefExoticComponent<Omit<InputProps & React.RefAttributes<HTMLInputElement> & WithLabelProps, "ref"> & React.RefAttributes<any>>;
17
+ export { LabeledInput as Input };
@@ -1,17 +1,15 @@
1
1
  import React from 'react';
2
- export interface PasswordInputProps {
2
+ import { WithLabelProps } from '../subcomponents/Label';
3
+ export interface PasswordInputProps extends WithLabelProps {
3
4
  ref?: React.LegacyRef<HTMLInputElement>;
4
- label: string;
5
5
  value?: string | undefined;
6
- name: string;
7
- placeholder: string;
6
+ placeholder?: string;
8
7
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
9
- isRequired?: boolean;
10
8
  isDisabled?: boolean;
11
9
  errorMessage?: string | undefined;
12
10
  helpText?: string;
13
- hasHiddenLabel?: boolean;
14
11
  hasShowPassword?: boolean;
15
12
  defaultValue?: string;
16
13
  }
17
- export declare const PasswordInput: React.ForwardRefExoticComponent<Omit<PasswordInputProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
14
+ declare const LabeledPasswordInput: React.ForwardRefExoticComponent<Omit<Omit<PasswordInputProps, "ref"> & React.RefAttributes<HTMLInputElement> & WithLabelProps, "ref"> & React.RefAttributes<any>>;
15
+ export { LabeledPasswordInput as PasswordInput };
@@ -1,8 +1,11 @@
1
- interface LabelProps {
1
+ import React from 'react';
2
+ export interface LabelProps {
2
3
  label: string;
3
4
  name: string;
4
5
  isRequired?: boolean;
6
+ }
7
+ export interface WithLabelProps extends LabelProps {
5
8
  hasHiddenLabel?: boolean;
6
9
  }
7
- export declare const Label: ({ label, name, isRequired, hasHiddenLabel }: LabelProps) => import("react/jsx-runtime").JSX.Element;
8
- export {};
10
+ export declare const Label: ({ label, name, isRequired }: LabelProps) => import("react/jsx-runtime").JSX.Element;
11
+ export declare function withLabel<P extends object>(WrappedComponent: React.ComponentType<P>): React.ForwardRefExoticComponent<React.PropsWithoutRef<P & WithLabelProps> & React.RefAttributes<any>>;
@@ -1,16 +1,13 @@
1
1
  import React from 'react';
2
- export interface TextareaProps {
2
+ import { WithLabelProps } from '../subcomponents/Label';
3
+ export interface TextareaProps extends WithLabelProps {
3
4
  ref?: React.LegacyRef<HTMLTextAreaElement>;
4
- label: string;
5
- name: string;
6
- placeholder: string;
5
+ placeholder?: string;
7
6
  value?: string | undefined;
8
7
  onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
9
- isRequired?: boolean;
10
8
  isDisabled?: boolean;
11
9
  errorMessage?: string | undefined;
12
10
  helpText?: string;
13
- hasHiddenLabel?: boolean;
14
11
  rows?: number;
15
12
  cols?: number;
16
13
  readonly?: boolean;
@@ -20,4 +17,5 @@ export interface TextareaProps {
20
17
  autofocus?: boolean;
21
18
  defaultValue?: string;
22
19
  }
23
- export declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
20
+ declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement> & WithLabelProps, "ref"> & React.RefAttributes<any>>;
21
+ export { LabeledTextarea as Textarea };
@@ -12,3 +12,5 @@ export { Select } from './forms/select';
12
12
  export { Form } from './forms/form';
13
13
  export { Skeleton } from './skeleton';
14
14
  export { Card } from './card';
15
+ export { Popper } from './popper';
16
+ export { Menu } from './menu';
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export type MenuProps = {
3
+ children: React.ReactNode;
4
+ };
5
+ export declare function Menu({ children }: MenuProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Menu, MenuProps } from './Menu';
3
+ declare const meta: Meta<typeof Menu>;
4
+ export default meta;
5
+ type Story = StoryObj<MenuProps>;
6
+ export declare const Default: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export { Menu } from './Menu';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Placement } from '@floating-ui/react-dom';
3
+ export type PopperProps = {
4
+ children: React.ReactNode;
5
+ referenceElement: HTMLElement | null;
6
+ isOpen: boolean;
7
+ onClose: () => void;
8
+ ariaLabel: string;
9
+ placement?: Placement;
10
+ offsetValue?: number;
11
+ };
12
+ export declare function Popper({ children, referenceElement, isOpen, onClose, ariaLabel, placement, offsetValue, }: PopperProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,6 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { Popper, PopperProps } from './Popper';
3
+ declare const meta: Meta<typeof Popper>;
4
+ export default meta;
5
+ type Story = StoryObj<PopperProps>;
6
+ export declare const Default: Story;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export { Popper } from './Popper';
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const useClickOutside: (ref: React.MutableRefObject<HTMLElement>, handler: (e: MouseEvent | TouchEvent) => void) => void;
@@ -17,3 +17,5 @@ export { Select as SelectInput } from './components/forms/select';
17
17
  export { Form } from './components/forms/form';
18
18
  export { Skeleton } from './components/skeleton';
19
19
  export { Card } from './components/card';
20
+ export { Popper } from './components/popper';
21
+ export { Menu } from './components/menu';
@@ -0,0 +1,3 @@
1
+ import { ArgTypes } from '@storybook/react';
2
+ declare const labelArgTypes: ArgTypes;
3
+ export default labelArgTypes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indico-data/design-system",
3
- "version": "2.18.0",
3
+ "version": "2.20.0",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "main": "lib/index.js",
@@ -28,6 +28,7 @@
28
28
  "**/*": "prettier --write --ignore-unknown"
29
29
  },
30
30
  "dependencies": {
31
+ "@floating-ui/react-dom": "^2.1.1",
31
32
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
32
33
  "@fortawesome/free-regular-svg-icons": "^6.5.2",
33
34
  "@fortawesome/free-solid-svg-icons": "^6.5.2",
@@ -5,13 +5,26 @@ import * as Input from './Input.stories';
5
5
 
6
6
  # Input
7
7
 
8
- The input component is the building block of any form. Below you will find the accepted properties for this component. It is encouraged to build forms utilizing [React Hook Form](https://react-hook-form.com/) library in your application. This will facilitate form state management and enforce best practices. (***Our components are compatible with but do not provide the plugin***)
8
+ The input component is the building block of any form. Below you will find the accepted properties for this component. It is encouraged to build forms utilizing [React Hook Form](https://react-hook-form.com/) library in your application. This will facilitate form state management and enforce best practices. (**_Our components are compatible with but do not provide the plugin_**)
9
9
 
10
10
  <Canvas
11
11
  of={Input.Default}
12
12
  source={{
13
13
  code: `
14
- <Input name="first_name" required={true} isRequired helpText="This Is Help Text" isClearable label="Label Name" iconName="user" />
14
+ <Input
15
+ label="Label Name"
16
+ name="first_name"
17
+ placeholder="Please enter a value"
18
+ helpText="This Is Help Text"
19
+ isRequired
20
+ hasHiddenLabel={false}
21
+ isClearable
22
+ iconName="user"
23
+ isDisabled={false}
24
+ errorMessage=""
25
+ value=""
26
+ onChange={() => {}}
27
+ />
15
28
  `,
16
29
  }}
17
30
  />
@@ -2,6 +2,7 @@ import { Meta, StoryObj } from '@storybook/react';
2
2
  import { Input, InputProps } from './Input';
3
3
  import { SetStateAction, useEffect, useState } from 'react';
4
4
  import { iconNames } from 'build/generated/iconTypes';
5
+ import labelArgTypes from '@/storybook/labelArgTypes';
5
6
 
6
7
  const meta: Meta = {
7
8
  title: 'Forms/Input',
@@ -16,28 +17,9 @@ const meta: Meta = {
16
17
  summary: '(e: React.ChangeEvent<HTMLInputElement>) => void',
17
18
  },
18
19
  },
20
+ type: { name: 'function', required: true },
19
21
  action: 'onChange',
20
22
  },
21
- label: {
22
- control: 'text',
23
- description: 'The label for the input field',
24
- table: {
25
- category: 'Props',
26
- type: {
27
- summary: 'string',
28
- },
29
- },
30
- },
31
- name: {
32
- control: 'text',
33
- description: 'The name for the input field',
34
- table: {
35
- category: 'Props',
36
- type: {
37
- summary: 'string',
38
- },
39
- },
40
- },
41
23
  placeholder: {
42
24
  control: 'text',
43
25
  description: 'The placeholder for the input field',
@@ -47,6 +29,7 @@ const meta: Meta = {
47
29
  summary: 'string',
48
30
  },
49
31
  },
32
+ type: { name: 'string', required: false },
50
33
  },
51
34
  value: {
52
35
  control: 'text',
@@ -57,17 +40,7 @@ const meta: Meta = {
57
40
  summary: 'string',
58
41
  },
59
42
  },
60
- },
61
- isRequired: {
62
- control: 'boolean',
63
- description: 'Toggles the required asterisk on the label',
64
- table: {
65
- category: 'Props',
66
- type: {
67
- summary: 'boolean',
68
- },
69
- },
70
- defaultValue: { summary: 'false' },
43
+ type: { name: 'string', required: false },
71
44
  },
72
45
  isDisabled: {
73
46
  control: 'boolean',
@@ -81,7 +54,7 @@ const meta: Meta = {
81
54
  defaultValue: { summary: 'false' },
82
55
  },
83
56
  errorMessage: {
84
- control: false,
57
+ control: 'text',
85
58
  description: 'Error message',
86
59
  table: {
87
60
  category: 'Props',
@@ -101,17 +74,6 @@ const meta: Meta = {
101
74
  },
102
75
  },
103
76
  },
104
- hasHiddenLabel: {
105
- control: 'boolean',
106
- description: 'Hides the label visually (retains it for screen readers)',
107
- table: {
108
- category: 'Props',
109
- type: {
110
- summary: 'boolean',
111
- },
112
- },
113
- defaultValue: { summary: 'false' },
114
- },
115
77
  iconName: {
116
78
  control: 'select',
117
79
  options: iconNames,
@@ -140,6 +102,7 @@ const meta: Meta = {
140
102
  disable: true,
141
103
  },
142
104
  },
105
+ ...labelArgTypes,
143
106
  },
144
107
  };
145
108
 
@@ -147,11 +110,12 @@ export default meta;
147
110
 
148
111
  type Story = StoryObj<typeof Input>;
149
112
 
150
- const defaultArgs = {
113
+ const defaultArgs: InputProps = {
151
114
  label: 'Enter your name',
152
115
  name: 'first_name',
153
116
  placeholder: 'Please enter a value',
154
- } as InputProps;
117
+ onChange: () => {},
118
+ };
155
119
 
156
120
  export const Default: Story = {
157
121
  args: {
@@ -177,6 +141,7 @@ export const Default: Story = {
177
141
  const handleChange = (e: { target: { value: SetStateAction<string> } }) => {
178
142
  setValue(e.target.value);
179
143
  };
144
+
180
145
  return <Input {...args} value={value} onChange={handleChange} />;
181
146
  },
182
147
  };
@@ -1,30 +1,27 @@
1
1
  import React from 'react';
2
+ import classNames from 'classnames';
3
+
2
4
  import { Icon } from '@/components/icons';
3
5
  import { IconName } from '@/types';
4
- import { Label } from '../subcomponents/Label';
6
+ import { withLabel, WithLabelProps } from '../subcomponents/Label';
5
7
  import { DisplayFormError } from '../subcomponents/DisplayFormError';
6
8
 
7
- export interface InputProps {
8
- label: string;
9
- name: string;
9
+ export interface InputProps extends WithLabelProps {
10
10
  value?: string | undefined;
11
- placeholder: string;
11
+ placeholder?: string;
12
12
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
13
- isRequired?: boolean;
14
13
  isDisabled?: boolean;
15
14
  errorMessage?: string | undefined;
16
15
  helpText?: string;
17
- hasHiddenLabel?: boolean;
18
16
  iconName?: IconName;
19
17
  isClearable?: boolean;
20
18
  className?: string;
21
19
  defaultValue?: string;
22
20
  }
23
21
 
24
- export const Input = React.forwardRef<HTMLInputElement, InputProps>(
22
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
25
23
  (
26
24
  {
27
- label,
28
25
  name,
29
26
  placeholder,
30
27
  onChange,
@@ -34,7 +31,6 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
34
31
  errorMessage,
35
32
  helpText,
36
33
  iconName,
37
- hasHiddenLabel,
38
34
  className,
39
35
  ...rest
40
36
  },
@@ -45,9 +41,17 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
45
41
  onChange({ target: { value: '' } } as React.ChangeEvent<HTMLInputElement>);
46
42
  };
47
43
 
44
+ const inputClasses = classNames(
45
+ 'input',
46
+ {
47
+ error: hasErrors,
48
+ 'input--has-icon': iconName,
49
+ },
50
+ className,
51
+ );
52
+
48
53
  return (
49
- <div className="form-control">
50
- <Label label={label} name={name} isRequired={isRequired} hasHiddenLabel={hasHiddenLabel} />
54
+ <>
51
55
  <div className="input-wrapper">
52
56
  {iconName && (
53
57
  <Icon name={iconName} data-testid={`${name}-embedded-icon`} className="embedded-icon" />
@@ -60,11 +64,10 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
60
64
  disabled={isDisabled}
61
65
  placeholder={placeholder}
62
66
  onChange={onChange}
63
- className={`input ${hasErrors ? 'error' : ''} ${iconName ? 'input--has-icon' : ''} ${className}`}
67
+ className={inputClasses}
64
68
  aria-invalid={hasErrors ? true : undefined}
65
69
  aria-describedby={hasErrors || helpText ? `${name}-helper` : undefined}
66
70
  aria-required={isRequired}
67
- aria-label={label}
68
71
  {...rest}
69
72
  />
70
73
  {isClearable && (
@@ -83,7 +86,11 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
83
86
  {helpText}
84
87
  </div>
85
88
  )}
86
- </div>
89
+ </>
87
90
  );
88
91
  },
89
92
  );
93
+
94
+ const LabeledInput = withLabel(Input);
95
+
96
+ export { LabeledInput as Input };
@@ -94,17 +94,6 @@
94
94
  cursor: pointer;
95
95
  }
96
96
  }
97
- .is-visually-hidden {
98
- position: absolute;
99
- width: 1px;
100
- height: 1px;
101
- padding: 0;
102
- margin: -1px;
103
- overflow: hidden;
104
- clip: rect(0, 0, 0, 0);
105
- white-space: nowrap;
106
- border: 0;
107
- }
108
97
  .form-label {
109
98
  margin-bottom: var(--pf-margin-2);
110
99
  }
@@ -5,22 +5,24 @@ import * as PasswordInput from './PasswordInput.stories';
5
5
 
6
6
  # Password Input
7
7
 
8
- The password input component is the building block of any form. Below you will find the accepted properties for this component. It is encouraged to build forms utilizing [React Hook Form](https://react-hook-form.com/) library in your application. This will facilitate form state management and enforce best practices. (***Our components are compatible with but do not provide the plugin***)
8
+ The password input component is the building block of any form. Below you will find the accepted properties for this component. It is encouraged to build forms utilizing [React Hook Form](https://react-hook-form.com/) library in your application. This will facilitate form state management and enforce best practices. (**_Our components are compatible with but do not provide the plugin_**)
9
9
 
10
10
  <Canvas
11
11
  of={PasswordInput.Default}
12
12
  source={{
13
13
  code: `
14
14
  <PasswordInput
15
- name="first_name"
15
+ label="Label Name"
16
+ name="first_name"
17
+ placeholder="Please enter a value"
18
+ helpText="This Is Help Text"
16
19
  isRequired
20
+ hasHiddenLabel={false}
17
21
  hasShowPassword
18
- placeholder="Placeholder Text"
19
- value=''
20
- onChange={() => {}}
21
- helpText="This Is Help Text"
22
- label="Label Name"
23
- />
22
+ isDisabled={false}
23
+ errorMessage=""
24
+ value=""
25
+ onChange={() => {}}/>
24
26
  `,
25
27
  }}
26
28
  />
@@ -1,7 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
  import { PasswordInput, PasswordInputProps } from './PasswordInput';
3
3
  import { SetStateAction, useEffect, useState } from 'react';
4
- import { iconNames } from 'build/generated/iconTypes';
4
+ import labelArgTypes from '@/storybook/labelArgTypes';
5
5
 
6
6
  const meta: Meta = {
7
7
  title: 'Forms/PasswordInput',
@@ -29,26 +29,6 @@ const meta: Meta = {
29
29
  },
30
30
  action: 'onChange',
31
31
  },
32
- label: {
33
- control: 'text',
34
- description: 'The label for the password field',
35
- table: {
36
- category: 'Props',
37
- type: {
38
- summary: 'string',
39
- },
40
- },
41
- },
42
- name: {
43
- control: 'text',
44
- description: 'The name for the password field',
45
- table: {
46
- category: 'Props',
47
- type: {
48
- summary: 'string',
49
- },
50
- },
51
- },
52
32
  placeholder: {
53
33
  control: 'text',
54
34
  description: 'The placeholder for the password field',
@@ -69,17 +49,6 @@ const meta: Meta = {
69
49
  },
70
50
  },
71
51
  },
72
- isRequired: {
73
- control: 'boolean',
74
- description: 'Toggles the required astherisk on the label',
75
- table: {
76
- category: 'Props',
77
- type: {
78
- summary: 'boolean',
79
- },
80
- },
81
- defaultValue: { summary: 'false' },
82
- },
83
52
  isDisabled: {
84
53
  control: 'boolean',
85
54
  description: 'Toggles the disabled state of the input',
@@ -112,22 +81,12 @@ const meta: Meta = {
112
81
  },
113
82
  },
114
83
  },
115
- hasHiddenLabel: {
116
- control: 'boolean',
117
- description: 'Hides the label visually (retains it for screen readers)',
118
- table: {
119
- category: 'Props',
120
- type: {
121
- summary: 'boolean',
122
- },
123
- },
124
- defaultValue: { summary: 'false' },
125
- },
126
84
  ref: {
127
85
  table: {
128
86
  disable: true,
129
87
  },
130
88
  },
89
+ ...labelArgTypes,
131
90
  },
132
91
  };
133
92
 
@@ -143,7 +102,7 @@ const defaultArgs = {
143
102
 
144
103
  export const Default: Story = {
145
104
  args: {
146
- isRequired: false,
105
+ isRequired: true,
147
106
  helpText: 'This Is Help Text',
148
107
  label: 'Label Name',
149
108
  name: 'first_name',
@@ -1,28 +1,24 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Icon } from '@/components/icons';
3
- import { Label } from '../subcomponents/Label';
3
+ import { withLabel, WithLabelProps } from '../subcomponents/Label';
4
4
  import { DisplayFormError } from '../subcomponents/DisplayFormError';
5
+ import classNames from 'classnames';
5
6
 
6
- export interface PasswordInputProps {
7
+ export interface PasswordInputProps extends WithLabelProps {
7
8
  ref?: React.LegacyRef<HTMLInputElement>;
8
- label: string;
9
9
  value?: string | undefined;
10
- name: string;
11
- placeholder: string;
10
+ placeholder?: string;
12
11
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
13
- isRequired?: boolean;
14
12
  isDisabled?: boolean;
15
13
  errorMessage?: string | undefined;
16
14
  helpText?: string;
17
- hasHiddenLabel?: boolean;
18
15
  hasShowPassword?: boolean;
19
16
  defaultValue?: string;
20
17
  }
21
18
 
22
- export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(
19
+ const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(
23
20
  (
24
21
  {
25
- label,
26
22
  name,
27
23
  placeholder,
28
24
  onChange,
@@ -30,7 +26,6 @@ export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputPro
30
26
  isDisabled,
31
27
  errorMessage,
32
28
  helpText,
33
- hasHiddenLabel,
34
29
  hasShowPassword = true,
35
30
  ...rest
36
31
  },
@@ -44,9 +39,16 @@ export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputPro
44
39
  setShowPassword((prevShowPassword) => !prevShowPassword);
45
40
  };
46
41
 
42
+ const inputClasses = classNames(
43
+ 'password-input',
44
+ {
45
+ error: hasErrors,
46
+ },
47
+ 'password-input--has-icon',
48
+ );
49
+
47
50
  return (
48
- <div className="form-control">
49
- <Label label={label} name={name} isRequired={isRequired} hasHiddenLabel={hasHiddenLabel} />
51
+ <>
50
52
  <div className="password-input-wrapper">
51
53
  <Icon name="lock" data-testid={`${name}-embedded-icon`} className="embedded-icon" />
52
54
  <input
@@ -57,11 +59,10 @@ export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputPro
57
59
  disabled={isDisabled}
58
60
  placeholder={placeholder}
59
61
  onChange={onChange}
60
- className={`password-input ${hasErrors ? 'error' : ''} password-input--has-icon`}
62
+ className={inputClasses}
61
63
  aria-invalid={hasErrors ? 'true' : 'false'}
62
64
  aria-describedby={hasErrors || helpText ? `${name}-helper` : undefined}
63
65
  aria-required={isRequired}
64
- aria-label={label}
65
66
  {...rest}
66
67
  />
67
68
  {hasShowPassword && (
@@ -80,7 +81,11 @@ export const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputPro
80
81
  {helpText}
81
82
  </div>
82
83
  )}
83
- </div>
84
+ </>
84
85
  );
85
86
  },
86
87
  );
88
+
89
+ const LabeledPasswordInput = withLabel(PasswordInput);
90
+
91
+ export { LabeledPasswordInput as PasswordInput };
@@ -101,17 +101,6 @@
101
101
  cursor: pointer;
102
102
  }
103
103
  }
104
- .is-visually-hidden {
105
- position: absolute;
106
- width: 1px;
107
- height: 1px;
108
- padding: 0;
109
- margin: -1px;
110
- overflow: hidden;
111
- clip: rect(0, 0, 0, 0);
112
- white-space: nowrap;
113
- border: 0;
114
- }
115
104
  .form-label {
116
105
  margin-bottom: var(--pf-margin-2);
117
106
  }