Skip to content

Commit c5b47a8

Browse files
feat: give more control over the underlying vuetify text input
Added (and forwarded) these arguments to the underlying vuetify text input: dense: bool = False, hide_details: Union[str, bool] = "auto", placeholder: Optional[str] = None, prefix: Optional[str] = None, suffix: Optional[str] = None, clearable: bool = False,
1 parent 6aacbff commit c5b47a8

File tree

3 files changed

+148
-18
lines changed

3 files changed

+148
-18
lines changed

solara/components/input.py

Lines changed: 96 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def cleanup():
4040
def InputText(
4141
label: str,
4242
value: Union[str, solara.Reactive[str]] = "",
43-
on_value: Callable[[str], None] = None,
43+
on_value: Optional[Callable[[str], None]] = None,
4444
disabled: bool = False,
4545
password: bool = False,
4646
continuous_update: bool = False,
@@ -50,6 +50,12 @@ def InputText(
5050
classes: List[str] = [],
5151
style: Optional[Union[str, Dict[str, str]]] = None,
5252
autofocus: bool = False,
53+
dense: bool = False,
54+
hide_details: Union[str, bool] = "auto",
55+
placeholder: Optional[str] = None,
56+
prefix: Optional[str] = None,
57+
suffix: Optional[str] = None,
58+
clearable: bool = False,
5359
):
5460
"""Free form text input.
5561
@@ -107,6 +113,12 @@ def Page():
107113
* `classes`: List of CSS classes to apply to the input.
108114
* `style`: CSS style to apply to the input.
109115
* `autofocus`: Determines if a component is to be autofocused or not (Default is False). Autofocus will occur during page load and only one component per page can have autofocus active.
116+
* `dense`: Reduces the input height.
117+
* `hide_details`: Hides hint and validation errors. When set to 'auto', messages will be rendered only if there's a message (hint, error message, etc) to display.
118+
* `placeholder`: Sets the input's placeholder text.
119+
* `prefix`: Displays prefix text.
120+
* `suffix`: Displays suffix text.
121+
* `clearable`: Whether the input can be cleared.
110122
"""
111123
reactive_value = solara.use_reactive(value, on_value)
112124
del value, on_value
@@ -130,12 +142,18 @@ def on_v_model(value):
130142
on_v_model=on_v_model,
131143
label=label,
132144
disabled=disabled,
133-
type="password" if password else None,
145+
type="password" if password else "text",
134146
error=bool(error),
135147
messages=messages,
136148
class_=classes_flat,
137149
style_=style_flat,
138150
autofocus=autofocus,
151+
dense=dense,
152+
hide_details=hide_details,
153+
placeholder=placeholder if placeholder is not None else "",
154+
prefix=prefix if prefix is not None else "",
155+
suffix=suffix if suffix is not None else "",
156+
clearable=clearable,
139157
)
140158
use_change(text_field, set_value_cast, enabled=not continuous_update, update_events=update_events)
141159
return text_field
@@ -154,6 +172,11 @@ def InputFloat(
154172
classes: List[str] = ...,
155173
style: Optional[Union[str, Dict[str, str]]] = ...,
156174
autofocus: bool = False,
175+
dense: bool = False,
176+
hide_details: Union[str, bool] = "auto",
177+
placeholder: Optional[str] = None,
178+
prefix: Optional[str] = None,
179+
suffix: Optional[str] = None,
157180
) -> reacton.core.ValueElement[vw.TextField, Any]: ...
158181

159182

@@ -170,6 +193,11 @@ def InputFloat(
170193
classes: List[str] = ...,
171194
style: Optional[Union[str, Dict[str, str]]] = ...,
172195
autofocus: bool = False,
196+
dense: bool = False,
197+
hide_details: Union[str, bool] = "auto",
198+
placeholder: Optional[str] = None,
199+
prefix: Optional[str] = None,
200+
suffix: Optional[str] = None,
173201
) -> reacton.core.ValueElement[vw.TextField, Any]: ...
174202

175203

@@ -185,6 +213,11 @@ def InputFloat(
185213
classes: List[str] = [],
186214
style: Optional[Union[str, Dict[str, str]]] = None,
187215
autofocus: bool = False,
216+
dense: bool = False,
217+
hide_details: Union[str, bool] = "auto",
218+
placeholder: Optional[str] = None,
219+
prefix: Optional[str] = None,
220+
suffix: Optional[str] = None,
188221
):
189222
"""Numeric input (floats).
190223
@@ -218,6 +251,11 @@ def Page():
218251
* `classes`: List of CSS classes to apply to the input.
219252
* `style`: CSS style to apply to the input.
220253
* `autofocus`: Determines if a component is to be autofocused or not (Default is False). Autofocus will occur either during page load, or when the component becomes visible (for example, dialog being opened). Only one component per page should have autofocus on each such event.
254+
* `dense`: Reduces the input height.
255+
* `hide_details`: Hides hint and validation errors. When set to 'auto', messages will be rendered only if there's a message (hint, error message, etc) to display.
256+
* `placeholder`: Sets the input's placeholder text.
257+
* `prefix`: Displays prefix text.
258+
* `suffix`: Displays suffix text.
221259
222260
"""
223261

