Skip to content

Commit

Permalink
chore: keep native browser behavior for tel|number input type #2170
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-mihok committed Nov 16, 2023
1 parent 4b60f76 commit 1f4b452
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 59 deletions.
4 changes: 2 additions & 2 deletions py/examples/textbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ async def serve(q: Q):
placeholder='I am disabled'),
ui.textbox(name='textbox_multiline', label='Multiline textarea', multiline=True),
ui.textbox(name='textbox_spellcheck_disabled', label='Spellcheck disabled', spellcheck=False),
ui.textbox(name='textbox_numeric', label='With numeric keyboard (iOS, Android)', keyboard='number'),
ui.textbox(name='textbox_tel', label='With telephone keyboard (iOS, Android)', keyboard='tel'),
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.button(name='show_inputs', label='Submit', primary=True),
])
await q.page.save()
24 changes: 12 additions & 12 deletions py/h2o_lightwave/h2o_lightwave/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -969,10 +969,10 @@ def load(__d: Dict) -> 'MessageBar':
)


_TextboxKeyboard = ['text', 'number', 'tel']
_TextboxType = ['text', 'number', 'tel']


class TextboxKeyboard:
class TextboxType:
TEXT = 'text'
NUMBER = 'number'
TEL = 'tel'
Expand Down Expand Up @@ -1007,7 +1007,7 @@ def __init__(
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
spellcheck: Optional[bool] = None,
keyboard: Optional[str] = None,
type: Optional[str] = None,
):
_guard_scalar('Textbox.name', name, (str,), True, False, False)
_guard_scalar('Textbox.label', label, (str,), False, True, False)
Expand All @@ -1029,7 +1029,7 @@ def __init__(
_guard_scalar('Textbox.visible', visible, (bool,), False, True, False)
_guard_scalar('Textbox.tooltip', tooltip, (str,), False, True, False)
_guard_scalar('Textbox.spellcheck', spellcheck, (bool,), False, True, False)
_guard_enum('Textbox.keyboard', keyboard, _TextboxKeyboard, True)
_guard_enum('Textbox.type', type, _TextboxType, True)
self.name = name
"""An identifying name for this component."""
self.label = label
Expand Down Expand Up @@ -1070,8 +1070,8 @@ def __init__(
"""An optional tooltip message displayed when a user clicks the help icon to the right of the component."""
self.spellcheck = spellcheck
"""True if the text may be checked for spelling errors. Defaults to True."""
self.keyboard = keyboard
"""Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxKeyboard."""
self.type = type
"""Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxType."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
Expand All @@ -1095,7 +1095,7 @@ def dump(self) -> Dict:
_guard_scalar('Textbox.visible', self.visible, (bool,), False, True, False)
_guard_scalar('Textbox.tooltip', self.tooltip, (str,), False, True, False)
_guard_scalar('Textbox.spellcheck', self.spellcheck, (bool,), False, True, False)
_guard_enum('Textbox.keyboard', self.keyboard, _TextboxKeyboard, True)
_guard_enum('Textbox.type', self.type, _TextboxType, True)
return _dump(
name=self.name,
label=self.label,
Expand All @@ -1117,7 +1117,7 @@ def dump(self) -> Dict:
visible=self.visible,
tooltip=self.tooltip,
spellcheck=self.spellcheck,
keyboard=self.keyboard,
type=self.type,
)

@staticmethod
Expand Down Expand Up @@ -1163,8 +1163,8 @@ def load(__d: Dict) -> 'Textbox':
_guard_scalar('Textbox.tooltip', __d_tooltip, (str,), False, True, False)
__d_spellcheck: Any = __d.get('spellcheck')
_guard_scalar('Textbox.spellcheck', __d_spellcheck, (bool,), False, True, False)
__d_keyboard: Any = __d.get('keyboard')
_guard_enum('Textbox.keyboard', __d_keyboard, _TextboxKeyboard, True)
__d_type: Any = __d.get('type')
_guard_enum('Textbox.type', __d_type, _TextboxType, True)
name: str = __d_name
label: Optional[str] = __d_label
placeholder: Optional[str] = __d_placeholder
Expand All @@ -1185,7 +1185,7 @@ def load(__d: Dict) -> 'Textbox':
visible: Optional[bool] = __d_visible
tooltip: Optional[str] = __d_tooltip
spellcheck: Optional[bool] = __d_spellcheck
keyboard: Optional[str] = __d_keyboard
type: Optional[str] = __d_type
return Textbox(
name,
label,
Expand All @@ -1207,7 +1207,7 @@ def load(__d: Dict) -> 'Textbox':
visible,
tooltip,
spellcheck,
keyboard,
type,
)


Expand Down
6 changes: 3 additions & 3 deletions py/h2o_lightwave/h2o_lightwave/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def textbox(
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
spellcheck: Optional[bool] = None,
keyboard: Optional[str] = None,
type: Optional[str] = None,
) -> Component:
"""Create a text box.
Expand Down Expand Up @@ -427,7 +427,7 @@ def textbox(
visible: True if the component should be visible. Defaults to True.
tooltip: An optional tooltip message displayed when a user clicks the help icon to the right of the component.
spellcheck: True if the text may be checked for spelling errors. Defaults to True.
keyboard: Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxKeyboard.
type: Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxType.
Returns:
A `h2o_wave.types.Textbox` instance.
"""
Expand All @@ -452,7 +452,7 @@ def textbox(
visible,
tooltip,
spellcheck,
keyboard,
type,
))


Expand Down
24 changes: 12 additions & 12 deletions py/h2o_wave/h2o_wave/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -969,10 +969,10 @@ def load(__d: Dict) -> 'MessageBar':
)


_TextboxKeyboard = ['text', 'number', 'tel']
_TextboxType = ['text', 'number', 'tel']


class TextboxKeyboard:
class TextboxType:
TEXT = 'text'
NUMBER = 'number'
TEL = 'tel'
Expand Down Expand Up @@ -1007,7 +1007,7 @@ def __init__(
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
spellcheck: Optional[bool] = None,
keyboard: Optional[str] = None,
type: Optional[str] = None,
):
_guard_scalar('Textbox.name', name, (str,), True, False, False)
_guard_scalar('Textbox.label', label, (str,), False, True, False)
Expand All @@ -1029,7 +1029,7 @@ def __init__(
_guard_scalar('Textbox.visible', visible, (bool,), False, True, False)
_guard_scalar('Textbox.tooltip', tooltip, (str,), False, True, False)
_guard_scalar('Textbox.spellcheck', spellcheck, (bool,), False, True, False)
_guard_enum('Textbox.keyboard', keyboard, _TextboxKeyboard, True)
_guard_enum('Textbox.type', type, _TextboxType, True)
self.name = name
"""An identifying name for this component."""
self.label = label
Expand Down Expand Up @@ -1070,8 +1070,8 @@ def __init__(
"""An optional tooltip message displayed when a user clicks the help icon to the right of the component."""
self.spellcheck = spellcheck
"""True if the text may be checked for spelling errors. Defaults to True."""
self.keyboard = keyboard
"""Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxKeyboard."""
self.type = type
"""Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxType."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
Expand All @@ -1095,7 +1095,7 @@ def dump(self) -> Dict:
_guard_scalar('Textbox.visible', self.visible, (bool,), False, True, False)
_guard_scalar('Textbox.tooltip', self.tooltip, (str,), False, True, False)
_guard_scalar('Textbox.spellcheck', self.spellcheck, (bool,), False, True, False)
_guard_enum('Textbox.keyboard', self.keyboard, _TextboxKeyboard, True)
_guard_enum('Textbox.type', self.type, _TextboxType, True)
return _dump(
name=self.name,
label=self.label,
Expand All @@ -1117,7 +1117,7 @@ def dump(self) -> Dict:
visible=self.visible,
tooltip=self.tooltip,
spellcheck=self.spellcheck,
keyboard=self.keyboard,
type=self.type,
)

@staticmethod
Expand Down Expand Up @@ -1163,8 +1163,8 @@ def load(__d: Dict) -> 'Textbox':
_guard_scalar('Textbox.tooltip', __d_tooltip, (str,), False, True, False)
__d_spellcheck: Any = __d.get('spellcheck')
_guard_scalar('Textbox.spellcheck', __d_spellcheck, (bool,), False, True, False)
__d_keyboard: Any = __d.get('keyboard')
_guard_enum('Textbox.keyboard', __d_keyboard, _TextboxKeyboard, True)
__d_type: Any = __d.get('type')
_guard_enum('Textbox.type', __d_type, _TextboxType, True)
name: str = __d_name
label: Optional[str] = __d_label
placeholder: Optional[str] = __d_placeholder
Expand All @@ -1185,7 +1185,7 @@ def load(__d: Dict) -> 'Textbox':
visible: Optional[bool] = __d_visible
tooltip: Optional[str] = __d_tooltip
spellcheck: Optional[bool] = __d_spellcheck
keyboard: Optional[str] = __d_keyboard
type: Optional[str] = __d_type
return Textbox(
name,
label,
Expand All @@ -1207,7 +1207,7 @@ def load(__d: Dict) -> 'Textbox':
visible,
tooltip,
spellcheck,
keyboard,
type,
)


Expand Down
6 changes: 3 additions & 3 deletions py/h2o_wave/h2o_wave/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def textbox(
visible: Optional[bool] = None,
tooltip: Optional[str] = None,
spellcheck: Optional[bool] = None,
keyboard: Optional[str] = None,
type: Optional[str] = None,
) -> Component:
"""Create a text box.
Expand Down Expand Up @@ -427,7 +427,7 @@ def textbox(
visible: True if the component should be visible. Defaults to True.
tooltip: An optional tooltip message displayed when a user clicks the help icon to the right of the component.
spellcheck: True if the text may be checked for spelling errors. Defaults to True.
keyboard: Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxKeyboard.
type: Keyboard to be shown on mobile devices. Defaults to 'text'. One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxType.
Returns:
A `h2o_wave.types.Textbox` instance.
"""
Expand All @@ -452,7 +452,7 @@ def textbox(
visible,
tooltip,
spellcheck,
keyboard,
type,
))


Expand Down
10 changes: 5 additions & 5 deletions r/R/ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,8 @@ ui_message_bar <- function(
#' @param visible True if the component should be visible. Defaults to True.
#' @param tooltip An optional tooltip message displayed when a user clicks the help icon to the right of the component.
#' @param spellcheck True if the text may be checked for spelling errors. Defaults to True.
#' @param keyboard Keyboard to be shown on mobile devices. Defaults to 'text'.
#' One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxKeyboard.
#' @param type Keyboard to be shown on mobile devices. Defaults to 'text'.
#' One of 'text', 'number', 'tel'. See enum h2o_wave.ui.TextboxType.
#' @return A Textbox instance.
#' @export
ui_textbox <- function(
Expand All @@ -510,7 +510,7 @@ ui_textbox <- function(
visible = NULL,
tooltip = NULL,
spellcheck = NULL,
keyboard = NULL) {
type = NULL) {
.guard_scalar("name", "character", name)
.guard_scalar("label", "character", label)
.guard_scalar("placeholder", "character", placeholder)
Expand All @@ -531,7 +531,7 @@ ui_textbox <- function(
.guard_scalar("visible", "logical", visible)
.guard_scalar("tooltip", "character", tooltip)
.guard_scalar("spellcheck", "logical", spellcheck)
# TODO Validate keyboard
# TODO Validate type
.o <- list(textbox=list(
name=name,
label=label,
Expand All @@ -553,7 +553,7 @@ ui_textbox <- function(
visible=visible,
tooltip=tooltip,
spellcheck=spellcheck,
keyboard=keyboard))
type=type))
class(.o) <- append(class(.o), c(.wave_obj, "WaveComponent"))
return(.o)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2620,7 +2620,7 @@
<option name="Python" value="true"/>
</context>
</template>
<template name="w_full_textbox" value="ui.textbox(name='$name$',label='$label$',placeholder='$placeholder$',value='$value$',mask='$mask$',icon='$icon$',prefix='$prefix$',suffix='$suffix$',error='$error$',required=$required$,disabled=$disabled$,readonly=$readonly$,multiline=$multiline$,password=$password$,trigger=$trigger$,height='$height$',width='$width$',visible=$visible$,tooltip='$tooltip$',spellcheck=$spellcheck$,keyboard='$keyboard$'),$END$" description="Create Wave Textbox with full attributes." toReformat="true" toShortenFQNames="true">
<template name="w_full_textbox" value="ui.textbox(name='$name$',label='$label$',placeholder='$placeholder$',value='$value$',mask='$mask$',icon='$icon$',prefix='$prefix$',suffix='$suffix$',error='$error$',required=$required$,disabled=$disabled$,readonly=$readonly$,multiline=$multiline$,password=$password$,trigger=$trigger$,height='$height$',width='$width$',visible=$visible$,tooltip='$tooltip$',spellcheck=$spellcheck$,type='$type$'),$END$" description="Create Wave Textbox with full attributes." toReformat="true" toShortenFQNames="true">
<variable name="name" expression="" defaultValue="" alwaysStopAt="true"/>
<variable name="label" expression="" defaultValue="" alwaysStopAt="true"/>
<variable name="placeholder" expression="" defaultValue="" alwaysStopAt="true"/>
Expand All @@ -2641,7 +2641,7 @@
<variable name="visible" expression="" defaultValue="&quot;True&quot;" alwaysStopAt="true"/>
<variable name="tooltip" expression="" defaultValue="" alwaysStopAt="true"/>
<variable name="spellcheck" expression="" defaultValue="&quot;True&quot;" alwaysStopAt="true"/>
<variable name="keyboard" expression="" defaultValue="&quot;text&quot;" alwaysStopAt="true"/>
<variable name="type" expression="" defaultValue="&quot;text&quot;" alwaysStopAt="true"/>
<context>
<option name="Python" value="true"/>
</context>
Expand Down
2 changes: 1 addition & 1 deletion tools/vscode-extension/component-snippets.json
Original file line number Diff line number Diff line change
Expand Up @@ -1906,7 +1906,7 @@
"Wave Full Textbox": {
"prefix": "w_full_textbox",
"body": [
"ui.textbox(name='$1', label='$2', placeholder='$3', value='$4', mask='$5', icon='$6', prefix='$7', suffix='$8', error='$9', required=${10:False}, disabled=${11:False}, readonly=${12:False}, multiline=${13:False}, password=${14:False}, trigger=${15:False}, height='$16', width='${17:100%}', visible=${18:True}, tooltip='$19', spellcheck=${20:True}, keyboard='${21:text}'),$0"
"ui.textbox(name='$1', label='$2', placeholder='$3', value='$4', mask='$5', icon='$6', prefix='$7', suffix='$8', error='$9', required=${10:False}, disabled=${11:False}, readonly=${12:False}, multiline=${13:False}, password=${14:False}, trigger=${15:False}, height='$16', width='${17:100%}', visible=${18:True}, tooltip='$19', spellcheck=${20:True}, type='${21:text}'),$0"
],
"description": "Create a full Wave Textbox."
},
Expand Down
28 changes: 11 additions & 17 deletions ui/src/textbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ import { B, Id, S } from './core'
import React from 'react'
import { debounce, wave } from './ui'

const hideFieldArrowsStyle = {
'&::-webkit-outer-spin-button, &::-webkit-inner-spin-button': {
'-webkit-appearance': 'none',
margin: 0,
},
'-moz-appearance': 'textfield',
}

/**
* Create a text box.
Expand Down Expand Up @@ -74,7 +67,7 @@ export interface Textbox {
/** True if the text may be checked for spelling errors. Defaults to True. */
spellcheck?: B
/** Keyboard to be shown on mobile devices. Defaults to 'text'. */
keyboard?: 'text' | 'number' | 'tel'
type?: 'text' | 'number' | 'tel'
}

const DEBOUNCE_TIMEOUT = 500
Expand All @@ -91,11 +84,6 @@ export const
setValue(v)
m.value = v
},
customHeight = !m.mask && m.multiline && m.height && !m.height.endsWith('%') ? m.height : undefined,
styles = {
field: { height: customHeight, ...(m.keyboard === 'number' ? hideFieldArrowsStyle : {}) },
fieldGroup: { minHeight: customHeight },
},
textFieldProps: Fluent.ITextFieldProps & { 'data-test': S } = {
'data-test': m.name,
label: m.label,
Expand All @@ -112,9 +100,6 @@ export const
multiline: m.multiline,
spellCheck: m.spellcheck,
type: m.password ? 'password' : (m.keyboard || 'text'),
styles,
onWheel: m.keyboard === 'number' ? e => e.currentTarget.blur() : undefined, // Disable setting number with scroll.
onKeyDown: m.keyboard === 'number' ? e => e.preventDefault() : undefined, // Disable setting number with keyboard arrows.
}

React.useEffect(() => {
Expand All @@ -124,5 +109,14 @@ export const

return m.mask
? <Fluent.MaskedTextField mask={m.mask} {...textFieldProps} />
: <Fluent.TextField {...textFieldProps} />
: (
<Fluent.TextField
styles={
m.multiline && m.height && !m.height.endsWith('%')
? { field: { height: m.height }, fieldGroup: { minHeight: m.height } }
: undefined
}
{...textFieldProps}
/>
)
}
4 changes: 2 additions & 2 deletions website/widgets/form/textbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,13 @@ q.page['example'] = ui.form_card(
name='textbox_keyboard_numeric',
label='With numeric keyboard (iOS, Android)',
# Show numeric keyboard
keyboard='number'
type='number'
),
ui.textbox(
name='textbox_keyboard_telephone',
label='With numeric keyboard (iOS, Android)',
# Show telephone keyboard
keyboard='tel'
type='tel'
)
]
)
Expand Down

0 comments on commit 1f4b452

Please sign in to comment.