Repository: deephaven/deephaven-plugins
Pull request #1158: docs: escape hatches
Author: login: dgodinez-dh
Created: 2025-04-07T20:56:30Z | Merged: 2025-04-09T13:32:11Z

https://deephaven.atlassian.net/browse/DOC-701


Diff:
diff --git a/plugins/ui/docs/components/html.md b/plugins/ui/docs/components/html.md
new file mode 100644
index 000000000..05236dd1f
--- /dev/null
+++ b/plugins/ui/docs/components/html.md
@@ -0,0 +1,100 @@
+# HTML Component Documentation
+
+The `html` module provides utilities for rendering HTML content within the `deephaven.ui`. This allows users to embed custom HTML elements into their applications.
+
+## Example
+
+```python
+from deephaven import ui
+
+basic_html_example = ui.html.div("basic html example")
+```
+
+## UI recommendations
+
+**Avoid using `html` components unless necessary**: This is an advanced feature that should only be used when creating an HTML component not covered by other `deephaven.ui` components. HTML components are not themed and may respond incorrectly to different user layouts.
+
+## HTML Element
+
+The `html_element` method allows you to specify any html `tag` along with any `children` and `attributes`.
+
+```python
+from deephaven import ui
+
+simple_html = ui.html.html_element("div", "Welcome to Deephaven", id="simple")
+
+nested_html = ui.html.html_element(
+    "div",
+    ui.html.html_element("h1", "Welcome to Deephaven"),
+    ui.html.html_element("p", "This is a custom HTML component."),
+    id="nested",
+)
+```
+
+## Common Tags
+
+`ui.html` also provides methods for common tags.
+
+```python
+from deephaven import ui
+
+simple_html = ui.html.div("Welcome to Deephaven", id="simple")
+
+nested_html = ui.html.div(
+    ui.html.h1("Welcome to Deephaven"),
+    ui.html.p("This is a custom HTML component."),
+    id="nested",
+)
+```
+
+For a full list of methods, see the API reference below.
+
+## Use with `deephaven.ui`
+
+The `ui.html` component can be nested inside other `deephaven.ui` components and vice versa.
+
+```python
+from deephaven import ui
+
+component = ui.view(
+    ui.heading("HTML inside a component"), ui.html.label("this is html")
+)
+
+html = ui.html.div(ui.html.h1("Component inside html"), ui.text("this is a component"))
+```
+
+## API reference
+
+```{eval-rst}
+.. dhautofunction:: deephaven.ui.html.html_element
+.. dhautofunction:: deephaven.ui.html.a
+.. dhautofunction:: deephaven.ui.html.button
+.. dhautofunction:: deephaven.ui.html.code
+.. dhautofunction:: deephaven.ui.html.div
+.. dhautofunction:: deephaven.ui.html.form
+.. dhautofunction:: deephaven.ui.html.h1
+.. dhautofunction:: deephaven.ui.html.h2
+.. dhautofunction:: deephaven.ui.html.h3
+.. dhautofunction:: deephaven.ui.html.h4
+.. dhautofunction:: deephaven.ui.html.h5
+.. dhautofunction:: deephaven.ui.html.h6
+.. dhautofunction:: deephaven.ui.html.i
+.. dhautofunction:: deephaven.ui.html.img
+.. dhautofunction:: deephaven.ui.html.input
+.. dhautofunction:: deephaven.ui.html.label
+.. dhautofunction:: deephaven.ui.html.li
+.. dhautofunction:: deephaven.ui.html.ol
+.. dhautofunction:: deephaven.ui.html.option
+.. dhautofunction:: deephaven.ui.html.p
+.. dhautofunction:: deephaven.ui.html.pre
+.. dhautofunction:: deephaven.ui.html.selection
+.. dhautofunction:: deephaven.ui.html.span
+.. dhautofunction:: deephaven.ui.html.table
+.. dhautofunction:: deephaven.ui.html.tbody
+.. dhautofunction:: deephaven.ui.html.td
+.. dhautofunction:: deephaven.ui.html.textarea
+.. dhautofunction:: deephaven.ui.html.th
+.. dhautofunction:: deephaven.ui.html.thread
+.. dhautofunction:: deephaven.ui.html.tr
+.. dhautofunction:: deephaven.ui.html.ul
+```
diff --git a/plugins/ui/docs/creating-layouts/escape-hatches.md b/plugins/ui/docs/creating-layouts/escape-hatches.md
new file mode 100644
index 000000000..57cd7b1a3
--- /dev/null
+++ b/plugins/ui/docs/creating-layouts/escape-hatches.md
@@ -0,0 +1,57 @@
+# Escape Hatches
+
+`deephaven.ui` offers a versatile API for building comprehensive UI layouts. However, there may be scenarios where the provided API does not cover specific customization needs. In such cases, three "escape hatches" are available to enable additional customization of `deephaven.ui` components. 
+
+**Avoid using these options unless necessary**.
+
+1. [`ui.html`](../components/html.md) - Provides a set of functions for creating raw HTML elements.
+2. `UNSAFE_class_name` - Allows a custom A CSS class to apply to most `deephaven.ui` components.
+3. `UNSAFE_style` - Allows a custom A CSS style to apply to most `deephaven.ui` components.
+
+## ui.html
+
+`deephaven.ui` provides a large list of components for building a UI. If you need a UI element that is not available, you can use [`ui.html`](../components/html.md) to inject html tags into your UI.
+
+```python
+from deephaven import ui
+
+component_with_html = ui.view(
+    ui.heading("HTML inside a component"),
+    ui.html.div(
+        ui.html.h1("Welcome to Deephaven"),
+        ui.html.p("This is a custom HTML component."),
+        id="html_div",
+    ),
+)
+```
+
+## UNSAFE_class_name
+
+If a component's styling props are not sufficient, you can set the `UNSAFE_class_name` prop, which sets the HTML [`className`](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) attribute on the element. To do this, you must use `ui.html` to define a class name.
+
+```python
+from deephaven import ui
+
+unsafe_class_name = ui.panel(
+    ui.html.style(
+        """
+        .my_class { background: red !important;}
+        """
+    ),
+    ui.button("test", UNSAFE_class_name="my_class"),
+    ui.html.div("test", class_name="my_class"),
+)
+```
+
+## UNSAFE_style
+
+Rather than define a class name as above, you can use the `UNSAFE_style` prop, which allows you to set style props directly on a component using a `dict`.
+
+```python
+from deephaven import ui
+
+unsafe_style = ui.panel(
+    ui.button("test", UNSAFE_style={"background": "red"}),
+    ui.button("test", UNSAFE_style={"background": "green"}),
+)
+```
diff --git a/plugins/ui/docs/sidebar.json b/plugins/ui/docs/sidebar.json
index 5bad502f4..7a45f10a6 100644
--- a/plugins/ui/docs/sidebar.json
+++ b/plugins/ui/docs/sidebar.json
@@ -139,6 +139,10 @@
           {
             "label": "Size and Theme",
             "path": "creating-layouts/size-and-theme.md"
+          },
+          {
+            "label": "Escape Hatches",
+            "path": "creating-layouts/escape-hatches.md"
           }
         ]
       },
