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

docs: Component Rules #1055

Merged
merged 16 commits into from
Dec 16, 2024
90 changes: 90 additions & 0 deletions plugins/ui/docs/describing/component_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Component Rules

Here are some important rules to understand about `deephaven.ui` components.
dgodinez-dh marked this conversation as resolved.
Show resolved Hide resolved

## Children and Props

Arguments passed to a component may be either `children` or `props`. `Children` refers to `child` components that are passed to a `parent` component as arguments. `Props` are properties that determine the behavior and rendering style of the component.
dgodinez-dh marked this conversation as resolved.
Show resolved Hide resolved

```python
margaretkennedy marked this conversation as resolved.
Show resolved Hide resolved
from deephaven import ui

my_flex = ui.flex(
ui.heading("Heading"),
ui.button("Button"),
ui.text("Text"),
direction="column",
wrap=True,
width="200px",
)
```

In the above example, the `flex` component is the `parent`. It has three `children`: a `heading`, a `button`, and a `text` component. These `children` will be rendered inside the `flex`. It also has three props: `direction`, `wrap`, and `width`. These three props indicate that the flex should be rendered as a 200 pixel column with wrap enabled.

## Defining Your Own Children and Props
Copy link
Contributor

Choose a reason for hiding this comment

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

sentence case for headings, please

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed


To define `children` and `props` for a custom component, add them as arguments to the component function. As a convention, you may declare the children using the `*` symbol to take any number of arguments.

```python
margaretkennedy marked this conversation as resolved.
Show resolved Hide resolved
from deephaven import ui


@ui.component
def custom_flex(*children, is_column):
return ui.flex(
ui.heading("My Component"),
children,
direction="column" if is_column else "row",
)


my_custom_flex = custom_flex(ui.text("text"), ui.button("button"), is_column=True)
```

## Component Return Values

You can return three values from a `deephaven.ui` component: a component, a list of components, or `None`. Returning a single component will render that component at the root level of a panel. Returning a list of components will render all the components in a panel. Returning `None` should be used when a component is used to perform logic but does not need to be rendered.
Copy link
Contributor

Choose a reason for hiding this comment

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

@mofojed this isn't true? For instance you can also return hooks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did not know you could return hooks from a component. Can you also return primitive values like strings, numbers, and booleans?

Copy link
Member

Choose a reason for hiding this comment

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

@dsmmcken What do you mean return hooks? You can return the result of a hook, but returning the hook itself doesn't make sense (ditto in React). The result of the hook could be a component, list of components, None, or a primitive.
You can also return primitives though, such as str, int, boolean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I pushed an update. I'm still not sure if this is saying what we want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I tested dict and set. They do not open up a panel.
With bool, it opens a panel, but does not render anything (where string and int get rendered).

Copy link
Member

Choose a reason for hiding this comment

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

Yes that's correct. I don't know why you'd want to return a boolean (since it doesn't get rendered), but React does allow you to do that.
Returning a dict or a set could possibly give you an error. There's a little playground at the bottom of the React page where you can play with what are valid returns, we should match that: https://react.dev/learn/your-first-component

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to add a code playground in our docs? Can we do that in an md file?

Copy link
Member

Choose a reason for hiding this comment

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

We want to do that, it will not be in the first deployment.
With React Playground it's nice because it all runs client side. We need to have a server running for our playground, so setup is a little more complicated. Probably use a running instance that's shared between all viewers of the docs.

Copy link
Contributor

Choose a reason for hiding this comment

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

What do you mean return hooks? You can return the result of a hook,

Yeah, that's what I meant, like return [my_state, my_set_state]

Copy link
Member

Choose a reason for hiding this comment

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

@dsmmcken doing return [my_state, my_set_state] does not make sense from a component. You can do that from other hooks, but that doesn't make sense in React or in deephaven.ui.
You can do return my_state. You wouldn't return the setter function.


```python
from deephaven import ui


@ui.component
def return_component():
return ui.text("component")


@ui.component
def list_of_components():
return [ui.text("list"), ui.text("of"), ui.text("components")]


@ui.component
def return_none():
print("return none")
return None


my_return_component = return_component()
my_list_of_components = list_of_components()
my_return_none = return_none()
```

## Conditional Return

Return statements can be conditional in order to render different components based on inputs.

```python
from deephaven import ui


@ui.component
def return_conditional(is_button):
if is_button:
return ui.button("button")
return ui.text("text")


my_button = return_conditional(True)
my_text = return_conditional(False)
```
margaretkennedy marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 9 additions & 0 deletions plugins/ui/docs/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
"label": "Architecture",
"path": "architecture.md"
},
{
"label": "Describing the UI",
"items": [
{
"label": "Component Rules",
"path": "describing/component_rules.md"
}
]
},
{
"label": "Components",
"items": [
Expand Down
Loading