-
Notifications
You must be signed in to change notification settings - Fork 9
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
Changes from 1 commit
810becd
e7ea3aa
f69fd7f
77b7def
9f89baa
110608c
868a5ac
7603a3d
5c5959d
a8098e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,12 @@ | ||
import React from 'react'; | ||
|
||
import {Copy, CopyCheck, Eye, EyeSlash} from '@gravity-ui/icons'; | ||
import { | ||
Button, | ||
CopyToClipboard, | ||
CopyToClipboardStatus, | ||
Icon, | ||
TextInput, | ||
TextInputProps, | ||
} from '@gravity-ui/uikit'; | ||
import {Eye, EyeSlash} from '@gravity-ui/icons'; | ||
import {Button, ClipboardButton, TextInput, TextInputProps, Tooltip} from '@gravity-ui/uikit'; | ||
|
||
import {block} from '../utils/cn'; | ||
|
||
import i18n from './i18n'; | ||
|
||
import './PasswordInput.scss'; | ||
|
||
const b = block('password-input'); | ||
|
@@ -20,18 +15,27 @@ export type PasswordInputProps = Required<Pick<TextInputProps, 'onUpdate' | 'val | |
Omit<TextInputProps, 'type'> & { | ||
/** Show copy button */ | ||
showCopyButton?: boolean; | ||
/** Show visibility button */ | ||
showVisibilityButton?: boolean; | ||
/** Show reveal button */ | ||
showRevealButton?: boolean; | ||
/** Disable tooltip. Tooltip won't be shown */ | ||
hasTooltip?: boolean; | ||
}; | ||
|
||
export const PasswordInput: React.FC<PasswordInputProps> = (props) => { | ||
const {autoComplete, value, showCopyButton, rightContent, showVisibilityButton, className} = | ||
props; | ||
const { | ||
autoComplete, | ||
value, | ||
showCopyButton, | ||
rightContent, | ||
showRevealButton, | ||
size = 'm', | ||
hasTooltip = true, | ||
} = props; | ||
|
||
const [hideValue, setHideValue] = React.useState(true); | ||
|
||
const additionalRightContent = React.useMemo(() => { | ||
if (!showVisibilityButton && !showCopyButton) { | ||
if (!showRevealButton && !showCopyButton) { | ||
return <React.Fragment>{rightContent}</React.Fragment>; | ||
} | ||
|
||
|
@@ -43,40 +47,47 @@ export const PasswordInput: React.FC<PasswordInputProps> = (props) => { | |
<div className={b('additional-right-content')}> | ||
{rightContent} | ||
{value && showCopyButton ? ( | ||
<CopyToClipboard text={String(value)} timeout={500}> | ||
{(state) => ( | ||
<Button view="flat-secondary" className={b('button')} size="s"> | ||
<Icon | ||
size={14} | ||
data={ | ||
state === CopyToClipboardStatus.Pending ? Copy : CopyCheck | ||
} | ||
/> | ||
</Button> | ||
)} | ||
</CopyToClipboard> | ||
<ClipboardButton | ||
text={value} | ||
hasTooltip={hasTooltip} | ||
size={16} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should map input size to button size |
||
className={b('copy-button')} | ||
/> | ||
) : null} | ||
{showVisibilityButton ? ( | ||
<Button | ||
view="flat-secondary" | ||
onClick={onClick} | ||
className={b('button')} | ||
size="s" | ||
{showRevealButton ? ( | ||
<Tooltip | ||
disabled={!hasTooltip} | ||
content={ | ||
hideValue ? i18n('label_show-password') : i18n('label_hide-password') | ||
} | ||
> | ||
<Icon data={hideValue ? Eye : EyeSlash} size={14} /> | ||
</Button> | ||
<Button | ||
view="flat-secondary" | ||
onClick={onClick} | ||
size={size} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TextInput size !== Button size, take a look at clear button, maybe reuse this logic here as well |
||
extraProps={{ | ||
'aria-label': hideValue | ||
? i18n('label_show-password') | ||
: i18n('label_hide-password'), | ||
}} | ||
> | ||
<Button.Icon>{hideValue ? <Eye /> : <EyeSlash />}</Button.Icon> | ||
</Button> | ||
</Tooltip> | ||
) : null} | ||
</div> | ||
); | ||
}, [rightContent, value, showCopyButton, showVisibilityButton, hideValue]); | ||
}, [showRevealButton, showCopyButton, rightContent, value, hasTooltip, hideValue, size]); | ||
|
||
return ( | ||
<TextInput | ||
{...props} | ||
type={hideValue ? 'password' : 'text'} | ||
rightContent={additionalRightContent} | ||
autoComplete={autoComplete ? autoComplete : 'new-password'} | ||
className={b('input', className)} | ||
controlProps={{ | ||
className: b(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now it's an opposite, you're passing root className ( |
||
}} | ||
/> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"label_show-password": "Show password", | ||
"label_hide-password": "Hide password" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import {registerKeyset} from '../../utils/registerKeyset'; | ||
|
||
import en from './en.json'; | ||
import ru from './ru.json'; | ||
|
||
const COMPONENT = 'PasswordInput'; | ||
|
||
export default registerKeyset({en, ru}, COMPONENT); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"label_show-password": "Показать пароль", | ||
"label_hide-password": "Скрыть пароль" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would pick separate names here,
hasCopyTooltip
andhasRevealTooltip