@@ -237,15 +275,20 @@ def str_to_float(value: Optional[str]):
237275
return _InputNumeric(
238276
str_to_float,
239277
label=label,
240-
value=value,
241-
on_value=on_value,
278+
value=value, # type: ignore
279+
on_value=on_value, # type: ignore
242280
disabled=disabled,
243281
continuous_update=continuous_update,
244282
clearable=clearable,
245283
classes=classes,
246284
style=style,
247285
autofocus=autofocus,
248-
)
286+
dense=dense,
287+
hide_details=hide_details,
288+
placeholder=placeholder,
289+
prefix=prefix,
290+
suffix=suffix,
291+
) # type: ignore
249292

250293

251294
@overload
@@ -261,6 +304,11 @@ def InputInt(
261304
classes: List[str] = ...,
262305
style: Optional[Union[str, Dict[str, str]]] = ...,
263306
autofocus: bool = False,
307+
dense: bool = False,
308+
hide_details: Union[str, bool] = "auto",
309+
placeholder: Optional[str] = None,
310+
prefix: Optional[str] = None,
311+
suffix: Optional[str] = None,
264312
) -> reacton.core.ValueElement[vw.TextField, Any]: ...
265313

266314

@@ -277,6 +325,11 @@ def InputInt(
277325
classes: List[str] = ...,
278326
style: Optional[Union[str, Dict[str, str]]] = ...,
279327
autofocus: bool = False,
328+
dense: bool = False,
329+
hide_details: Union[str, bool] = "auto",
330+
placeholder: Optional[str] = None,
331+
prefix: Optional[str] = None,
332+
suffix: Optional[str] = None,
280333
) -> reacton.core.ValueElement[vw.TextField, Any]: ...
281334

282335

@@ -292,6 +345,11 @@ def InputInt(
292345
classes: List[str] = [],
293346
style: Optional[Union[str, Dict[str, str]]] = None,
294347
autofocus: bool = False,
348+
dense: bool = False,
349+
hide_details: Union[str, bool] = "auto",
350+
placeholder: Optional[str] = None,
351+
prefix: Optional[str] = None,
352+
suffix: Optional[str] = None,
295353
):
296354
"""Numeric input (integers).
297355
@@ -324,6 +382,11 @@ def Page():
324382
* `classes`: List of CSS classes to apply to the input.
325383
* `style`: CSS style to apply to the input.
326384
* `autofocus`: Determines if a component is to be autofocused or not (Default is False). Autofocus will occur either during page load, or when the component becomes visible (for example, dialog being opened). Only one component per page should have autofocus on each such event.
385+
* `dense`: Reduces the input height.
386+
* `hide_details`: Hides hint and validation errors. When set to 'auto', messages will be rendered only if there's a message (hint, error message, etc) to display.
387+
* `placeholder`: Sets the input's placeholder text.
388+
* `prefix`: Displays prefix text.
389+
* `suffix`: Displays suffix text.
327390
"""
328391

329392
def str_to_int(value: Optional[str]):
@@ -341,15 +404,20 @@ def str_to_int(value: Optional[str]):
341404
return _InputNumeric(
342405
str_to_int,
343406
label=label,
344-
value=value,
345-
on_value=on_value,
407+
value=value, # type: ignore
408+
on_value=on_value, # type: ignore
346409
disabled=disabled,
347410
continuous_update=continuous_update,
348411
clearable=clearable,
349412
classes=classes,
350413
style=style,
351414
autofocus=autofocus,
352-
)
415+
dense=dense,
416+
hide_details=hide_details,
417+
placeholder=placeholder,
418+
prefix=prefix,
419+
suffix=suffix,
420+
) # type: ignore
353421

354422

