mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-02 20:15:22 +02:00
Add stimulus tooltip controller (#1065)
* Add Tooltip Stimulus controller * Add test for tooltip * Remove comma * Normalize translations * Use floating-ui instead popper * Use component classes * Increase cross axis value * Cleanup * Update app/views/accounts/show.html.erb Use correct tailwind class Co-authored-by: Zach Gollwitzer <zach.gollwitzer@gmail.com> Signed-off-by: Tony Vincent <tonyvince7@gmail.com> * Use default values for options * Remove tooltip global variable * Add arrow target * Remove unused method --------- Signed-off-by: Tony Vincent <tonyvince7@gmail.com> Co-authored-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>
This commit is contained in:
parent
6e74414cb2
commit
f315370512
11 changed files with 164 additions and 4 deletions
|
@ -4,11 +4,11 @@
|
|||
|
||||
/* Reset rules, default styles applied to plain HTML */
|
||||
@layer base {
|
||||
details > summary::-webkit-details-marker {
|
||||
details>summary::-webkit-details-marker {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
details>summary {
|
||||
@apply list-none;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
|||
@apply w-full cursor-pointer rounded-lg bg-black p-3 text-center text-white hover:bg-gray-700;
|
||||
}
|
||||
|
||||
input:checked + label + .toggle-switch-dot {
|
||||
input:checked+label+.toggle-switch-dot {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,10 @@
|
|||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
@apply hidden absolute;
|
||||
}
|
||||
}
|
||||
|
||||
/* Small, single purpose classes that should take precedence over other styles */
|
||||
|
|
74
app/javascript/controllers/tooltip_controller.js
Normal file
74
app/javascript/controllers/tooltip_controller.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { Controller } from '@hotwired/stimulus'
|
||||
import {
|
||||
computePosition,
|
||||
flip,
|
||||
shift,
|
||||
offset,
|
||||
arrow
|
||||
} from '@floating-ui/dom';
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["arrow", "tooltip"];
|
||||
static values = {
|
||||
placement: { type: String, default: "top" },
|
||||
offset: { type: Number, default: 10 },
|
||||
crossAxis: { type: Number, default: 0 },
|
||||
alignmentAxis: { type: Number, default: null },
|
||||
};
|
||||
|
||||
connect() {
|
||||
this.element.addEventListener("mouseenter", this.showTooltip);
|
||||
this.element.addEventListener("mouseleave", this.hideTooltip);
|
||||
this.element.addEventListener("focus", this.showTooltip);
|
||||
this.element.addEventListener("blur", this.hideTooltip);
|
||||
};
|
||||
|
||||
showTooltip = () => {
|
||||
this.tooltipTarget.style.display = 'block';
|
||||
this.#update();
|
||||
};
|
||||
|
||||
hideTooltip = () => {
|
||||
this.tooltipTarget.style.display = '';
|
||||
};
|
||||
|
||||
disconnect() {
|
||||
this.element.removeEventListener("mouseenter", this.showTooltip);
|
||||
this.element.removeEventListener("mouseleave", this.hideTooltip);
|
||||
this.element.removeEventListener("focus", this.showTooltip);
|
||||
this.element.removeEventListener("blur", this.hideTooltip);
|
||||
};
|
||||
|
||||
#update() {
|
||||
computePosition(this.element, this.tooltipTarget, {
|
||||
placement: this.placementValue,
|
||||
middleware: [
|
||||
offset({ mainAxis: this.offsetValue, crossAxis: this.crossAxisValue, alignmentAxis: this.alignmentAxisValue }),
|
||||
flip(),
|
||||
shift({ padding: 5 }),
|
||||
arrow({ element: this.arrowTarget }),
|
||||
],
|
||||
}).then(({ x, y, placement, middlewareData }) => {
|
||||
Object.assign(this.tooltipTarget.style, {
|
||||
left: `${x}px`,
|
||||
top: `${y}px`,
|
||||
});
|
||||
|
||||
const { x: arrowX, y: arrowY } = middlewareData.arrow;
|
||||
const staticSide = {
|
||||
top: 'bottom',
|
||||
right: 'left',
|
||||
bottom: 'top',
|
||||
left: 'right',
|
||||
}[placement.split('-')[0]];
|
||||
|
||||
Object.assign(this.arrowTarget.style, {
|
||||
left: arrowX != null ? `${arrowX}px` : '',
|
||||
top: arrowY != null ? `${arrowY}px` : '',
|
||||
right: '',
|
||||
bottom: '',
|
||||
[staticSide]: '-4px',
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
26
app/views/accounts/_tooltip.html.erb
Normal file
26
app/views/accounts/_tooltip.html.erb
Normal file
|
@ -0,0 +1,26 @@
|
|||
<%# locals: (account:) -%>
|
||||
<div data-controller="tooltip" data-tooltip-target="element" data-tooltip-placement-value="right" data-tooltip-offset-value=10 data-tooltip-cross-axis-value=50>
|
||||
<%= lucide_icon("info", class: "w-4 h-4 shrink-0 text-gray-500") %>
|
||||
<div id="tooltip" role="tooltip" data-tooltip-target="tooltip" class="tooltip bg-gray-700 text-sm p-2 rounded w-64">
|
||||
<div class="text-white">
|
||||
<%= t(".total_value_tooltip") %>
|
||||
</div>
|
||||
<div class="flex pt-3">
|
||||
<div class="text-gray-300">
|
||||
<%= t(".holdings") %>
|
||||
</div>
|
||||
<div class="text-white ml-auto">
|
||||
<%= tag.p format_money(account.investment.holdings_value, precision: 0) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="text-gray-300">
|
||||
<%= t(".cash") %>
|
||||
</div>
|
||||
<div class="text-white ml-auto">
|
||||
<%= tag.p format_money(account.balance_money, precision: 0) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-tooltip-target="arrow"></div>
|
||||
</div>
|
|
@ -52,7 +52,12 @@
|
|||
<div class="bg-white shadow-xs rounded-xl border border-alpha-black-25 rounded-lg">
|
||||
<div class="p-4 flex justify-between">
|
||||
<div class="space-y-2">
|
||||
<%= tag.p t(".total_value"), class: "text-sm font-medium text-gray-500" %>
|
||||
<div class="flex items-center gap-1">
|
||||
<div>
|
||||
<%= tag.p t(".total_value"), class: "text-sm font-medium text-gray-500" %>
|
||||
</div>
|
||||
<%= render "tooltip", account: @account if @account.investment? %>
|
||||
</div>
|
||||
<%= tag.p format_money(@account.value, precision: 0), class: "text-gray-900 text-3xl font-medium" %>
|
||||
<div>
|
||||
<% if @series.trend.direction.flat? %>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue