Skip to content

Commit 55e8ce2

Browse files
authored
feat: ui.badge (#973)
Closes #935 and Closes #868 (Also includes docs for ui.badge).
1 parent 2eb5fab commit 55e8ce2

File tree

9 files changed

+291
-0
lines changed

9 files changed

+291
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Badge
2+
3+
Badges display small, color-coded pieces of metadata to capture a user's attention. They are useful for highlighting important information, such as notifications, statuses, or counts.
4+
5+
## Example
6+
7+
```python
8+
from deephaven import ui
9+
10+
my_badge_basic = ui.badge("Licensed", variant="positive")
11+
```
12+
13+
## UI recommendations
14+
15+
Consider using [`text`](./text.md) to provide descriptive text for elements without the colored emphasis of a badge.
16+
17+
18+
## Content
19+
20+
Badges can include a label, an icon, or both as children.
21+
22+
```python
23+
from deephaven import ui
24+
25+
26+
my_badge_context_example = ui.badge(
27+
ui.icon("vsWarning"), "Rejected", variant="negative"
28+
)
29+
```
30+
31+
32+
## Variants
33+
34+
Badges can have different colors to indicate their purpose.
35+
36+
```python
37+
from deephaven import ui
38+
39+
40+
@ui.component
41+
def ui_badge_variant_examples():
42+
return [
43+
ui.badge(
44+
"Green: Approved, Complete, Success, New, Purchased, Licensed",
45+
variant="positive",
46+
),
47+
ui.badge("Blue: Active, In Use, Live, Published", variant="info"),
48+
ui.badge("Red: Error, Alert, Rejected, Failed", variant="negative"),
49+
ui.badge(
50+
"Gray: Archived, Deleted, Paused, Draft, Not Started, Ended",
51+
variant="neutral",
52+
),
53+
]
54+
55+
56+
my_badge_variant_examples = ui_badge_variant_examples()
57+
```
58+
59+
Use badges with label colors to color-code categories, ideally for 8 or fewer categories.
60+
61+
62+
```python
63+
from deephaven import ui
64+
65+
66+
@ui.component
67+
def ui_badge_variant_color_examples():
68+
return [
69+
ui.badge("Seafoam", variant="seafoam"),
70+
ui.badge("Indigo", variant="indigo"),
71+
ui.badge("Purple", variant="purple"),
72+
ui.badge("Fuchsia", variant="fuchsia"),
73+
ui.badge("Magenta", variant="magenta"),
74+
ui.badge("Yellow", variant="yellow"),
75+
]
76+
77+
78+
my_badge_variant_color_examples = ui_badge_variant_color_examples()
79+
```
80+
81+
## API reference
82+
83+
```{eval-rst}
84+
.. dhautofunction:: deephaven.ui.badge
85+
```

plugins/ui/docs/sidebar.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
"label": "action_menu",
3838
"path": "components/action_menu.md"
3939
},
40+
{
41+
"label": "badge",
42+
"path": "components/badge.md"
43+
},
4044
{
4145
"label": "button",
4246
"path": "components/button.md"

plugins/ui/src/deephaven/ui/components/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .basic import (
55
component_element,
66
)
7+
from .badge import badge
78
from .button import button
89
from .button_group import button_group
910
from .calendar import calendar
@@ -68,6 +69,7 @@
6869
"action_group",
6970
"action_menu",
7071
"component_element",
72+
"badge",
7173
"button",
7274
"button_group",
7375
"calendar",
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
from __future__ import annotations
2+
from typing import Any
3+
from .types import (
4+
# Layout
5+
AlignSelf,
6+
CSSProperties,
7+
DimensionValue,
8+
JustifySelf,
9+
LayoutFlex,
10+
Position,
11+
)
12+
from .basic import component_element
13+
from ..elements import Element
14+
from ..types import BadgeVariant
15+
16+
17+
def badge(
18+
*children: Any,
19+
variant: BadgeVariant | None = None,
20+
flex: LayoutFlex | None = None,
21+
flex_grow: float | None = None,
22+
flex_shrink: float | None = None,
23+
flex_basis: DimensionValue | None = None,
24+
align_self: AlignSelf | None = None,
25+
justify_self: JustifySelf | None = None,
26+
order: int | None = None,
27+
grid_area: str | None = None,
28+
grid_row: str | None = None,
29+
grid_column: str | None = None,
30+
grid_row_start: str | None = None,
31+
grid_row_end: str | None = None,
32+
grid_column_start: str | None = None,
33+
grid_column_end: str | None = None,
34+
margin: DimensionValue | None = None,
35+
margin_top: DimensionValue | None = None,
36+
margin_bottom: DimensionValue | None = None,
37+
margin_start: DimensionValue | None = None,
38+
margin_end: DimensionValue | None = None,
39+
margin_x: DimensionValue | None = None,
40+
margin_y: DimensionValue | None = None,
41+
width: DimensionValue | None = None,
42+
height: DimensionValue | None = None,
43+
min_width: DimensionValue | None = None,
44+
min_height: DimensionValue | None = None,
45+
max_width: DimensionValue | None = None,
46+
max_height: DimensionValue | None = None,
47+
position: Position | None = None,
48+
top: DimensionValue | None = None,
49+
bottom: DimensionValue | None = None,
50+
left: DimensionValue | None = None,
51+
right: DimensionValue | None = None,
52+
start: DimensionValue | None = None,
53+
end: DimensionValue | None = None,
54+
z_index: int | None = None,
55+
is_hidden: bool | None = None,
56+
id: str | None = None,
57+
aria_label: str | None = None,
58+
aria_labelledby: str | None = None,
59+
aria_describedby: str | None = None,
60+
aria_details: str | None = None,
61+
UNSAFE_class_name: str | None = None,
62+
UNSAFE_style: CSSProperties | None = None,
63+
key: str | None = None,
64+
) -> Element:
65+
"""
66+
A badge is used for showing a small amount of color-categorized metadata.
67+
68+
Args:
69+
*children: The content to display in the badge.
70+
variant: The background color of the badge.
71+
flex: When used in a flex layout, specifies how the element will grow or shrink to fit the space available.
72+
flex_grow: When used in a flex layout, specifies how the element will grow to fit the space available.
73+
flex_shrink: When used in a flex layout, specifies how the element will shrink to fit the space available.
74+
flex_basis: When used in a flex layout, specifies the initial main size of the element.
75+
align_self: Overrides the alignItems property of a flex or grid container.
76+
justify_self: Species how the element is justified inside a flex or grid container.
77+
order: The layout order for the element within a flex or grid container.
78+
grid_area: When used in a grid layout specifies, specifies the named grid area that the element should be placed in within the grid.
79+
grid_row: When used in a grid layout, specifies the row the element should be placed in within the grid.
80+
grid_column: When used in a grid layout, specifies the column the element should be placed in within the grid.
81+
grid_row_start: When used in a grid layout, specifies the starting row to span within the grid.
82+
grid_row_end: When used in a grid layout, specifies the ending row to span within the grid.
83+
grid_column_start: When used in a grid layout, specifies the starting column to span within the grid.
84+
grid_column_end: When used in a grid layout, specifies the ending column to span within the grid.
85+
margin: The margin for all four sides of the element.
86+
margin_top: The margin for the top side of the element.
87+
margin_bottom: The margin for the bottom side of the element.
88+
margin_start: The margin for the logical start side of the element, depending on layout direction.
89+
margin_end: The margin for the logical end side of the element, depending on layout direction.
90+
margin_x: The margin for the left and right sides of the element.
91+
margin_y: The margin for the top and bottom sides of the element.
92+
width: The width of the element.
93+
height: The height of the element.
94+
min_width: The minimum width of the element.
95+
min_height: The minimum height of the element.
96+
max_width: The maximum width of the element.
97+
max_height: The maximum height of the element.
98+
position: Specifies how the element is position.
99+
top: The top position of the element.
100+
bottom: The bottom position of the element.
101+
left: The left position of the element.
102+
right: The right position of the element.
103+
start: The logical start position of the element, depending on layout direction.
104+
end: The logical end position of the element, depending on layout direction.
105+
z_index: The stacking order for the element
106+
is_hidden: Hides the element.
107+
id: The unique identifier of the element.
108+
aria_label: Defines a string value that labels the current element.
109+
aria_labelledby: Identifies the element (or elements) that labels the current element.
110+
aria_describedby: Identifies the element (or elements) that describes the object.
111+
aria_details: Identifies the element (or elements) that provide a detailed, extended description for the object.
112+
UNSAFE_class_name: Set the CSS className for the element. Only use as a last resort. Use style props instead.
113+
UNSAFE_style: Set the inline style for the element. Only use as a last resort. Use style props instead.
114+
key: A unique identifier used by React to render elements in a list.
115+
116+
Returns:
117+
The rendered badge element.
118+
119+
"""
120+
return component_element(
121+
"Badge",
122+
*children,
123+
variant=variant,
124+
flex=flex,
125+
flex_grow=flex_grow,
126+
flex_shrink=flex_shrink,
127+
flex_basis=flex_basis,
128+
align_self=align_self,
129+
justify_self=justify_self,
130+
order=order,
131+
grid_area=grid_area,
132+
grid_row=grid_row,
133+
grid_column=grid_column,
134+
grid_row_start=grid_row_start,
135+
grid_row_end=grid_row_end,
136+
grid_column_start=grid_column_start,
137+
grid_column_end=grid_column_end,
138+
margin=margin,
139+
margin_top=margin_top,
140+
margin_bottom=margin_bottom,
141+
margin_start=margin_start,
142+
margin_end=margin_end,
143+
margin_x=margin_x,
144+
margin_y=margin_y,
145+
width=width,
146+
height=height,
147+
min_width=min_width,
148+
min_height=min_height,
149+
max_width=max_width,
150+
max_height=max_height,
151+
position=position,
152+
top=top,
153+
bottom=bottom,
154+
left=left,
155+
right=right,
156+
start=start,
157+
end=end,
158+
z_index=z_index,
159+
is_hidden=is_hidden,
160+
id=id,
161+
aria_label=aria_label,
162+
aria_labelledby=aria_labelledby,
163+
aria_describedby=aria_describedby,
164+
aria_details=aria_details,
165+
UNSAFE_class_name=UNSAFE_class_name,
166+
UNSAFE_style=UNSAFE_style,
167+
key=key,
168+
)

plugins/ui/src/deephaven/ui/types/types.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,18 @@ class SliderChange(TypedDict):
507507
ActionGroupDensity = Literal["compact", "regular"]
508508
TabDensity = Literal["compact", "regular"]
509509
LinkVariant = Literal["primary", "secondary", "over_background"]
510+
BadgeVariant = Literal[
511+
"neutral",
512+
"info",
513+
"positive",
514+
"negative",
515+
"indigo",
516+
"yellow",
517+
"magenta",
518+
"fuchsia",
519+
"purple",
520+
"seafoam",
521+
]
510522
Dependencies = Union[Tuple[Any], List[Any]]
511523
Selection = Sequence[Key]
512524
LocalTime = DType
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import {
3+
Badge as DHCBadge,
4+
BadgeProps as DHCBadgeProps,
5+
} from '@deephaven/components';
6+
import { wrapTextChildren } from './utils';
7+
8+
export function Badge(props: DHCBadgeProps): JSX.Element {
9+
const { children } = props;
10+
return (
11+
// eslint-disable-next-line react/jsx-props-no-spreading
12+
<DHCBadge {...props}>{wrapTextChildren(children)}</DHCBadge>
13+
);
14+
}
15+
Badge.displayName = 'Badge';
16+
export default Badge;

plugins/ui/src/js/src/elements/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './ActionButton';
22
export * from './ActionGroup';
3+
export * from './Badge';
34
export * from './Button';
45
export * from './Calendar';
56
export * from './ComboBox';

plugins/ui/src/js/src/elements/model/ElementConstants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const ELEMENT_NAME = {
2626
actionButton: uiComponentName('ActionButton'),
2727
actionGroup: uiComponentName('ActionGroup'),
2828
actionMenu: uiComponentName('ActionMenu'),
29+
badge: uiComponentName('Badge'),
2930
button: uiComponentName('Button'),
3031
buttonGroup: uiComponentName('ButtonGroup'),
3132
calendar: uiComponentName('Calendar'),

plugins/ui/src/js/src/widget/WidgetUtils.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import Dashboard from '../layout/Dashboard';
4949
import {
5050
ActionButton,
5151
ActionGroup,
52+
Badge,
5253
Button,
5354
Calendar,
5455
ComboBox,
@@ -110,6 +111,7 @@ export const elementComponentMap = {
110111
[ELEMENT_NAME.actionButton]: ActionButton,
111112
[ELEMENT_NAME.actionGroup]: ActionGroup,
112113
[ELEMENT_NAME.actionMenu]: ActionMenu,
114+
[ELEMENT_NAME.badge]: Badge,
113115
[ELEMENT_NAME.button]: Button,
114116
[ELEMENT_NAME.buttonGroup]: ButtonGroup,
115117
[ELEMENT_NAME.calendar]: Calendar,

0 commit comments

Comments
 (0)