@@ -257,6 +261,10 @@
             "label": "heading",
             "path": "components/heading.md"
           },
+          {
+            "label": "html",
+            "path": "components/html.md"
+          },
           {
             "label": "icon",
             "path": "components/icon.md"
diff --git a/plugins/ui/src/deephaven/ui/components/html.py b/plugins/ui/src/deephaven/ui/components/html.py
index 8900600d5..40e2d2f90 100644
--- a/plugins/ui/src/deephaven/ui/components/html.py
+++ b/plugins/ui/src/deephaven/ui/components/html.py
@@ -1,3 +1,5 @@
+from typing import Any
+
 """
 Provides a set of functions for creating raw HTML elements.
 
@@ -6,7 +8,7 @@
 from ..elements import BaseElement
 
 
-def html_element(tag: str, *children, **attributes):
+def html_element(tag: str, *children: Any, **attributes: Any) -> BaseElement:
     """
     Create a new HTML element. Render just returns the children that are passed in.
 
@@ -14,141 +16,484 @@ def html_element(tag: str, *children, **attributes):
         tag: The HTML tag for this element.
         *children: The children of the element.
         **attributes: Attributes to set on the element
+
+    Returns:
+        A new HTML element.
     """
     return BaseElement(f"deephaven.ui.html.{tag}", *children, **attributes)
 
 
-def div(*children, **attributes):
+def div(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "div" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "div" with the specified children and attributes.
+    """
     return html_element("div", *children, **attributes)
 
 
-def span(*children, **attributes):
+def span(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "span" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "span" with the specified children and attributes.
+    """
     return html_element("span", *children, **attributes)
 
 
-def h1(*children, **attributes):
+def h1(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h1" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h1" with the specified children and attributes.
+    """
     return html_element("h1", *children, **attributes)
 
 
-def h2(*children, **attributes):
+def h2(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h2" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h2" with the specified children and attributes.
+    """
     return html_element("h2", *children, **attributes)
 
 
-def h3(*children, **attributes):
+def h3(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h3" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h3" with the specified children and attributes.
+    """
     return html_element("h3", *children, **attributes)
 
 
-def h4(*children, **attributes):
+def h4(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h4" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h4" with the specified children and attributes.
+    """
     return html_element("h4", *children, **attributes)
 
 
-def h5(*children, **attributes):
+def h5(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h5" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h5" with the specified children and attributes.
+    """
     return html_element("h5", *children, **attributes)
 
 
-def h6(*children, **attributes):
+def h6(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "h6" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "h6" with the specified children and attributes.
+    """
     return html_element("h6", *children, **attributes)
 
 
-def p(*children, **attributes):
+def p(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "p" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "p" with the specified children and attributes.
+    """
     return html_element("p", *children, **attributes)
 
 
-def a(*children, **attributes):
+def a(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "a" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "a" with the specified children and attributes.
+    """
     return html_element("a", *children, **attributes)
 
 
-def ul(*children, **attributes):
+def ul(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "ul" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "ul" with the specified children and attributes.
+    """
     return html_element("ul", *children, **attributes)
 
 
-def ol(*children, **attributes):
+def ol(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "ol" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "ol" with the specified children and attributes.
+    """
     return html_element("ol", *children, **attributes)
 
 
-def li(*children, **attributes):
+def li(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "li" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "li" with the specified children and attributes.
+    """
     return html_element("li", *children, **attributes)
 
 
-def table(*children, **attributes):
+def table(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "table" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "table" with the specified children and attributes.
+    """
     return html_element("table", *children, **attributes)
 
 
-def thead(*children, **attributes):
+def thead(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "thead" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "thead" with the specified children and attributes.
+    """
     return html_element("thead", *children, **attributes)
 
 
-def tbody(*children, **attributes):
+def tbody(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "tbody" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "tbody" with the specified children and attributes.
+    """
     return html_element("tbody", *children, **attributes)
 
 
-def tr(*children, **attributes):
+def tr(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "tr" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "tr" with the specified children and attributes.
+    """
     return html_element("tr", *children, **attributes)
 
 
-def th(*children, **attributes):
+def th(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "th" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "th" with the specified children and attributes.
+    """
     return html_element("th", *children, **attributes)
 
 
-def td(*children, **attributes):
+def td(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "td" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "td" with the specified children and attributes.
+    """
     return html_element("td", *children, **attributes)
 
 
-def b(*children, **attributes):
+def b(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "b" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "b" with the specified children and attributes.
+    """
     return html_element("b", *children, **attributes)
 
 
-def i(*children, **attributes):
+def i(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "i" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "i" with the specified children and attributes.
+    """
     return html_element("i", *children, **attributes)
 
 
-def br(*children, **attributes):
+def br(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "br" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "br" with the specified children and attributes.
+    """
     return html_element("br", *children, **attributes)
 
 
-def hr(*children, **attributes):
+def hr(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "hr" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "hr" with the specified children and attributes.
+    """
     return html_element("hr", *children, **attributes)
 
 
-def pre(*children, **attributes):
+def pre(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "pre" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "pre" with the specified children and attributes.
+    """
     return html_element("pre", *children, **attributes)
 
 
-def code(*children, **attributes):
+def code(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "code" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "code" with the specified children and attributes.
+    """
     return html_element("code", *children, **attributes)
 
 
-def img(*children, **attributes):
+def img(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "img" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "img" with the specified children and attributes.
+    """
     return html_element("img", *children, **attributes)
 
 
-def button(*children, **attributes):
+def button(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "button" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "button" with the specified children and attributes.
+    """
     return html_element("button", *children, **attributes)
 
 
-def input(*children, **attributes):
+def input(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "input" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "input" with the specified children and attributes.
+    """
     return html_element("input", *children, **attributes)
 
 
-def form(*children, **attributes):
+def form(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "form" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "form" with the specified children and attributes.
+    """
     return html_element("form", *children, **attributes)
 
 
-def label(*children, **attributes):
+def label(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "label" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "label" with the specified children and attributes.
+    """
     return html_element("label", *children, **attributes)
 
 
-def select(*children, **attributes):
+def select(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "select" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "select" with the specified children and attributes.
+    """
     return html_element("select", *children, **attributes)
 
 
-def option(*children, **attributes):
+def option(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "option" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "option" with the specified children and attributes.
+    """
     return html_element("option", *children, **attributes)
 
 
-def textarea(*children, **attributes):
+def textarea(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "textarea" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "textarea" with the specified children and attributes.
+    """
     return html_element("textarea", *children, **attributes)
 
 
-def style(*children, **attributes):
+def style(*children: Any, **attributes: Any) -> BaseElement:
+    """
+    Creates an HTML "style" element with the specified children and attributes.
+
+    Args:
+        *children: The children of the element.
+        **attributes: Attributes to set on the element
+
+    Returns:
+        An HTML element representing a "style" with the specified children and attributes.
+    """
     return html_element("style", *children, **attributes)


Reviews:
user: login: mofojed
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-08T13:45:48Z
user: login: margaretkennedy
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T16:00:43Z
user: login: mofojed
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-09T13:23:44Z

Review comments:
diff_hunk: @@ -0,0 +1,55 @@
+# Escape Hatches
+
+`deephaven.ui` offers a versatile API for building comprehensive UI layouts. However, there may be scenarios where the provided API does not cover specific customization needs. In such cases, three "escape hatches" are available to enable additional customization of `deephaven.ui` components. **Proceed with caution** when using these options.
path: plugins/ui/docs/creating-layouts/escape-hatches.md
user: login: mofojed
body: The language we use on `use_liveness_scope.md` is "**Avoid using `use_liveness_scope` unless necessary**", which seems a bit stronger. I think we should say something similar here.
```suggestion
`deephaven.ui` offers a versatile API for building comprehensive UI layouts. However, there may be scenarios where the provided API does not cover specific customization needs. In such cases, three "escape hatches" are available to enable additional customization of `deephaven.ui` components. 

**Avoid using these options unless necessary**.
```
created_at: 2025-04-08T13:28:34Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,66 @@
+# HTML Component Documentation
+
+The `html` module provides utilities for rendering HTML content within the `deephaven.ui`. This allows users to embed custom HTML elements into their applications.
+
+## Example
+
+```python
+from deephaven import ui
+
+basic_html_example = ui.html.div("basic html example")
+```
+
path: plugins/ui/docs/components/html.md
user: login: mofojed
body: Add a section for UI Recommendations here, and discourage it's use
```suggestion
## UI recommendations

**Avoid using `html` components unless necessary**: This is an advanced feature that should only be used when you need to create an HTML component not covered by other deephaven.ui components. HTML components are not themed and may not respond correctly to different user layouts.
```
created_at: 2025-04-08T13:45:45Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,100 @@
+# HTML Component Documentation
+
+The `html` module provides utilities for rendering HTML content within the `deephaven.ui`. This allows users to embed custom HTML elements into their applications.
+
+## Example
+
+```python
+from deephaven import ui
+
+basic_html_example = ui.html.div("basic html example")
+```
+
+## UI recommendations
+
+**Avoid using `html` components unless necessary**: This is an advanced feature that should only be used when you need to create an HTML component not covered by other deephaven.ui components. HTML components are not themed and may not respond correctly to different user layouts.
path: plugins/ui/docs/components/html.md
user: login: margaretkennedy
body: ```suggestion
**Avoid using `html` components unless necessary**: This is an advanced feature that should only be used when creating an HTML component not covered by other `deephaven.ui` components. HTML components are not themed and may respond incorrectly to different user layouts.
```
created_at: 2025-04-08T15:57:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+# HTML Component Documentation
+
+The `html` module provides utilities for rendering HTML content within the `deephaven.ui`. This allows users to embed custom HTML elements into their applications.
+
+## Example
+
+```python
+from deephaven import ui
+
+basic_html_example = ui.html.div("basic html example")
+```
+
+## UI recommendations
+
+**Avoid using `html` components unless necessary**: This is an advanced feature that should only be used when you need to create an HTML component not covered by other deephaven.ui components. HTML components are not themed and may not respond correctly to different user layouts.
+
+## HTML Element
+
+The `html_element` method allows to specify any html `tag` along with any `children` and `attributes`.
path: plugins/ui/docs/components/html.md
user: login: margaretkennedy
body: ```suggestion
The `html_element` method allows you to specify any html `tag` along with any `children` and `attributes`.
```
created_at: 2025-04-08T15:57:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,57 @@
+# Escape Hatches
+
+`deephaven.ui` offers a versatile API for building comprehensive UI layouts. However, there may be scenarios where the provided API does not cover specific customization needs. In such cases, three "escape hatches" are available to enable additional customization of `deephaven.ui` components. 
+
+**Avoid using these options unless necessary**.
+
+1. [`ui.html`](../components/html.md) - Provides a set of functions for creating raw HTML elements.
+2. `UNSAFE_class_name` - Allows a custom A CSS class to apply to most `deephaven.ui` components.
+3. `UNSAFE_style` - Allows a custom A CSS style to apply to most `deephaven.ui` components.
+
+## ui.html
+
+`deephaven.ui` provides a large list of components for building a UI. If you need a UI element that is not available, you can use [`ui.html`](../components/html.md) to inject html tags into your UI.
+
+```python
+from deephaven import ui
+
+component_with_html = ui.view(
+    ui.heading("HTML inside a component"),
+    ui.html.div(
+        ui.html.h1("Welcome to Deephaven"),
+        ui.html.p("This is a custom HTML component."),
+        id="html_div",
+    ),
+)
+```
+
+## UNSAFE_class_name
+
+If a component's styling props are not sufficient, you can set the `UNSAFE_class_name` prop which set the html [`className`](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) attribute on the element. To do this, you will need to define a class name using `style` using `ui.html`.
path: plugins/ui/docs/creating-layouts/escape-hatches.md
user: login: margaretkennedy
body: ```suggestion
If a component's styling props are not sufficient, you can set the `UNSAFE_class_name` prop, which sets the HTML [`className`](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) attribute on the element. To do this, you must use `ui.html` to define a class name.
```
created_at: 2025-04-08T15:59:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,57 @@
+# Escape Hatches
+
+`deephaven.ui` offers a versatile API for building comprehensive UI layouts. However, there may be scenarios where the provided API does not cover specific customization needs. In such cases, three "escape hatches" are available to enable additional customization of `deephaven.ui` components. 
+
+**Avoid using these options unless necessary**.
+
+1. [`ui.html`](../components/html.md) - Provides a set of functions for creating raw HTML elements.
+2. `UNSAFE_class_name` - Allows a custom A CSS class to apply to most `deephaven.ui` components.
+3. `UNSAFE_style` - Allows a custom A CSS style to apply to most `deephaven.ui` components.
+
+## ui.html
+
+`deephaven.ui` provides a large list of components for building a UI. If you need a UI element that is not available, you can use [`ui.html`](../components/html.md) to inject html tags into your UI.
+
+```python
+from deephaven import ui
+
+component_with_html = ui.view(
+    ui.heading("HTML inside a component"),
+    ui.html.div(
+        ui.html.h1("Welcome to Deephaven"),
+        ui.html.p("This is a custom HTML component."),
+        id="html_div",
+    ),
+)
+```
+
+## UNSAFE_class_name
+
+If a component's styling props are not sufficient, you can set the `UNSAFE_class_name` prop which set the html [`className`](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) attribute on the element. To do this, you will need to define a class name using `style` using `ui.html`.
+
+```python
+from deephaven import ui
+
+unsafe_class_name = ui.panel(
+    ui.html.style(
+        """
+        .my_class { background: red !important;}
+        """
+    ),
+    ui.button("test", UNSAFE_class_name="my_class"),
+    ui.html.div("test", class_name="my_class"),
+)
+```
+
+## UNSAFE_style
+
+Rather than define a class name as above, you can use the `UNSAFE_style` prop which allows you to use a `dict` to set style props directly on a component.
path: plugins/ui/docs/creating-layouts/escape-hatches.md
user: login: margaretkennedy
body: ```suggestion
Rather than define a class name as above, you can use the `UNSAFE_style` prop, which allows you to set style props directly on a component using a `dict`.
```
created_at: 2025-04-08T16:00:03Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-08T14:01:57Z
body: [ui docs preview](https://preview.deephaven.io/core/ui/pr-1158/docs) (Available for 14 days)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-08T14:05:54Z
body: [ui docs preview](https://preview.deephaven.io/core/ui/pr-1158/docs) (Available for 14 days)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-08T14:07:31Z
body: [ui docs preview](https://preview.deephaven.io/core/ui/pr-1158/docs) (Available for 14 days)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-08T14:39:58Z
body: [ui docs preview](https://preview.deephaven.io/core/ui/pr-1158/docs) (Available for 14 days)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-08T16:28:37Z
body: [ui docs preview](https://preview.deephaven.io/core/ui/pr-1158/docs) (Available for 14 days)
author_association: NONE