Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: made a new password input component #108

Merged
merged 10 commits into from
Nov 1, 2023
8 changes: 5 additions & 3 deletions src/components/PasswordInput/PasswordInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
$block: '.#{variables.$ns}password-input';

#{$block} {
&::-ms-reveal,
&::-ms-clear {
display: none;
&__input-control {
&::-ms-reveal,
&::-ms-clear {
display: none;
}
}

&__additional-right-content {
Expand Down
39 changes: 28 additions & 11 deletions src/components/PasswordInput/PasswordInput.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';

import {Eye, EyeSlash} from '@gravity-ui/icons';
import {Button, ClipboardButton, TextInput, TextInputProps, Tooltip} from '@gravity-ui/uikit';
import {Button, ClipboardButton, Icon, TextInput, TextInputProps, Tooltip} from '@gravity-ui/uikit';

import {block} from '../utils/cn';

import i18n from './i18n';
import {getCopyButtonSizeAndIconSize} from './utils';

import './PasswordInput.scss';

Expand All @@ -17,8 +18,10 @@ export type PasswordInputProps = Required<Pick<TextInputProps, 'onUpdate' | 'val
showCopyButton?: boolean;
/** Show reveal button */
showRevealButton?: boolean;
/** Disable tooltip. Tooltip won't be shown */
hasTooltip?: boolean;
/** Disable the tooltip for the copy button. The tooltip will not be displayed */
hasCopyTooltip?: boolean;
/** Disable the tooltip for the reveal button. The tooltip will not be displayed */
hasRevealTooltip?: boolean;
};

export const PasswordInput: React.FC<PasswordInputProps> = (props) => {
Expand All @@ -29,7 +32,9 @@ export const PasswordInput: React.FC<PasswordInputProps> = (props) => {
rightContent,
showRevealButton,
size = 'm',
hasTooltip = true,
hasCopyTooltip = true,
hasRevealTooltip = true,
controlProps,
} = props;

const [hideValue, setHideValue] = React.useState(true);
Expand All @@ -43,41 +48,52 @@ export const PasswordInput: React.FC<PasswordInputProps> = (props) => {
setHideValue((hideValue) => !hideValue);
};

const {copyButtonSize, iconSize} = getCopyButtonSizeAndIconSize(size);

return (
<div className={b('additional-right-content')}>
{rightContent}
{value && showCopyButton ? (
<ClipboardButton
text={value}
hasTooltip={hasTooltip}
size={16}
hasTooltip={hasRevealTooltip}
size={iconSize}
className={b('copy-button')}
/>
) : null}
{showRevealButton ? (
<Tooltip
disabled={!hasTooltip}
disabled={!hasCopyTooltip}
content={
hideValue ? i18n('label_show-password') : i18n('label_hide-password')
}
>
<Button
view="flat-secondary"
onClick={onClick}
size={size}
size={copyButtonSize}
extraProps={{
'aria-label': hideValue
? i18n('label_show-password')
: i18n('label_hide-password'),
}}
>
<Button.Icon>{hideValue ? <Eye /> : <EyeSlash />}</Button.Icon>
<Icon data={hideValue ? Eye : EyeSlash} size={iconSize} />
</Button>
</Tooltip>
) : null}
</div>
);
}, [showRevealButton, showCopyButton, rightContent, value, hasTooltip, hideValue, size]);
}, [
showRevealButton,
showCopyButton,
rightContent,
value,
hasRevealTooltip,
hasCopyTooltip,
hideValue,
size,
]);

return (
<TextInput
Expand All @@ -86,7 +102,8 @@ export const PasswordInput: React.FC<PasswordInputProps> = (props) => {
rightContent={additionalRightContent}
autoComplete={autoComplete ? autoComplete : 'new-password'}
controlProps={{
className: b(),
className: b('input-control', controlProps?.className),
...controlProps,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spread should be before the className, otherwise it would be overwritten by the controlProps

}}
/>
);
Expand Down
13 changes: 7 additions & 6 deletions src/components/PasswordInput/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ Same as [TextInput component](https://github.com/gravity-ui/uikit/blob/main/src/
- `onUpdate` is required property;
- `type` is omitted;

| Property | Type | Required | Default | Description |
| :--------------- | :-------- | :------- | :------ | :-------------------------------------- |
| showCopyButton | `boolean` | | | Show copy button |
| showRevealButton | `boolean` | | | Show reveal button |
| hasTooltip | `boolean` | | `true` | Disable tooltip. Tooltip won't be shown |
| Property | Type | Required | Default | Description |
| :--------------- | :-------- | :------- | :------ | :--------------------------------------------------------------------------- |
| showCopyButton | `boolean` | | | Show copy button |
| showRevealButton | `boolean` | | | Show reveal button |
| hasCopyTooltip | `boolean` | | `true` | Disable the tooltip for the copy button. The tooltip will not be displayed |
| hasRevealTooltip | `boolean` | | `true` | Disable the tooltip for the reveal button. The tooltip will not be displayed |

#### Usage example

Expand All @@ -25,7 +26,7 @@ function MyComponent() {
return (
<PasswordInput
showCopyButton={true}
showVisibilityButton={true}
showRevealButton={true}
onUpdate={setValue}
value={value}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Button} from '@gravity-ui/uikit';
import type {Meta, StoryFn} from '@storybook/react';

import {cn} from '../../utils/cn';
import {PasswordInput} from '../PasswordInput';
import {PasswordInput, PasswordInputProps} from '../PasswordInput';

import './PasswordInputStories.scss';

Expand All @@ -13,26 +13,21 @@ const b = cn('password-input-stories');
export default {
title: 'Components/PasswordInput',
component: PasswordInput,
args: {
showCopyButton: true,
showRevealButton: true,
},
} as Meta;

const DefaultTemplate: StoryFn<React.ComponentProps<typeof PasswordInput>> = () => {
const DefaultTemplate: StoryFn<PasswordInputProps> = (args) => {
const [value, setValue] = React.useState('');

return (
<PasswordInput
showCopyButton={true}
showRevealButton={true}
onUpdate={setValue}
value={value}
/>
);
return <PasswordInput {...args} onUpdate={setValue} value={value} />;
};

export const Default = DefaultTemplate.bind({});

const WithGenerateRandomValueTemplate: StoryFn<React.ComponentProps<typeof PasswordInput>> = (
props: React.ComponentProps<typeof PasswordInput>,
) => {
const WithGenerateRandomValueTemplate: StoryFn<PasswordInputProps> = (args) => {
const [value, setValue] = React.useState('');

const generateRandomValue = React.useCallback(() => {
Expand All @@ -51,7 +46,7 @@ const WithGenerateRandomValueTemplate: StoryFn<React.ComponentProps<typeof Passw

return (
<div className={b()}>
<PasswordInput {...props} onUpdate={setValue} value={value} />
<PasswordInput {...args} onUpdate={setValue} value={value} />
<Button onClick={generateRandomValue} className={b('button-generate-random-value')}>
Copy link

@personaljs personaljs Oct 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add prop showCopyButton and showRevealButton?

Generate random value
</Button>
Expand Down
26 changes: 26 additions & 0 deletions src/components/PasswordInput/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type {ButtonSize, InputControlSize} from '@gravity-ui/uikit';

export const getCopyButtonSizeAndIconSize = (
textInputSize: InputControlSize,
): {copyButtonSize: ButtonSize; iconSize: number} => {
let copyButtonSize: ButtonSize = 's';
let iconSize = 16;

switch (textInputSize) {
case 's': {
copyButtonSize = 'xs';
iconSize = 12;
break;
}
case 'l': {
copyButtonSize = 'm';
break;
}
case 'xl': {
copyButtonSize = 'l';
iconSize = 20;
}
}

return {copyButtonSize, iconSize};
};
Loading