355423
def _use_input_type(
@@ -360,22 +428,22 @@ def _use_input_type(
360428
):
361429
reactive_value = solara.use_reactive(input_value, on_value) # type: ignore
362430
del input_value, on_value
363-
string_value, set_string_value = solara.use_state(stringify(reactive_value.value) if reactive_value.value is not None else None)
431+
string_value, set_string_value = solara.use_state(stringify(reactive_value.value) if reactive_value.value is not None else None) # type: ignore
364432
# Use a ref to make sure sync_back_input_value() does not get a stale string_value
365433
string_value_ref = solara.use_ref(string_value)
366434
string_value_ref.current = string_value
367435

368436
error_message = cast(Union[str, None], None)
369437

370438
try:
371-
reactive_value.set(parse(string_value))
439+
reactive_value.set(parse(string_value)) # type: ignore
372440
except ValueError as e:
373441
error_message = str(e.args[0])
374442

375443
def sync_back_input_value():
376444
# Make sure we update string_value when the effect is rerun,
377445
# Since the parsing & stringigying functions might have changed
378-
set_string_value(stringify(reactive_value.value) if reactive_value.value is not None else None)
446+
set_string_value(stringify(reactive_value.value) if reactive_value.value is not None else None) # type: ignore
379447

380448
def on_external_value_change(new_value: Optional[T]):
381449
new_string_value = stringify(new_value)
@@ -388,7 +456,7 @@ def on_external_value_change(new_value: Optional[T]):
388456
if new_value != parse(string_value_ref.current):
389457
set_string_value(new_string_value)
390458

391-
return reactive_value.subscribe(on_external_value_change)
459+
return reactive_value.subscribe(on_external_value_change) # type: ignore
392460

393461
solara.use_effect(sync_back_input_value, [reactive_value, parse, stringify])
394462

@@ -407,6 +475,11 @@ def _InputNumeric(
407475
classes: List[str] = [],
408476
style: Optional[Union[str, Dict[str, str]]] = None,
409477
autofocus: bool = False,
478+
dense: bool = False,
479+
hide_details: Union[str, bool] = "auto",
480+
placeholder: Optional[str] = None,
481+
prefix: Optional[str] = None,
482+
suffix: Optional[str] = None,
410483
):
411484
"""Numeric input.
412485
@@ -420,6 +493,12 @@ def _InputNumeric(
420493
* `classes`: List of CSS classes to apply to the input.
421494
* `style`: CSS style to apply to the input.
422495
* `autofocus`: Determines if a component is to be autofocused or not (Default is False). Autofocus will occur either during page load, or when the component becomes visible (for example, dialog being opened). Only one component per page should have autofocus on each such event.
496+
* `dense`: Reduces the input height.
497+
* `hide_details`: Hides hint and validation errors. When set to 'auto', messages will be rendered only if there's a message (hint, error message, etc) to display.
498+
* `placeholder`: Sets the input's placeholder text.
499+
* `prefix`: Displays prefix text.
500+
* `suffix`: Displays suffix text.
501+
* `clearable`: Whether the input can be cleared.
423502
"""
424503
style_flat = solara.util._flatten_style(style)
425504
classes_flat = solara.util._combine_classes(classes)
@@ -445,12 +524,16 @@ def on_v_model(value):
445524
# we are not using the number type, since we cannot validate invalid input
446525
# see https://stackoverflow.blog/2022/12/26/why-the-number-input-is-the-worst-input/
447526
# type="number",
448-
hide_details=True,
527+
hide_details=hide_details,
449528
clearable=clearable,
450529
error=bool(error),
451530
class_=classes_flat,
452531
style_=style_flat,
453532
autofocus=autofocus,
533+
dense=dense,
534+
placeholder=placeholder if placeholder is not None else "",
535+
prefix=prefix if prefix is not None else "",
536+
suffix=suffix if suffix is not None else "",
454537
)
455538
use_change(text_field, set_value_cast, enabled=not continuous_update)
456539
return text_field

solara/components/input_text_area.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ def InputTextArea(
1616
message: Optional[str] = None,
1717
auto_grow: bool = True,
1818
rows: int = 5,
19+
dense: bool = False,
20+
hide_details: Union[str, bool] = "auto",
21+
placeholder: Optional[str] = None,
22+
prefix: Optional[str] = None,
23+
suffix: Optional[str] = None,
1924
):
2025
r"""Free form text area input.
2126
@@ -53,6 +58,11 @@ def Page():
5358
* `message`: Message to show below the input. If `error` is a string, this will be ignored.
5459
* `classes`: List of CSS classes to apply to the input.
5560
* `style`: CSS style to apply to the input.
61+
* `dense`: Reduces the input height.
62+
* `hide_details`: Hides hint and validation errors. When set to 'auto', messages will be rendered only if there's a message (hint, error message, counter value etc) to display.
63+
* `placeholder`: Sets the input's placeholder text.
64+
* `prefix`: Displays prefix text.
65+
* `suffix`: Displays suffix text.
5666
"""
5767
reactive_value = solara.use_reactive(value, on_value)
5868
del value, on_value
@@ -77,10 +87,14 @@ def on_v_model(value):
7787
error=bool(error),
7888
messages=messages,
7989
solo=True,
80-
hide_details=True,
90+
hide_details=hide_details,
8191
outlined=True,
8292
rows=rows,
8393
auto_grow=auto_grow,
94+
dense=dense,
95+
placeholder=placeholder if placeholder is not None else "",
96+
prefix=prefix if prefix is not None else "",
97+
suffix=suffix if suffix is not None else "",
8498
)
8599
use_change(text_area, set_value_cast, enabled=not continuous_update, update_events=update_events)
86100
return text_area

0 commit comments

Comments
 (0)