@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.
- package/lib/index.css +55 -33
- package/lib/index.d.ts +34 -20
- package/lib/index.esm.css +55 -33
- package/lib/index.esm.js +1666 -85
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1669 -86
- package/lib/index.js.map +1 -1
- package/lib/src/components/forms/input/Input.d.ts +5 -7
- package/lib/src/components/forms/passwordInput/PasswordInput.d.ts +5 -7
- package/lib/src/components/forms/subcomponents/Label.d.ts +6 -3
- package/lib/src/components/forms/textarea/Textarea.d.ts +5 -7
- package/lib/src/components/index.d.ts +2 -0
- package/lib/src/components/menu/Menu.d.ts +5 -0
- package/lib/src/components/menu/Menu.stories.d.ts +6 -0
- package/lib/src/components/menu/Menu.test.d.ts +1 -0
- package/lib/src/components/menu/index.d.ts +1 -0
- package/lib/src/components/popper/Popper.d.ts +12 -0
- package/lib/src/components/popper/Popper.stories.d.ts +6 -0
- package/lib/src/components/popper/Popper.test.d.ts +1 -0
- package/lib/src/components/popper/index.d.ts +1 -0
- package/lib/src/hooks/useClickOutside.d.ts +2 -0
- package/lib/src/index.d.ts +2 -0
- package/lib/src/storybook/labelArgTypes.d.ts +3 -0
- package/package.json +2 -1
- package/src/components/forms/input/Input.mdx +15 -2
- package/src/components/forms/input/Input.stories.tsx +10 -45
- package/src/components/forms/input/Input.tsx +22 -15
- package/src/components/forms/input/styles/Input.scss +0 -11
- package/src/components/forms/passwordInput/PasswordInput.mdx +10 -8
- package/src/components/forms/passwordInput/PasswordInput.stories.tsx +3 -44
- package/src/components/forms/passwordInput/PasswordInput.tsx +20 -15
- package/src/components/forms/passwordInput/styles/PasswordInput.scss +0 -11
- package/src/components/forms/subcomponents/Label.tsx +29 -6
- package/src/components/forms/subcomponents/__tests__/Label.test.tsx +63 -15
- package/src/components/forms/textarea/Textarea.mdx +12 -2
- package/src/components/forms/textarea/Textarea.stories.tsx +4 -46
- package/src/components/forms/textarea/Textarea.tsx +15 -13
- package/src/components/forms/textarea/styles/Textarea.scss +0 -11
- package/src/components/index.ts +2 -0
- package/src/components/menu/Menu.mdx +15 -0
- package/src/components/menu/Menu.stories.tsx +56 -0
- package/src/components/menu/Menu.test.tsx +88 -0
- package/src/components/menu/Menu.tsx +20 -0
- package/src/components/menu/index.ts +1 -0
- package/src/components/menu/styles/Menu.scss +19 -0
- package/src/components/menu/styles/_variables.scss +15 -0
- package/src/components/popper/Popper.mdx +79 -0
- package/src/components/popper/Popper.stories.tsx +161 -0
- package/src/components/popper/Popper.test.tsx +68 -0
- package/src/components/popper/Popper.tsx +57 -0
- package/src/components/popper/index.ts +1 -0
- package/src/components/popper/styles/Popper.scss +11 -0
- package/src/components/popper/styles/_variables.scss +15 -0
- package/src/hooks/useClickOutside.tsx +22 -0
- package/src/index.ts +2 -0
- package/src/legacy/components/buttons/commonStyles.ts +0 -4
- package/src/storybook/labelArgTypes.ts +50 -0
- package/src/styles/index.scss +2 -0
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { IconName } from '@/types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
name: string;
|
|
3
|
+
import { WithLabelProps } from '../subcomponents/Label';
|
|
4
|
+
export interface InputProps extends WithLabelProps {
|
|
6
5
|
value?: string | undefined;
|
|
7
|
-
placeholder
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2
|
+
import { WithLabelProps } from '../subcomponents/Label';
|
|
3
|
+
export interface TextareaProps extends WithLabelProps {
|
|
3
4
|
ref?: React.LegacyRef<HTMLTextAreaElement>;
|
|
4
|
-
|
|
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
|
-
|
|
20
|
+
declare const LabeledTextarea: React.ForwardRefExoticComponent<Omit<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement> & WithLabelProps, "ref"> & React.RefAttributes<any>>;
|
|
21
|
+
export { LabeledTextarea as Textarea };
|
|
@@ -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 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Popper } from './Popper';
|
package/lib/src/index.d.ts
CHANGED
|
@@ -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';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indico-data/design-system",
|
|
3
|
-
"version": "2.
|
|
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. (
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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={
|
|
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
|
-
|
|
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. (
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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:
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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={
|
|
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
|
-
|
|
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
|
}
|