Skip to content

Commit

Permalink
fix: contextual_help uses heading, content, footer props (deephaven#945)
Browse files Browse the repository at this point in the history
- Fixes deephaven#926 
- Auto-wraps `heading`, `content`, and `footer` props in their
respective component

BREAKING CHANGE: `ui.contextual_help`'s signature replaces the
`*children` prop with `heading`, `content`, and `footer` props, in that
order. In parity with [React Spectrum
docs](https://react-spectrum.adobe.com/react-spectrum/ContextualHelp.html#:~:text=Each%20of%20these%20components%20are%20required%20in%20a%20Spectrum%20compliant%20ContextualHelp%20except%20for%20Footer%20since%20including%20a%20link%20is%20optional.),
the `heading` and `content` props are required and `footer` is optional.

Here are some examples of usages and how they might change:
```python
# This is still valid
old = ui.contextual_help(
    ui.heading("My Heading"),
    ui.content("My content"),
    ui.footer("My footer")
)
```
```python
# This is invalid
old = ui.contextual_help(ui.content("My content"))
# You must explicitly set heading to None
new = ui.contextual_help(None, ui.content("My content"))
```
  • Loading branch information
wusteven815 authored Oct 21, 2024
1 parent 7f03d95 commit d7bcc22
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 8 deletions.
13 changes: 10 additions & 3 deletions plugins/ui/src/deephaven/ui/components/contextual_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@


def contextual_help(
*children: Any,
heading: Any,
content: Any,
footer: Any = None,
*,
variant: ContextualHelperVariant | None = "help",
placement: Placement | None = "bottom start",
is_open: bool | None = None,
Expand Down Expand Up @@ -75,7 +78,9 @@ def contextual_help(
"""
A contextual help is a quiet action button that triggers an informational popover.
Args:
*children: The children of the contextual help popover.
heading: The heading of the popover.
content: The content of the popover.
footer: The footer of the popover.
variant: Indicates whether contents are informative or provides helpful guidance.
placement: The placement of the popover relative to the action button.
is_open: Whether the popover is open by default (controlled).
Expand Down Expand Up @@ -132,7 +137,9 @@ def contextual_help(
"""
return component_element(
"ContextualHelp",
*children,
heading=heading,
content=content,
footer=footer,
variant=variant,
placement=placement,
is_open=is_open,
Expand Down
46 changes: 46 additions & 0 deletions plugins/ui/src/js/src/elements/ContextualHelp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
ContextualHelp as DHCContextualHelp,
ContextualHelpProps as DHCContextualHelpProps,
Heading,
Content,
Footer,
} from '@deephaven/components';
import { isElementOfType } from '@deephaven/react-hooks';
import { ReactNode } from 'react';

export type SerializedContextualHelpProps = Omit<
DHCContextualHelpProps,
'children'
> & {
heading: ReactNode;
content: ReactNode;
footer?: ReactNode;
};

export function ContextualHelp(
props: SerializedContextualHelpProps
): JSX.Element {
const { heading, content, footer, ...otherProps } = props;

return (
/* eslint-disable-next-line react/jsx-props-no-spreading */
<DHCContextualHelp {...otherProps}>
{heading != null &&
(isElementOfType(heading, Heading) ? (
heading
) : (
<Heading>{heading}</Heading>
))}
{content != null &&
(isElementOfType(content, Content) ? (
content
) : (
<Content>{content}</Content>
))}
{footer != null &&
(isElementOfType(footer, Footer) ? footer : <Footer>{footer}</Footer>)}
</DHCContextualHelp>
);
}

export default ContextualHelp;
1 change: 1 addition & 0 deletions plugins/ui/src/js/src/elements/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './ActionGroup';
export * from './Button';
export * from './Calendar';
export * from './ComboBox';
export * from './ContextualHelp';
export * from './DateField';
export * from './DatePicker';
export * from './DateRangePicker';
Expand Down
6 changes: 2 additions & 4 deletions plugins/ui/src/js/src/widget/WidgetUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
SpectrumCheckbox as Checkbox,
CheckboxGroup,
Content,
ContextualHelp,
Heading,
Item,
ListActionGroup,
Expand Down Expand Up @@ -51,6 +50,7 @@ import {
Button,
Calendar,
ComboBox,
ContextualHelp,
DateField,
DatePicker,
DateRangePicker,
Expand Down Expand Up @@ -182,9 +182,7 @@ export function getComponentForElement(element: ElementNode): React.ReactNode {
}
if (props?.contextualHelp != null && isPrimitive(props.contextualHelp)) {
props.contextualHelp = (
<ContextualHelp>
<Content>{props.contextualHelp}</Content>
</ContextualHelp>
<ContextualHelp heading={null} content={props.contextualHelp} />
);
}
return <Component {...props} />;
Expand Down
2 changes: 1 addition & 1 deletion tests/app.d/ui_render_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def ui_components1():
ui.column("Column child A", "Column child B", "Column child C"),
# TODO: #201 ui.combo_box("Combo Box"),
ui.content("Content"),
ui.contextual_help("Contextual Help"),
ui.contextual_help("Contextual Help", "Content"),
ui.date_picker(label="Date Picker", value="2021-01-01"),
ui.date_range_picker(
label="Date Range Picker",
Expand Down

0 comments on commit d7bcc22

Please sign in to comment.