Skip to content

Commit

Permalink
feat: support tooltip via context
Browse files Browse the repository at this point in the history
Closes #261
  • Loading branch information
smbea committed Jul 20, 2023
1 parent 086f3a4 commit 3e9f698
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 50 deletions.
80 changes: 54 additions & 26 deletions src/PropertiesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
ErrorsContext,
EventContext,
LayoutContext,
PropertiesPanelContext
PropertiesPanelContext,
TooltipContext
} from './context';

import { useEvent } from './hooks';
Expand All @@ -33,6 +34,8 @@ const DEFAULT_LAYOUT = {};

const DEFAULT_DESCRIPTION = {};

const DEFAULT_TOOLTIP = {};


/**
* @typedef { {
Expand Down Expand Up @@ -112,6 +115,7 @@ export default function PropertiesPanel(props) {
layoutChanged,
descriptionConfig,
descriptionLoaded,
tooltipConfig,
eventBus
} = props;

Expand Down Expand Up @@ -167,6 +171,21 @@ export default function PropertiesPanel(props) {
getDescriptionForId
};

// set-up tooltip context
const tooltip = useMemo(() => createTooltipContext(tooltipConfig), [ tooltipConfig ]);

const getTooltipForId = (id, element) => {
if (id === 'taskDefinitionType') {
tooltip[id];

Check warning on line 179 in src/PropertiesPanel.js

View check run for this annotation

Codecov / codecov/patch

src/PropertiesPanel.js#L178-L179

Added lines #L178 - L179 were not covered by tests
}
return tooltip[id] && tooltip[id](element);

Check warning on line 181 in src/PropertiesPanel.js

View check run for this annotation

Codecov / codecov/patch

src/PropertiesPanel.js#L181

Added line #L181 was not covered by tests
};

const tooltipContext = {
tooltip,
getTooltipForId
};

const [ errors, setErrors ] = useState({});

const onSetErrors = ({ errors }) => setErrors(errors);
Expand Down Expand Up @@ -199,32 +218,34 @@ export default function PropertiesPanel(props) {
<PropertiesPanelContext.Provider value={ propertiesPanelContext }>
<ErrorsContext.Provider value={ errorsContext }>
<DescriptionContext.Provider value={ descriptionContext }>
<LayoutContext.Provider value={ layoutContext }>
<EventContext.Provider value={ eventContext }>
<div class="bio-properties-panel">
<Header
element={ element }
headerProvider={ headerProvider } />
<div class="bio-properties-panel-scroll-container">
{
groups.map(group => {
const {
component: Component = Group,
id
} = group;

return (
<Component
{ ...group }
key={ id }
element={ element } />
);
})
}
<TooltipContext.Provider value={ tooltipContext }>
<LayoutContext.Provider value={ layoutContext }>
<EventContext.Provider value={ eventContext }>
<div class="bio-properties-panel">
<Header
element={ element }
headerProvider={ headerProvider } />
<div class="bio-properties-panel-scroll-container">
{
groups.map(group => {
const {
component: Component = Group,
id
} = group;

return (
<Component
{ ...group }
key={ id }
element={ element } />
);
})
}
</div>
</div>
</div>
</EventContext.Provider>
</LayoutContext.Provider>
</EventContext.Provider>
</LayoutContext.Provider>
</TooltipContext.Provider>
</DescriptionContext.Provider>
</ErrorsContext.Provider>
</PropertiesPanelContext.Provider>
Expand All @@ -248,6 +269,13 @@ function createDescriptionContext(overrides = {}) {
};
}

function createTooltipContext(overrides = {}) {
return {
...DEFAULT_TOOLTIP,
...overrides
};
}

// hooks //////////////////

/**
Expand Down
5 changes: 3 additions & 2 deletions src/components/entries/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function Checkbox(props) {
checked={ localValue }
disabled={ disabled } />
<label for={ prefixId(id) } class="bio-properties-panel-label">
<Tooltip value={ tooltip } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{ label }
</Tooltip>
</label>
Expand Down Expand Up @@ -109,7 +109,8 @@ export default function CheckboxEntry(props) {
onFocus={ onFocus }
onBlur={ onBlur }
value={ value }
tooltip={ tooltip } />
tooltip={ tooltip }
element={ element } />
{ error && <div class="bio-properties-panel-error">{ error }</div> }
<Description forId={ id } element={ element } value={ description } />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/entries/FEEL/Feel.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ function FeelTextfield(props) {
{ 'feel-active': feelActive }
) }>
<label for={ prefixId(id) } class="bio-properties-panel-label" onClick={ () => setFocus() }>
<Tooltip value={ tooltip } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{label}
</Tooltip>
<FeelIcon
Expand Down
5 changes: 3 additions & 2 deletions src/components/entries/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function Select(props) {
return (
<div class="bio-properties-panel-select">
<label for={ prefixId(id) } class="bio-properties-panel-label">
<Tooltip value={ tooltip } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{label}
</Tooltip>
</label>
Expand Down Expand Up @@ -189,7 +189,8 @@ export default function SelectEntry(props) {
onBlur={ onBlur }
options={ options }
disabled={ disabled }
tooltip={ tooltip } />
tooltip={ tooltip }
element={ element } />
{ error && <div class="bio-properties-panel-error">{ error }</div> }
<Description forId={ id } element={ element } value={ description } />
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/entries/TextArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function TextArea(props) {
return (
<div class="bio-properties-panel-textarea">
<label for={ prefixId(id) } class="bio-properties-panel-label">
<Tooltip value={ tooltip } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{ label }
</Tooltip>
</label>
Expand Down Expand Up @@ -182,7 +182,8 @@ export default function TextAreaEntry(props) {
monospace={ monospace }
disabled={ disabled }
autoResize={ autoResize }
tooltip={ tooltip } />
tooltip={ tooltip }
element={ element } />
{ error && <div class="bio-properties-panel-error">{ error }</div> }
<Description forId={ id } element={ element } value={ description } />
</div>
Expand Down
7 changes: 3 additions & 4 deletions src/components/entries/TextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Tooltip from './Tooltip';
import {
useEffect,
useMemo,
useRef,
useState
} from 'preact/hooks';

Expand Down Expand Up @@ -34,7 +33,6 @@ function Textfield(props) {
const [ localValue, setLocalValue ] = useState(value || '');

const ref = useShowEntryEvent(id);
const labelRef = useRef(null);

const handleInputCallback = useMemo(() => {
return debounce(({ target }) => onInput(target.value.length ? target.value : undefined));
Expand All @@ -56,7 +54,7 @@ function Textfield(props) {
return (
<div class="bio-properties-panel-textfield">
<label for={ prefixId(id) } class="bio-properties-panel-label">
<Tooltip value={ tooltip } refElement={ labelRef } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{ label }
</Tooltip>
</label>
Expand Down Expand Up @@ -153,7 +151,8 @@ export default function TextfieldEntry(props) {
onFocus={ onFocus }
onBlur={ onBlur }
value={ value }
tooltip={ tooltip } />
tooltip={ tooltip }
element={ element } />
{ error && <div class="bio-properties-panel-error">{ error }</div> }
<Description forId={ id } element={ element } value={ description } />
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/entries/ToggleSwitch.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function ToggleSwitch(props) {
) }>
<label class="bio-properties-panel-label"
for={ prefixId(id) }>
<Tooltip value={ tooltip } labelId={ prefixId(id) }>
<Tooltip value={ tooltip } forId={ id } element={ props.element }>
{ label }
</Tooltip>
</label>
Expand Down Expand Up @@ -113,7 +113,8 @@ export default function ToggleSwitchEntry(props) {
onBlur={ onBlur }
switcherLabel={ switcherLabel }
inline={ inline }
tooltip={ tooltip } />
tooltip={ tooltip }
element={ element } />
<Description forId={ id } element={ element } value={ description } />
</div>
);
Expand Down
27 changes: 20 additions & 7 deletions src/components/entries/Tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,34 @@ import {
useEffect,
useState
} from 'react';
import { useTooltipContext } from '../../hooks/useTooltipContext';

/**
* @param {Object} props
* @param {String} props.labelId
* @param {String} props.forId
* @param {String} props.value
*/
export default function TooltipWrapper(props) {
const {
forId,
element
} = props;

const contextDescription = useTooltipContext(forId, element);

const value = props.value || contextDescription;

if (!props.value) {
if (!value) {
return props.children;
}

return <Tooltip { ...props } />;
return <Tooltip { ...props } value={ value } forId={ prefixId(forId) } />;
}

function Tooltip(props) {
const {
value,
labelId
forId,
value
} = props;

const [ visible, setShow ] = useState(false);
Expand Down Expand Up @@ -105,7 +114,7 @@ function Tooltip(props) {
class="bio-properties-panel-tooltip"
role="tooltip"
id="bio-properties-panel-tooltip"
aria-labelledby={ labelId }
aria-labelledby={ forId }
style={ getTooltipPosition(wrapperRef.current) }
ref={ tooltipRef }
onClick={ (e)=> e.stopPropagation() }
Expand Down Expand Up @@ -139,4 +148,8 @@ function getTooltipPosition(refElement) {

function isHovered(element) {
return element.matches(':hover');
}
}

function prefixId(id) {
return `bio-properties-panel-${ id }`;
}
10 changes: 10 additions & 0 deletions src/context/TooltipContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {
createContext
} from 'preact';

const TooltipContext = createContext({
tooltip: {},
getTooltipForId: () => {}
});

export default TooltipContext;
1 change: 1 addition & 0 deletions src/context/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { default as ErrorsContext } from './ErrorsContext';
export { default as EventContext } from './EventContext';
export { default as LayoutContext } from './LayoutContext';
export { default as PropertiesPanelContext } from './LayoutContext';
export { default as TooltipContext } from './TooltipContext';
1 change: 1 addition & 0 deletions src/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { usePrevious } from './usePrevious';
export { useShowEntryEvent } from './useShowEntryEvent';
export { useStickyIntersectionObserver } from './useStickyIntersectionObserver';
export { useStaticCallback } from './useStaticCallback';
export { useTooltipContext } from './useTooltipContext';
30 changes: 30 additions & 0 deletions src/hooks/useTooltipContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
useContext
} from 'preact/hooks';

import {
TooltipContext
} from '../context';

/**
* Accesses the global TooltipContext and returns a tooltip for a given id and element.
*
* @example
* ```jsx
* function TextField(props) {
* const tooltip = useTooltipContext('input1', element);
* }
* ```
*
* @param {string} id
* @param {object} element
*
* @returns {string}
*/
export function useTooltipContext(id, element) {
const {
getTooltipForId
} = useContext(TooltipContext);

return getTooltipForId(id, element);
}
Loading

0 comments on commit 3e9f698

Please sign in to comment.