From 5fe71a15894b65e9c7f145a4522de8073e111471 Mon Sep 17 00:00:00 2001 From: Akshat Jawne Date: Mon, 18 Nov 2024 23:57:01 -0500 Subject: [PATCH 1/4] complete logic --- plugins/ui/docs/components/avatar.md | 96 ++++++++++ plugins/ui/docs/sidebar.json | 4 + .../src/deephaven/ui/components/__init__.py | 2 + .../ui/src/deephaven/ui/components/avatar.py | 170 ++++++++++++++++++ plugins/ui/src/deephaven/ui/types/types.py | 10 ++ .../js/src/elements/model/ElementConstants.ts | 1 + plugins/ui/src/js/src/widget/WidgetUtils.tsx | 2 + 7 files changed, 285 insertions(+) create mode 100644 plugins/ui/docs/components/avatar.md create mode 100644 plugins/ui/src/deephaven/ui/components/avatar.py diff --git a/plugins/ui/docs/components/avatar.md b/plugins/ui/docs/components/avatar.md new file mode 100644 index 000000000..6eed31b36 --- /dev/null +++ b/plugins/ui/docs/components/avatar.md @@ -0,0 +1,96 @@ +# Avatar + +An avatar is a small image or icon representing a user or organization. + +## Example + +```python +from deephaven import ui + + +my_avatar_basic = ui.avatar(src="https://i.imgur.com/kJOwAdv.png", alt="default avatar") +``` + + +## Disabled State + +The `is_disabled` prop disables avatars to prevent user interaction, and gives it a silenced style. + +```python +from deephaven import ui + + +my_avatar_is_disabled_example = ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", alt="default avatar", is_disabled=True +) +``` + + +## Size + +The `size` of an avatar can be set to one of the preset sizes, or a custom pixel value. + +```python +from deephaven import ui + + +@ui.component +def ui_avatar_sizing_examples(): + return [ + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-50", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-75", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-100", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-200", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-300", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-400", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-500", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-600", + ), + ui.avatar( + src="https://i.imgur.com/kJOwAdv.png", + alt="default avatar", + size="avatar-size-700", + ), + ui.avatar(src="https://i.imgur.com/kJOwAdv.png", alt="default avatar", size=80), + ] + + +my_avatar_sizing_examples = ui_avatar_sizing_examples() +``` + +## API Reference + +```{eval-rst} +.. dhautofunction:: deephaven.ui.avatar +``` diff --git a/plugins/ui/docs/sidebar.json b/plugins/ui/docs/sidebar.json index b8ff32ebb..fc8cbd607 100644 --- a/plugins/ui/docs/sidebar.json +++ b/plugins/ui/docs/sidebar.json @@ -37,6 +37,10 @@ "label": "action_menu", "path": "components/action_menu.md" }, + { + "label": "avatar", + "path": "components/avatar.md" + }, { "label": "badge", "path": "components/badge.md" diff --git a/plugins/ui/src/deephaven/ui/components/__init__.py b/plugins/ui/src/deephaven/ui/components/__init__.py index 6761e71b4..623d14f3e 100644 --- a/plugins/ui/src/deephaven/ui/components/__init__.py +++ b/plugins/ui/src/deephaven/ui/components/__init__.py @@ -1,6 +1,7 @@ from .action_button import action_button from .action_group import action_group from .action_menu import action_menu +from .avatar import avatar from .basic import ( component_element, ) @@ -69,6 +70,7 @@ "action_button", "action_group", "action_menu", + "avatar", "component_element", "badge", "button", diff --git a/plugins/ui/src/deephaven/ui/components/avatar.py b/plugins/ui/src/deephaven/ui/components/avatar.py new file mode 100644 index 000000000..d5f471283 --- /dev/null +++ b/plugins/ui/src/deephaven/ui/components/avatar.py @@ -0,0 +1,170 @@ +from __future__ import annotations +from .types import ( + # Layout + AlignSelf, + CSSProperties, + DimensionValue, + JustifySelf, + LayoutFlex, + Position, +) +from ..types import AvatarSize +from .basic import component_element +from ..elements import Element + + +def avatar( + src: str, + is_disabled: bool | None = None, + size: AvatarSize | DimensionValue | None = "avatar-size-100", + alt: str | 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_column: str | None = None, + grid_row_start: str | None = None, + grid_row_end: 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, + left: DimensionValue | None = None, + right: DimensionValue | None = None, + start: DimensionValue | None = None, + end: DimensionValue | None = None, + z_index: int | None = None, + is_hidden: bool | None = None, + id: str | None = None, + aria_label: str | None = None, + aria_labelledby: str | None = None, + aria_describedby: str | None = None, + aria_details: str | None = None, + UNSAFE_class_name: str | None = None, + UNSAFE_style: CSSProperties | None = None, +) -> Element: + """ + An avatar is a thumbnail representation of an entity, such as a user or an organization. + + Args: + src: The image URL for the avatar. + is_disabled: Whether the avatar is disabled or not. + size: The size of the avatar. It affects both height and width. + alt: Description of the avatar. + 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. + height: The height of the element. + min_width: The minimum width of the element. + min_height: The minimum height of the element. + max_width: The maximum width of the element. + max_height: The maximum height of the element. + position: Specifies how the element is position. + top: The top position of the element. + bottom: The bottom position of the element. + left: The left position of the element. + right: The right position of the element. + start: The logical start position of the element, depending on layout direction. + end: The logical end position of the element, depending on layout direction. + z_index: The stacking order for the element + is_hidden: Hides the element. + id: The unique identifier of the element. + aria_label: Defines a string value that labels the current element. + aria_labelledby: Identifies the element (or elements) that labels the current element. + aria_describedby: Identifies the element (or elements) that describes the object. + aria_details: Identifies the element (or elements) that provide a detailed, extended description for the object. + UNSAFE_class_name: Set the CSS className for the element. Only use as a last resort. Use style props instead. + UNSAFE_style: Set the inline style for the element. Only use as a last resort. Use style props instead. + + Returns: + The rendered avatar element. + + """ + return component_element( + "Avatar", + src=src, + is_disabled=is_disabled, + size=size, + alt=alt, + 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_column=grid_column, + grid_row_start=grid_row_start, + grid_row_end=grid_row_end, + 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, + left=left, + right=right, + start=start, + end=end, + z_index=z_index, + is_hidden=is_hidden, + id=id, + aria_label=aria_label, + aria_labelledby=aria_labelledby, + aria_describedby=aria_describedby, + aria_details=aria_details, + UNSAFE_class_name=UNSAFE_class_name, + UNSAFE_style=UNSAFE_style, + ) diff --git a/plugins/ui/src/deephaven/ui/types/types.py b/plugins/ui/src/deephaven/ui/types/types.py index 1b8b9bd15..8815935f3 100644 --- a/plugins/ui/src/deephaven/ui/types/types.py +++ b/plugins/ui/src/deephaven/ui/types/types.py @@ -507,6 +507,16 @@ class SliderChange(TypedDict): ActionGroupDensity = Literal["compact", "regular"] TabDensity = Literal["compact", "regular"] LinkVariant = Literal["primary", "secondary", "over_background"] +AvatarSize = Literal[ + "avatar-size-50", + "avatar-sie-100", + "avatar-size-200", + "avatar-size-300", + "avatar-size-400", + "avatar-size-500", + "avatar-size-600", + "avatar-size-600", +] BadgeVariant = Literal[ "neutral", "info", diff --git a/plugins/ui/src/js/src/elements/model/ElementConstants.ts b/plugins/ui/src/js/src/elements/model/ElementConstants.ts index 9aa6cd7bf..391bb3c92 100644 --- a/plugins/ui/src/js/src/elements/model/ElementConstants.ts +++ b/plugins/ui/src/js/src/elements/model/ElementConstants.ts @@ -26,6 +26,7 @@ export const ELEMENT_NAME = { actionButton: uiComponentName('ActionButton'), actionGroup: uiComponentName('ActionGroup'), actionMenu: uiComponentName('ActionMenu'), + avatar: uiComponentName('Avatar'), badge: uiComponentName('Badge'), button: uiComponentName('Button'), buttonGroup: uiComponentName('ButtonGroup'), diff --git a/plugins/ui/src/js/src/widget/WidgetUtils.tsx b/plugins/ui/src/js/src/widget/WidgetUtils.tsx index e29d3c1ea..7041124ea 100644 --- a/plugins/ui/src/js/src/widget/WidgetUtils.tsx +++ b/plugins/ui/src/js/src/widget/WidgetUtils.tsx @@ -6,6 +6,7 @@ import type { JSONRPCServerAndClient } from 'json-rpc-2.0'; // wrapped due to how Spectrum collection components consume them. import { ActionMenu, + Avatar, ButtonGroup, SpectrumCheckbox as Checkbox, CheckboxGroup, @@ -112,6 +113,7 @@ export const elementComponentMap = { [ELEMENT_NAME.actionButton]: ActionButton, [ELEMENT_NAME.actionGroup]: ActionGroup, [ELEMENT_NAME.actionMenu]: ActionMenu, + [ELEMENT_NAME.avatar]: Avatar, [ELEMENT_NAME.badge]: Badge, [ELEMENT_NAME.button]: Button, [ELEMENT_NAME.buttonGroup]: ButtonGroup, From ae0cdef9f4b8bb156f6df926790c937559606f3d Mon Sep 17 00:00:00 2001 From: Akshat Jawne <69530774+AkshatJawne@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:34:53 -0500 Subject: [PATCH 2/4] Update plugins/ui/docs/components/avatar.md Co-authored-by: margaretkennedy <82049573+margaretkennedy@users.noreply.github.com> --- plugins/ui/docs/components/avatar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ui/docs/components/avatar.md b/plugins/ui/docs/components/avatar.md index 6eed31b36..4cd6f3b93 100644 --- a/plugins/ui/docs/components/avatar.md +++ b/plugins/ui/docs/components/avatar.md @@ -14,7 +14,7 @@ my_avatar_basic = ui.avatar(src="https://i.imgur.com/kJOwAdv.png", alt="default ## Disabled State -The `is_disabled` prop disables avatars to prevent user interaction, and gives it a silenced style. +The `is_disabled` prop disables avatars to prevent user interaction and gives them a silenced style. ```python from deephaven import ui From 5fb12e8ed47e942d85ad7e2300dea0f55878cc49 Mon Sep 17 00:00:00 2001 From: Akshat Jawne Date: Fri, 22 Nov 2024 12:43:33 -0500 Subject: [PATCH 3/4] make change to code review --- plugins/ui/docs/components/avatar.md | 69 +++++++++++++++------- plugins/ui/src/deephaven/ui/types/types.py | 5 +- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/plugins/ui/docs/components/avatar.md b/plugins/ui/docs/components/avatar.md index 6eed31b36..d7c94b8df 100644 --- a/plugins/ui/docs/components/avatar.md +++ b/plugins/ui/docs/components/avatar.md @@ -8,7 +8,9 @@ An avatar is a small image or icon representing a user or organization. from deephaven import ui -my_avatar_basic = ui.avatar(src="https://i.imgur.com/kJOwAdv.png", alt="default avatar") +my_avatar_basic = ui.avatar( + src="https://github.com/deephaven.png", alt="default avatar" +) ``` @@ -21,11 +23,34 @@ from deephaven import ui my_avatar_is_disabled_example = ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", alt="default avatar", is_disabled=True + src="https://github.com/deephaven.png", alt="default avatar", is_disabled=True ) ``` +## Local Image + +The following example shows to download an image from a URL, encode it in base64, and use it to create an avatar with a specified size using `ui.avatar`. + +```python +from deephaven import ui +import urllib.request +import base64 + + +url = "https://github.com/deephaven.png" +file_name, headers = urllib.request.urlretrieve(url) + + +with open(file_name, "rb") as f: + file_content = f.read() + + +b64_content = base64.b64encode(file_content).decode() +b64_avatar = ui.avatar(src=f"data:image/png;base64,{b64_content}", size=300) +``` + + ## Size The `size` of an avatar can be set to one of the preset sizes, or a custom pixel value. @@ -38,51 +63,53 @@ from deephaven import ui def ui_avatar_sizing_examples(): return [ ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-50", size="avatar-size-50", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-75", size="avatar-size-75", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="davatar-size-100", size="avatar-size-100", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-200", size="avatar-size-200", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-300", size="avatar-size-300", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-400", size="avatar-size-400", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-500", size="avatar-size-500", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-600", size="avatar-size-600", ), ui.avatar( - src="https://i.imgur.com/kJOwAdv.png", - alt="default avatar", + src="https://github.com/deephaven.png", + alt="avatar-size-700", size="avatar-size-700", ), - ui.avatar(src="https://i.imgur.com/kJOwAdv.png", alt="default avatar", size=80), + ui.avatar( + src="https://github.com/deephaven.png", alt="custom pixel size", size=80 + ), ] diff --git a/plugins/ui/src/deephaven/ui/types/types.py b/plugins/ui/src/deephaven/ui/types/types.py index 8815935f3..106b4d1b5 100644 --- a/plugins/ui/src/deephaven/ui/types/types.py +++ b/plugins/ui/src/deephaven/ui/types/types.py @@ -509,13 +509,14 @@ class SliderChange(TypedDict): LinkVariant = Literal["primary", "secondary", "over_background"] AvatarSize = Literal[ "avatar-size-50", - "avatar-sie-100", + "avatar-size-75", + "avatar-size-100", "avatar-size-200", "avatar-size-300", "avatar-size-400", "avatar-size-500", "avatar-size-600", - "avatar-size-600", + "avatar-size-700", ] BadgeVariant = Literal[ "neutral", From 4e952055a942acde157a82b88ef10845356416b9 Mon Sep 17 00:00:00 2001 From: Akshat Jawne Date: Tue, 26 Nov 2024 16:54:07 -0500 Subject: [PATCH 4/4] remove example --- plugins/ui/docs/components/avatar.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/plugins/ui/docs/components/avatar.md b/plugins/ui/docs/components/avatar.md index e36144b6a..a098dcbae 100644 --- a/plugins/ui/docs/components/avatar.md +++ b/plugins/ui/docs/components/avatar.md @@ -28,29 +28,6 @@ my_avatar_is_disabled_example = ui.avatar( ``` -## Local Image - -The following example shows to download an image from a URL, encode it in base64, and use it to create an avatar with a specified size using `ui.avatar`. - -```python -from deephaven import ui -import urllib.request -import base64 - - -url = "https://github.com/deephaven.png" -file_name, headers = urllib.request.urlretrieve(url) - - -with open(file_name, "rb") as f: - file_content = f.read() - - -b64_content = base64.b64encode(file_content).decode() -b64_avatar = ui.avatar(src=f"data:image/png;base64,{b64_content}", size=300) -``` - - ## Size The `size` of an avatar can be set to one of the preset sizes, or a custom pixel value.