Skip to content

Commit

Permalink
feat: Add reveal button to password textbox h2oai#1977 (h2oai#2198)
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-mihok authored Nov 21, 2023
1 parent de4af7e commit 9c05467
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
2 changes: 2 additions & 0 deletions py/examples/textbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async def serve(q: Q):
ui.text(f'textbox_spellcheck_disabled={q.args.textbox_spellcheck_disabled}'),
ui.text(f'textbox_numeric={q.args.textbox_numeric}'),
ui.text(f'textbox_tel={q.args.textbox_tel}'),
ui.text(f'textbox_password={q.args.textbox_password}'),
ui.button(name='show_form', label='Back', primary=True),
]
else:
Expand All @@ -44,6 +45,7 @@ async def serve(q: Q):
ui.textbox(name='textbox_spellcheck_disabled', label='Spellcheck disabled', spellcheck=False),
ui.textbox(name='textbox_numeric', label='With numeric keyboard (iOS, Android)', type='number'),
ui.textbox(name='textbox_tel', label='With telephone keyboard (iOS, Android)', type='tel'),
ui.textbox(name='textbox_password', label='Password', password=True),
ui.button(name='show_inputs', label='Submit', primary=True),
])
await q.page.save()
27 changes: 19 additions & 8 deletions ui/src/textbox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('Textbox.tsx', () => {
})

it('Debounces wave push', () => {
const { getByTestId } = render(<XTextbox model={{...textboxProps, trigger: true}} />)
const { getByTestId } = render(<XTextbox model={{ ...textboxProps, trigger: true }} />)

userEvent.type(getByTestId(name), 'a')
userEvent.type(getByTestId(name), 'a')
Expand All @@ -125,10 +125,10 @@ describe('Textbox.tsx', () => {
})

it('Display new value when "value" prop changes', () => {
const { getByTestId, rerender } = render(<XTextbox model={{...textboxProps, value: 'A'}} />)
const { getByTestId, rerender } = render(<XTextbox model={{ ...textboxProps, value: 'A' }} />)
expect(getByTestId(name)).toHaveValue('A')

rerender(<XTextbox model={{...textboxProps, value: 'B'}} />)
rerender(<XTextbox model={{ ...textboxProps, value: 'B' }} />)
expect(getByTestId(name)).toHaveValue('B')
})

Expand All @@ -137,24 +137,35 @@ describe('Textbox.tsx', () => {
userEvent.type(getByTestId(name), '{backspace}A{Enter}')
expect(getByTestId(name)).toHaveValue('A')

rerender(<XTextbox model={{...textboxProps, value: 'B'}} />)
rerender(<XTextbox model={{ ...textboxProps, value: 'B' }} />)
expect(getByTestId(name)).toHaveValue('B')
})

it('Display new value when "value" prop changes (masked)', () => {
const { getByTestId, rerender } = render(<XTextbox model={{...textboxProps, value: '123', mask: '(999)'}} />)
const { getByTestId, rerender } = render(<XTextbox model={{ ...textboxProps, value: '123', mask: '(999)' }} />)
expect(getByTestId(name)).toHaveValue('(123)')

rerender(<XTextbox model={{...textboxProps, value: '456', mask: '(999)'}} />)
rerender(<XTextbox model={{ ...textboxProps, value: '456', mask: '(999)' }} />)
expect(getByTestId(name)).toHaveValue('(456)')
})

it('Types value and then display new value when "value" prop changes (masked)', () => {
const { getByTestId, rerender } = render(<XTextbox model={{...textboxProps, mask: '(999)'}} />)
const { getByTestId, rerender } = render(<XTextbox model={{ ...textboxProps, mask: '(999)' }} />)
userEvent.type(getByTestId(name), '{backspace}123{Enter}')
expect(getByTestId(name)).toHaveValue('(123)')

rerender(<XTextbox model={{...textboxProps, value: '456', mask: '(999)'}} />)
rerender(<XTextbox model={{ ...textboxProps, value: '456', mask: '(999)' }} />)
expect(getByTestId(name)).toHaveValue('(456)')
})

it('Can reveal password', () => {
const { container, getByTestId } = render(<XTextbox model={{ ...textboxProps, password: true }} />)
const revealButton = container.querySelector('button')

expect(revealButton).toBeInTheDocument()
expect(getByTestId(name)).toHaveAttribute('type', 'password')

fireEvent.click(revealButton!)
expect(getByTestId(name)).toHaveAttribute('type', 'text')
})
})
1 change: 1 addition & 0 deletions ui/src/textbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const
multiline: m.multiline,
spellCheck: m.spellcheck,
type: m.password ? 'password' : (m.type || 'text'),
canRevealPassword: true,
}

React.useEffect(() => {
Expand Down
11 changes: 11 additions & 0 deletions website/widgets/form/textbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,14 @@ q.page['example'] = ui.form_card(
]
)
```

## Password

Prompt for passwords.

```py
q.page['example'] = ui.form_card(
box='1 1 2 2',
items=[ui.textbox(name='textbox_password', label='Password', value='123456', password=True)]
)
```

0 comments on commit 9c05467

Please sign in to comment.