Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: UI table formatting #950

Merged
merged 23 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions plugins/ui/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
# options for sphinx_autodoc_typehints
always_use_bars_union = True

strip_signature_backslash = True

from deephaven_server import Server

# need a server instance to pull types from the autodocs
Expand Down
139 changes: 139 additions & 0 deletions plugins/ui/docs/components/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,137 @@ t = ui.table(_t)
2. Use a UI table to show properties like filters as if the user had created them in the UI. Users can change the default values provided by the UI table, such as filters.
3. UI tables handle ticking tables automatically, so you can pass any Deephaven table to a UI table.

## Formatting

You can format the table using the `format_` prop. This prop takes a list of `ui.TableFormat` objects. `ui.TableFormat` is a dataclass that encapsulates the formatting options for a table. The full list of formatting options can be found in the [API Reference](#tableformat).

### Formatting Rows and Columns
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

Every formatting rule may optionally specify `cols` and `if_` properties. The `cols` property is a column name or list of column names to apply the formatting rule to. If `cols` is omitted, then the rule will be applied to the entire row. The `if_` property is a Deephaven formula to apply the formatting rule to. The `if_` property _must_ evaluate to a boolean. If `if_` is omitted, then the rule will be applied to every row. These may be combined to apply formatting to specific columns only when a condition is met.
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

> [!NOTE]
> The `if_` property is a Deephaven formula evaluated in the engine. You can think of it like adding a new boolean column using [`update_view`](https://deephaven.io/core/docs/reference/table-operations/select/update-view/)
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a sections for each formatter? Helps both SEO and shows a functional example of how to accomplish each task

#### Formatting table background colors

#### Formatting table decimals

#### Formatting table dates
...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to do Formatting Colors and Formatting Values unless you want each of those sections to be 1 or 2 sentences. That feels like overkill to me to show someone what "changing the background color to red" does or "changing text alignment to left".

I think formatting colors would explain what kind of color values you can use and what values can take colors.

Formatting values would link out to appropriate docs about value format strings (I think they're Java formatting strings, but need to verify)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting colors and Formatting values sound reasonable in terms of avoiding super short sections; however, if a user is likely to search "Formatting table dates" and similar, it might be worth it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up adding Formatting Colors as an h3 to describe you can (and should) use theme colors. Then text/background color as h4.

For values I added an h3 for numeric and datetime

The following example shows how to format the `Sym` and `Exchange` columns with a red background and white text when the `Sym` is `DOG`.

```python
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(
cols=["Sym", "Exchange"],
if_="Sym = `DOG`",
background_color="red",
color="white",
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved
)
],
)
```

### Formatting Rule Priority
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

The last matching formatting rule for each property will be applied. This means the lowest priority rules should be first in the list with higher priority rules at the end.

In the following example, the `Sym` column will have a red background with white text, and the rest of the table will have a blue background with white text.

```python
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(background_color="blue", color="white"),
ui.TableFormat(cols="Sym", background_color="red"),
],
)
```

### Formatting Color
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

Formatting rules for colors support Deephaven theme colors, hex colors, or any valid CSS color (e.g., `red`, `#ff0000`, `rgb(255, 0, 0)`). It is **recommended to use Deephaven theme colors** when possible to maintain a consistent look and feel across the UI. Theme colors will also automatically update if the user changes the theme.

#### Formatting Text Color
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

The `color` property sets the text color of the cell. If a cell has a `background_color`, but no `color` set, the text color will be set to black or white depending on which contrasts better with the background color. Setting the `color` property will override this behavior.

The following example will make all text the foreground color except the `Sym` column, which will be white. In dark mode the foreground color is white, and in light mode the foreground color is black. In light mode, the `Sym` column will be nearly invisible because it is not a theme color
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

```py
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(color="fg"),
ui.TableFormat(cols="Sym", color="white"),
],
)
```

#### Formatting Background Color
mattrunyon marked this conversation as resolved.
Show resolved Hide resolved

The `background_color` property sets the background color of the cell. Setting the `background_color` without setting `color` will result in the text color automatically being set to black or white based on the contrast with the `background_color`.

The following example will make all the background color what is usually the foreground color. This means the table will have a white background with black text in dark theme and a black background with white text in light theme. The `Sym` column text will be the accent color in both themes.

```py
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(background_color="fg"),
ui.TableFormat(cols="Sym", color="accent"),
],
)
```

### Formatting Numeric Values

> [!WARNING]
> Datetime values are considered numeric. If you provide a default format for numeric values, it will also apply to datetime values. It is recommended to specify `cols` when applying value formats.

Numeric values can be formatted using the `value` property. The `value` property is a string that follows [the GWT Java NumberFormat syntax](https://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/NumberFormat.html). If a numeric format is applied to a non-numeric column, it will be ignored.

This example will format the `Price` and `Dollars` columns with the dollar sign, a comma separator for every 3 digits, 2 decimal places, and a minimum of 1 digit to the left of the decimal point. The `Random` column will be formatted with 3 decimal places and will drop the leading zero if the absolute value is less than 1.

```py
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(cols=["Price", "Dollars"], value="$#,##0.00"),
ui.TableFormat(cols="Random", value="#.000")
],
)
```

### Formatting Datetime Values

Datetime values can be formatted using the `value` property. The `value` property is a string that follows [the GWT Java DateTimeFormat syntax](https://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/DateTimeFormat.html) with additional support for nanoseconds. You may provide up to 9 `S` characters after the decimal to represent partial seconds down to nanoseconds.

The following example formats the `Timestamp` column to show the short date of the week, day of the month, short month name, full year, hours, minutes, seconds, and microseconds with the user selected timezone.

```py
from deephaven import ui
import deephaven.plot.express as dx

t = ui.table(
dx.data.stocks(),
format_=[
ui.TableFormat(cols="Timestamp", value="E, dd MMM yyyy HH:mm:ss.SSSSSS z"),
],
)
```

## Events

You can listen for different user events on a `ui.table`. There is both a `press` and `double_press` event for `row`, `cell`, and `column`. These events typically correspond to a click or double click on the table. The event payloads include table data related to the event. For `row` and `column` events, the corresponding data within the viewport will be sent to the event handler. The viewport is typically the visible area ± a window equal to the visible area (e.g., if rows 5-10 are visible, rows 0-15 will be in the viewport).
Expand Down Expand Up @@ -265,6 +396,14 @@ t = ui.table(

## API Reference

### Table

```{eval-rst}
.. dhautofunction:: deephaven.ui.table
```

### TableFormat

```{eval-rst}
.. dhautofunction:: deephaven.ui.TableFormat
```
4 changes: 3 additions & 1 deletion plugins/ui/src/deephaven/ui/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from .tab_list import tab_list
from .tab_panels import tab_panels
from .tab import tab
from .table import table
from .table import table, TableDatabar, TableFormat
from .tabs import tabs
from .text import text
from .text_area import text_area
Expand Down Expand Up @@ -108,6 +108,8 @@
"stack",
"switch",
"table",
"TableDatabar",
"TableFormat",
"tab_list",
"tab_panels",
"tabs",
Expand Down
Loading
Loading