diff --git a/plugins/ui/docs/components/labeled_value.md b/plugins/ui/docs/components/labeled_value.md new file mode 100644 index 000000000..8a057c746 --- /dev/null +++ b/plugins/ui/docs/components/labeled_value.md @@ -0,0 +1,108 @@ +# Labeled Value + +A labeled value displays a non-editable value with a label. + +## Example + +```python +from deephaven import ui + + +my_labeled_value_basic = ui.labeled_value(label="File name", value="Budget.xls") +``` + + +## Value + +A labeled value accepts numbers, strings, and lists of strings in the `value` prop. + +```python +from deephaven import ui + + +@ui.component +def ui_labeled_value_examples(): + return [ + ui.labeled_value(label="File name", value="Budget.xls"), + ui.labeled_value(label="Number of expenses in Budget file", value=123), + ui.labeled_value( + label="Pizza toppings", value=["Pizza", "Pineapple", "Mushroom", "Garlic"] + ), + ] + + +my_labeled_value_values_examples = ui_labeled_value_examples() +``` + +## Numbers + +When passing a number into a labeled value, the `format_options` prop dictates how the value is displayed. There are 3 styles supported by this parameter: Percentage, Currency, and Units. + +Note that this prop is compatible with the option parameter of [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat). + +```python +from deephaven import ui + + +@ui.component +def ui_labeled_value_numbers_example(): + return [ + ui.labeled_value( + label="Percent completed", + value=0.89, + format_options={"style": "percent"}, + ), + ui.labeled_value( + label="Withdrawal amount", + value=2350.50, + format_options={"style": "currency", "currency": "USD"}, + ), + ui.labeled_value( + label="Height of Burj Khalifa", + value=32600, + format_options={"style": "unit", "unit": "inch"}, + ), + ] + + +my_labeled_value_numbers_example = ui_labeled_value_numbers_example() +``` + + +## Label position + +By default, the label is positioned above the labeled value, but it can be changed to the side using the `label_position` prop. + +```python +from deephaven import ui + + +my_labeled_value_label_position_example = ui.labeled_value( + label="File name", value="Onboarding.pdf", label_position="side", label_align="end" +) +``` + + +## Contextual Help + +Using the `contextual_help` prop, a `ui.contextual_help` can be placed next to the labeled value to provide additional information. + +```python +from deephaven import ui + + +my_labeled_value_contextual_help_example = ui.labeled_value( + label="File name", + value="Onboarding.pdf", + contextual_help=ui.contextual_help( + heading="Info about the onboarding document", content="Sample content" + ), +) +``` + + +## API reference + +```{eval-rst} +.. dhautofunction:: deephaven.ui.labeled_value +``` \ No newline at end of file diff --git a/plugins/ui/docs/sidebar.json b/plugins/ui/docs/sidebar.json index 22d631c6d..5a5f7aec9 100644 --- a/plugins/ui/docs/sidebar.json +++ b/plugins/ui/docs/sidebar.json @@ -138,6 +138,10 @@ "label": "inline_alert", "path": "components/inline_alert.md" }, + { + "label": "labeled_value", + "path": "components/labeled_value.md" + }, { "label": "link", "path": "components/link.md" diff --git a/plugins/ui/src/deephaven/ui/components/__init__.py b/plugins/ui/src/deephaven/ui/components/__init__.py index c54e95e4a..da854c99c 100644 --- a/plugins/ui/src/deephaven/ui/components/__init__.py +++ b/plugins/ui/src/deephaven/ui/components/__init__.py @@ -32,6 +32,7 @@ from .inline_alert import inline_alert from .item import item from .item_table_source import item_table_source +from .labeled_value import labeled_value from .link import link from .list_action_group import list_action_group from .list_action_menu import list_action_menu @@ -102,6 +103,7 @@ "item_table_source", "illustrated_message", "image", + "labeled_value", "inline_alert", "link", "list_view", diff --git a/plugins/ui/src/deephaven/ui/components/checkbox_group.py b/plugins/ui/src/deephaven/ui/components/checkbox_group.py index 073328090..7996f14e4 100644 --- a/plugins/ui/src/deephaven/ui/components/checkbox_group.py +++ b/plugins/ui/src/deephaven/ui/components/checkbox_group.py @@ -4,6 +4,7 @@ from .types import ( Orientation, + Alignment, AlignSelf, CSSProperties, DimensionValue, @@ -12,6 +13,7 @@ Position, ValidationBehavior, FocusEventCallable, + LabelPosition, ) from .basic import component_element from ..elements import Element @@ -33,8 +35,8 @@ def checkbox_group( is_required: bool | None = None, is_invalid: bool | None = None, validation_behavior: ValidationBehavior | None = "aria", - label_position: str | None = None, - label_align: str | None = None, + label_position: LabelPosition | None = None, + label_align: Alignment | None = None, necessity_indicator: str | None = None, contextual_help: Any | None = None, show_error_icon: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/labeled_value.py b/plugins/ui/src/deephaven/ui/components/labeled_value.py new file mode 100644 index 000000000..633192a20 --- /dev/null +++ b/plugins/ui/src/deephaven/ui/components/labeled_value.py @@ -0,0 +1,166 @@ +from __future__ import annotations +from typing import Any, List + +from .number_field import NumberFieldFormatOptions +from .types import ( + Alignment, + AlignSelf, + CSSProperties, + DimensionValue, + JustifySelf, + LayoutFlex, + Position, + LabelPosition, +) +from .basic import component_element +from ..elements import Element + + +def labeled_value( + value: str | List[str] | int | None = None, + label: Element | None = None, + format_options: NumberFieldFormatOptions | None = None, + label_position: LabelPosition | None = "top", + label_align: Alignment | None = None, + contextual_help: Any | None = None, + flex: LayoutFlex | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, + flex_basis: DimensionValue | None = None, + align_self: AlignSelf | None = None, + justify_self: JustifySelf | None = None, + order: int | None = None, + grid_area: str | None = None, + grid_row: str | None = None, + grid_row_start: str | None = None, + grid_row_end: str | None = None, + grid_column: str | None = None, + grid_column_start: str | None = None, + grid_column_end: str | None = None, + margin: DimensionValue | None = None, + margin_top: DimensionValue | None = None, + margin_bottom: DimensionValue | None = None, + margin_start: DimensionValue | None = None, + margin_end: DimensionValue | None = None, + margin_x: DimensionValue | None = None, + margin_y: DimensionValue | None = None, + width: DimensionValue | None = None, + height: DimensionValue | None = None, + min_width: DimensionValue | None = None, + min_height: DimensionValue | None = None, + max_width: DimensionValue | None = None, + max_height: DimensionValue | None = None, + position: Position | None = None, + top: DimensionValue | None = None, + bottom: DimensionValue | None = None, + start: DimensionValue | None = None, + end: DimensionValue | None = None, + left: DimensionValue | None = None, + right: DimensionValue | None = None, + z_index: int | None = None, + is_hidden: bool | None = None, + id: str | None = None, + UNSAFE_class_name: str | None = None, + UNSAFE_style: CSSProperties | None = None, +) -> Element: + """ + Labeled values displays non-editable values with a corresponding label + + Args: + value: The value to be displayed. + label: The content of the label. + format_options: Formatting options for the value displayed in the number field. + label_position: The label's overall position relative to the element it is labeling. + label_align: The label's horizontal alignment relative to the element it is labeling. + contextual_help: A contextual help element to place next to the label. + flex: When used in a flex layout, specifies how the element will grow or shrink to fit the space available. + flex_grow: When used in a flex layout, specifies how the element will grow to fit the space available. + flex_shrink: When used in a flex layout, specifies how the element will shrink to fit the space available. + flex_basis: When used in a flex layout, specifies the initial main size of the element. + align_self: Overrides the alignItems property of a flex or grid container. + justify_self: Species how the element is justified inside a flex or grid container. + order: The layout order for the element within a flex or grid container. + grid_area: When used in a grid layout specifies, specifies the named grid area that the element should be placed in within the grid. + grid_row: When used in a grid layout, specifies the row the element should be placed in within the grid. + grid_column: When used in a grid layout, specifies the column the element should be placed in within the grid. + grid_row_start: When used in a grid layout, specifies the starting row to span within the grid. + grid_row_end: When used in a grid layout, specifies the ending row to span within the grid. + grid_column_start: When used in a grid layout, specifies the starting column to span within the grid. + grid_column_end: When used in a grid layout, specifies the ending column to span within the grid. + margin: The margin for all four sides of the element. + margin_top: The margin for the top side of the element. + margin_bottom: The margin for the bottom side of the element. + margin_start: The margin for the logical start side of the element, depending on layout direction. + margin_end: The margin for the logical end side of the element, depending on layout direction. + margin_x: The margin for the left and right sides of the element. + margin_y: The margin for the top and bottom sides of the element. + width: The width of the element. + min_width: The minimum width of the element. + max_width: The maximum width of the element. + height: The height of the element. + min_height: The minimum height of the element. + max_height: The maximum height of the element. + position: The position of the element. + top: The distance from the top of the containing element. + bottom: The distance from the bottom of the containing element. + left: The distance from the left of the containing element. + right: The distance from the right of the containing element. + start: The distance from the start of the containing element, depending on layout direction. + end: The distance from the end of the containing element, depending on layout direction. + z_index: The stack order of the element. + is_hidden: Whether the element is hidden. + id: The unique identifier of the element. + UNSAFE_class_name: A CSS class to apply to the element. + UNSAFE_style: A CSS style to apply to the element. + + Returns: + The rendered labeled value element. + """ + return component_element( + "LabeledValue", + value=value, + label=label, + format_options=format_options, + label_position=label_position, + label_align=label_align, + contextual_help=contextual_help, + flex=flex, + flex_grow=flex_grow, + flex_shrink=flex_shrink, + flex_basis=flex_basis, + align_self=align_self, + justify_self=justify_self, + order=order, + grid_area=grid_area, + grid_row=grid_row, + grid_row_start=grid_row_start, + grid_row_end=grid_row_end, + grid_column=grid_column, + grid_column_start=grid_column_start, + grid_column_end=grid_column_end, + margin=margin, + margin_top=margin_top, + margin_bottom=margin_bottom, + margin_start=margin_start, + margin_end=margin_end, + margin_x=margin_x, + margin_y=margin_y, + width=width, + height=height, + min_width=min_width, + min_height=min_height, + max_width=max_width, + max_height=max_height, + position=position, + top=top, + bottom=bottom, + start=start, + end=end, + left=left, + right=right, + z_index=z_index, + is_hidden=is_hidden, + id=id, + UNSAFE_class_name=UNSAFE_class_name, + UNSAFE_style=UNSAFE_style, + ) diff --git a/plugins/ui/src/js/src/elements/LabeledValue.tsx b/plugins/ui/src/js/src/elements/LabeledValue.tsx new file mode 100644 index 000000000..d6a7cec91 --- /dev/null +++ b/plugins/ui/src/js/src/elements/LabeledValue.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { + LabeledValue as DHCLabeledValue, + LabeledValueProps as DHCLabeledValueProps, +} from '@deephaven/components'; + +export function LabeledValue( + props: DHCLabeledValueProps +): JSX.Element { + return ( + // eslint-disable-next-line react/jsx-props-no-spreading + + ); +} +LabeledValue.displayName = 'LabeledValue'; +export default LabeledValue; diff --git a/plugins/ui/src/js/src/elements/index.ts b/plugins/ui/src/js/src/elements/index.ts index 58c8846f7..3b00b57bb 100644 --- a/plugins/ui/src/js/src/elements/index.ts +++ b/plugins/ui/src/js/src/elements/index.ts @@ -17,6 +17,7 @@ export * from './HTMLElementView'; export * from './IconElementView'; export * from './IllustratedMessage'; export * from './Image'; +export * from './LabeledValue'; export * from './InlineAlert'; export * from './ListView'; export * from './Markdown'; diff --git a/plugins/ui/src/js/src/elements/model/ElementConstants.ts b/plugins/ui/src/js/src/elements/model/ElementConstants.ts index 83d386a79..430051f9c 100644 --- a/plugins/ui/src/js/src/elements/model/ElementConstants.ts +++ b/plugins/ui/src/js/src/elements/model/ElementConstants.ts @@ -50,6 +50,7 @@ export const ELEMENT_NAME = { image: uiComponentName('Image'), inlineAlert: uiComponentName('InlineAlert'), item: uiComponentName('Item'), + labeledValue: uiComponentName('LabeledValue'), listActionGroup: uiComponentName('ListActionGroup'), listActionMenu: uiComponentName('ListActionMenu'), link: uiComponentName('Link'), diff --git a/plugins/ui/src/js/src/widget/WidgetUtils.tsx b/plugins/ui/src/js/src/widget/WidgetUtils.tsx index a3fc677bf..6489bc194 100644 --- a/plugins/ui/src/js/src/widget/WidgetUtils.tsx +++ b/plugins/ui/src/js/src/widget/WidgetUtils.tsx @@ -64,6 +64,7 @@ import { Grid, IllustratedMessage, Image, + LabeledValue, InlineAlert, ListView, Markdown, @@ -142,6 +143,7 @@ export const elementComponentMap = { [ELEMENT_NAME.image]: Image, [ELEMENT_NAME.inlineAlert]: InlineAlert, [ELEMENT_NAME.item]: Item, + [ELEMENT_NAME.labeledValue]: LabeledValue, [ELEMENT_NAME.link]: Link, [ELEMENT_NAME.listActionGroup]: ListActionGroup, [ELEMENT_NAME.listActionMenu]: ListActionMenu, diff --git a/tests/app.d/ui_render_all.py b/tests/app.d/ui_render_all.py index 3b96ae6e4..19d03b519 100644 --- a/tests/app.d/ui_render_all.py +++ b/tests/app.d/ui_render_all.py @@ -87,6 +87,7 @@ def ui_components2(): ), variant="positive", ), + ui.labeled_value(label="File name", value="Budget.xls"), ui.link("Learn more about Deephaven", href="https://deephaven.io/"), ui.list_view( _item_table_source_with_action_group, diff --git a/tests/express.spec.ts-snapshots/Histogram-loads-1-webkit-linux.png b/tests/express.spec.ts-snapshots/Histogram-loads-1-webkit-linux.png index fbc109b04..42b79ecec 100644 Binary files a/tests/express.spec.ts-snapshots/Histogram-loads-1-webkit-linux.png and b/tests/express.spec.ts-snapshots/Histogram-loads-1-webkit-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-1-chromium-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-1-chromium-linux.png index 7150458c7..de6c09e29 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-1-chromium-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-1-chromium-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-chromium-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-chromium-linux.png index 5e821a5bd..7ef9401bb 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-chromium-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-chromium-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-firefox-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-firefox-linux.png index 083699b0a..f8e91d73c 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-firefox-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-firefox-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-webkit-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-webkit-linux.png index a46551b34..1b3f8835e 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-webkit-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-2-1-webkit-linux.png differ