Skip to content

Commit

Permalink
refactor(tooltip): support tooltip positions - add to button and tool…
Browse files Browse the repository at this point in the history
…tip-icon components
  • Loading branch information
aarthy-dk committed Nov 7, 2024
1 parent a67078b commit 41b25c1
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 62 deletions.
6 changes: 6 additions & 0 deletions testgen/ui/components/frontend/css/shared.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ body {
--disabled-text-color: #00000042;
--caption-text-color: rgba(49, 51, 63, 0.6); /* Match Streamlit's caption color */
--border-color: rgba(0, 0, 0, .12);
--tooltip-color: #333d;
--dk-card-background: #fff;

--sidebar-background-color: white;
Expand Down Expand Up @@ -88,6 +89,11 @@ body {
}
}

.hidden {
display: none !important;
}


/* Table styles */
.table {
background-color: var(--dk-card-background);
Expand Down
29 changes: 21 additions & 8 deletions testgen/ui/components/frontend/js/components/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import { emitEvent, enforceElementWidth, getValue, loadStylesheet } from '../utils.js';
import van from '../van.min.js';
import { Streamlit } from '../streamlit.js';
import { Tooltip } from './tooltip.js';

const { button, i, span } = van.tags;
const BUTTON_TYPE = {
Expand Down Expand Up @@ -44,21 +45,29 @@ const Button = (/** @type Properties */ props) => {
if (width) {
enforceElementWidth(window.frameElement, width);
}
}

if (props.tooltip) {
window.frameElement.parentElement.setAttribute('data-tooltip', props.tooltip.val);
window.frameElement.parentElement.setAttribute('data-tooltip-position', props.tooltipPosition.val);
if (props.tooltip) {
window.frameElement.parentElement.setAttribute('data-tooltip', props.tooltip.val);
window.frameElement.parentElement.setAttribute('data-tooltip-position', props.tooltipPosition.val);
}
}

const onClickHandler = props.onclick || (() => emitEvent('ButtonClicked'));
const showTooltip = van.state(false);

return button(
{
class: `tg-button tg-${buttonType}-button tg-${getValue(props.color) ?? 'basic'}-button ${buttonType !== 'icon' && isIconOnly ? 'tg-icon-button' : ''}`,
style: () => `width: ${isIconOnly ? '' : (width ?? '100%')}; ${getValue(props.style)}`,
onclick: onClickHandler,
disabled: props.disabled,
onmouseenter: props.tooltip ? (() => showTooltip.val = true) : undefined,
onmouseleave: props.tooltip ? (() => showTooltip.val = false) : undefined,
},
props.tooltip ? Tooltip({
text: props.tooltip,
show: showTooltip,
position: props.tooltipPosition,
}) : undefined,
span({class: 'tg-button-focus-state-indicator'}, ''),
props.icon ? i({class: 'material-symbols-rounded'}, props.icon) : undefined,
!isIconOnly ? span(props.label) : undefined,
Expand All @@ -71,7 +80,6 @@ button.tg-button {
height: 40px;
position: relative;
overflow: hidden;
display: flex;
flex-direction: row;
Expand All @@ -88,6 +96,11 @@ button.tg-button {
font-size: 14px;
}
button.tg-button .tg-button-focus-state-indicator {
border-radius: inherit;
overflow: hidden;
}
button.tg-button .tg-button-focus-state-indicator::before {
content: "";
opacity: 0;
Expand All @@ -113,15 +126,15 @@ button.tg-button:has(span) {
}
button.tg-button:not(.tg-icon-button):has(span):has(i) {
padding-left: 8px;
padding-left: 12px;
}
button.tg-button[disabled] {
color: var(--disabled-text-color);
cursor: not-allowed;
}
button.tg-button.tg-icon-button > i {
button.tg-button > i {
font-size: 18px;
}
Expand Down
157 changes: 157 additions & 0 deletions testgen/ui/components/frontend/js/components/tooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Code modified from vanjs-ui
// https://www.npmjs.com/package/vanjs-ui
// https://cdn.jsdelivr.net/npm/vanjs-ui@0.10.0/dist/van-ui.nomodule.js

/**
* @typedef Properties
* @type {object}
* @property {string} text
* @property {boolean} show
* @property {('top-left' | 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left')?} position
*/
import van from '../van.min.js';
import { getValue, loadStylesheet } from '../utils.js';

const { div, span } = van.tags;
const defaultPosition = 'top';

const Tooltip = (/** @type Properties */ props) => {
loadStylesheet('tooltip', stylesheet);

return span(
{
class: () => `tg-tooltip ${getValue(props.position) || defaultPosition} ${getValue(props.show) ? '' : 'hidden'}`,
style: () => `opacity: ${getValue(props.show) ? 1 : 0};`,
},
props.text,
div({ class: 'tg-tooltip--triangle' }),
);
};

const stylesheet = new CSSStyleSheet();
stylesheet.replace(`
.tg-tooltip {
width: max-content;
max-width: 400px;
position: absolute;
z-index: 1;
border-radius: 4px;
background-color: var(--tooltip-color);
padding: 4px 8px;
color: white;
font-size: 13px;
font-family: 'Roboto', 'Helvetica Neue', sans-serif;
text-align: center;
text-wrap: wrap;
transition: opacity 0.3s;
}
.tg-tooltip--triangle {
width: 0;
height: 0;
position: absolute;
border: solid transparent;
}
.tg-tooltip.top-left {
right: 50%;
bottom: 125%;
transform: translateX(20px);
}
.top-left .tg-tooltip--triangle {
bottom: -5px;
right: 20px;
margin-right: -5px;
border-width: 5px 5px 0;
border-top-color: var(--tooltip-color);
}
.tg-tooltip.top {
left: 50%;
bottom: 125%;
transform: translateX(-50%);
}
.top .tg-tooltip--triangle {
bottom: -5px;
left: 50%;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: var(--tooltip-color);
}
.tg-tooltip.top-right {
left: 50%;
bottom: 125%;
transform: translateX(-20px);
}
.top-right .tg-tooltip--triangle {
bottom: -5px;
left: 20px;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: var(--tooltip-color);
}
.tg-tooltip.right {
left: 125%;
}
.right .tg-tooltip--triangle {
top: 50%;
left: -5px;
margin-top: -5px;
border-width: 5px 5px 5px 0;
border-right-color: var(--tooltip-color);
}
.tg-tooltip.bottom-right {
left: 50%;
top: 125%;
transform: translateX(-20px);
}
.bottom-right .tg-tooltip--triangle {
top: -5px;
left: 20px;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: var(--tooltip-color);
}
.tg-tooltip.bottom {
top: 125%;
left: 50%;
transform: translateX(-50%);
}
.bottom .tg-tooltip--triangle {
top: -5px;
left: 50%;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: var(--tooltip-color);
}
.tg-tooltip.bottom-left {
right: 50%;
top: 125%;
transform: translateX(20px);
}
.bottom-left .tg-tooltip--triangle {
top: -5px;
right: 20px;
margin-right: -5px;
border-width: 0 5px 5px;
border-bottom-color: var(--tooltip-color);
}
.tg-tooltip.left {
right: 125%;
}
.left .tg-tooltip--triangle {
top: 50%;
right: -5px;
margin-top: -5px;
border-width: 5px 0 5px 5px;
border-left-color: var(--tooltip-color);
}
`);

export { Tooltip };
45 changes: 45 additions & 0 deletions testgen/ui/components/frontend/js/components/tooltip_icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @typedef Properties
* @type {object}
* @property {string} icon
* @property {number?} iconSize
* @property {string} tooltip
* @property {('top-left' | 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left')?} tooltipPosition
* @property {string} classes
*/
import { getValue, loadStylesheet } from '../utils.js';
import van from '../van.min.js';
import { Tooltip } from './tooltip.js';

const { i } = van.tags;
const defaultIconSize = 20;

const TooltipIcon = (/** @type Properties */ props) => {
loadStylesheet('tooltipIcon', stylesheet);
const showTooltip = van.state(false);

return i(
{
class: () => `material-symbols-rounded tg-tooltip-icon text-secondary ${getValue(props.classes)}`,
style: () => `font-size: ${getValue(props.iconSize) || defaultIconSize}px;`,
onmouseenter: () => showTooltip.val = true,
onmouseleave: () => showTooltip.val = false,
},
props.icon,
Tooltip({
text: props.tooltip,
show: showTooltip,
position: props.tooltipPosition,
}),
);
};

const stylesheet = new CSSStyleSheet();
stylesheet.replace(`
.tg-tooltip-icon {
position: relative;
cursor: default;
}
`);

export { TooltipIcon };
2 changes: 1 addition & 1 deletion testgen/ui/components/frontend/js/pages/profiling_runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @property {array} items
*/
import van from '../van.min.js';
import { Tooltip } from '../van-tooltip.js';
import { Tooltip } from '../components/tooltip.js';
import { SummaryBar } from '../components/summary_bar.js';
import { Link } from '../components/link.js';
import { Button } from '../components/button.js';
Expand Down
2 changes: 1 addition & 1 deletion testgen/ui/components/frontend/js/pages/test_runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @property {array} items
*/
import van from '../van.min.js';
import { Tooltip } from '../van-tooltip.js';
import { Tooltip } from '../components/tooltip.js';
import { SummaryBar } from '../components/summary_bar.js';
import { Link } from '../components/link.js';
import { Button } from '../components/button.js';
Expand Down
52 changes: 0 additions & 52 deletions testgen/ui/components/frontend/js/van-tooltip.js

This file was deleted.

0 comments on commit 41b25c1

Please sign in to comment.