mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-05 05:25:24 +02:00
Consolidate dropdown controllers (#600)
* Basic listbox and popover controllers with temporary example * Separate select and menu controllers
This commit is contained in:
parent
0a0289846e
commit
4f0b2de4ef
14 changed files with 298 additions and 150 deletions
|
@ -24,16 +24,28 @@
|
|||
<span class="<%= valuation_styles[:text_class] %>">(<%= lucide_icon(valuation_styles[:icon], class: "w-4 h-4 align-text-bottom inline") %> <%= valuation.trend.percent %>%)</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="relative w-[72px]" data-controller="dropdown">
|
||||
<button data-action="click->dropdown#toggleMenu" class="ml-auto flex items-center justify-center hover:bg-gray-50 w-8 h-8 rounded-lg">
|
||||
<%= lucide_icon("more-horizontal", class: "w-5 h-5 text-gray-500" ) %>
|
||||
<div class="relative w-[72px]" data-controller="menu">
|
||||
<button
|
||||
data-menu-target="button"
|
||||
class="ml-auto flex items-center justify-center hover:bg-gray-50 w-8 h-8 rounded-lg"
|
||||
>
|
||||
<%= lucide_icon("more-horizontal", class: "w-5 h-5 text-gray-500") %>
|
||||
</button>
|
||||
<div class="hidden absolute min-w-[200px] z-10 top-10 right-0 bg-white p-1 rounded-sm shadow-xs border border-alpha-black-25 w-fit" data-dropdown-target="menu">
|
||||
<%= link_to edit_valuation_path(valuation.original), class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<div
|
||||
data-menu-target="content"
|
||||
class="absolute min-w-[200px] z-10 top-10 right-0 bg-white p-1 rounded-sm shadow-xs border border-alpha-black-25 w-fit"
|
||||
>
|
||||
<%= link_to edit_valuation_path(valuation.original),
|
||||
class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("pencil-line", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Edit entry</span>
|
||||
<% end %>
|
||||
<%= link_to valuation_path(valuation.original), data: { turbo_method: :delete, turbo_confirm: { title: t('custom_turbo_confirm.history.title'), body: t('custom_turbo_confirm.history.body_html'), accept: t('custom_turbo_confirm.history.accept') } }, class: "text-red-600 flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= link_to valuation_path(valuation.original),
|
||||
data: { turbo_method: :delete,
|
||||
turbo_confirm: { title: t('custom_turbo_confirm.history.title'),
|
||||
body: t('custom_turbo_confirm.history.body_html'),
|
||||
accept: t('custom_turbo_confirm.history.accept') } },
|
||||
class: "text-red-600 flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("trash-2", class: "w-5 h-5 shrink-0") %>
|
||||
<span class="text-sm">Delete entry</span>
|
||||
<% end %>
|
||||
|
|
|
@ -17,13 +17,22 @@
|
|||
<%= lucide_icon("chevron-down", class: "w-5 h-5 text-gray-500") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative cursor-pointer" data-controller="dropdown">
|
||||
<div class="flex hover:bg-gray-100 p-2 rounded" data-action="click->dropdown#toggleMenu">
|
||||
<div class="relative cursor-pointer" data-controller="menu">
|
||||
<button data-menu-target="button" class="flex hover:bg-gray-100 p-2 rounded">
|
||||
<%= lucide_icon("more-horizontal", class: "w-5 h-5 text-gray-500") %>
|
||||
</div>
|
||||
<div class="absolute z-10 top-10 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs hidden" data-dropdown-target="menu">
|
||||
</button>
|
||||
<div data-menu-target="content" class="absolute z-10 top-10 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs hidden">
|
||||
<div class="w-48 px-3 text-sm leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<%= button_to account_path(@account), method: :delete, class: "block w-full py-2 text-red-600 hover:text-red-800 flex items-center", data: { turbo_confirm: { title: t("custom_turbo_confirm.account_destroy.title"), body: t("custom_turbo_confirm.account_destroy.body_html"), accept: t("custom_turbo_confirm.account_destroy.accept", name: @account.name) } } do %>
|
||||
<%= button_to account_path(@account),
|
||||
method: :delete,
|
||||
class: "block w-full py-2 text-red-600 hover:text-red-800 flex items-center",
|
||||
data: {
|
||||
turbo_confirm: {
|
||||
title: t("custom_turbo_confirm.account_destroy.title"),
|
||||
body: t("custom_turbo_confirm.account_destroy.body_html"),
|
||||
accept: t("custom_turbo_confirm.account_destroy.accept", name: @account.name)
|
||||
}
|
||||
} do %>
|
||||
<%= lucide_icon("trash-2", class: "w-5 h-5 mr-2") %> Delete account
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -45,7 +54,9 @@
|
|||
}
|
||||
%>
|
||||
</div>
|
||||
<%= render partial: "shared/period_dropdown", locals: { period: @period, path: account_path(@account) } %>
|
||||
<%= form_with url: account_path(@account), method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="h-96 flex items-center justify-center text-2xl font-bold">
|
||||
<%= render partial: "shared/line_chart", locals: { series: @balance_series } %>
|
||||
|
|
|
@ -29,17 +29,24 @@
|
|||
<div class="flex-col p-5 min-w-80">
|
||||
<div class="flex items-center justify-between">
|
||||
<%= link_to root_path do %>
|
||||
<%= image_tag 'logo.svg', alt: 'Maybe' %>
|
||||
<%= image_tag 'logo.svg', alt: 'Maybe', class: "h-[22px]" %>
|
||||
<% end %>
|
||||
<div class="relative cursor-pointer" data-controller="dropdown">
|
||||
<div class="flex" data-action="click->dropdown#toggleMenu">
|
||||
<div class="mr-1.5 text-white w-8 h-8 bg-gray-400 rounded-full flex items-center justify-center text-lg uppercase"><%= Current.user.email.first %></div>
|
||||
</div>
|
||||
<div class="absolute z-10 hidden w-screen px-2 mt-2 -translate-x-1/2 left-1/2 max-w-min" data-dropdown-target="menu">
|
||||
<div class="w-48 px-3 text-sm font-semibold leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<%= link_to "Settings", edit_settings_path, class: 'block p-2 hover:text-gray-600' %>
|
||||
<%= button_to "Log Out", session_path, method: :delete, class: 'block p-2 hover:text-gray-600' %>
|
||||
</div>
|
||||
<div class="relative" data-controller="menu">
|
||||
<button data-menu-target="button">
|
||||
<div class="text-white w-9 h-9 bg-gray-400 rounded-full flex items-center justify-center text-lg uppercase"><%= Current.user.email.first %></div>
|
||||
</button>
|
||||
<div
|
||||
data-menu-target="content"
|
||||
class="absolute min-w-[200px] z-10 top-10 right-0 bg-white p-1 rounded-sm shadow-xs border border-alpha-black-25 w-fit"
|
||||
>
|
||||
<%= link_to edit_settings_path, class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("pencil-line", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Settings</span>
|
||||
<% end %>
|
||||
<%= button_to session_path, method: :delete, class: "w-full text-gray-900 flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("log-out", class: "w-5 h-5 shrink-0") %>
|
||||
<span class="text-sm">Logout</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -79,7 +86,6 @@
|
|||
</main>
|
||||
</div>
|
||||
<%= turbo_frame_tag "modal" %>
|
||||
|
||||
<%= render 'shared/custom_confirm_modal' %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
}
|
||||
%>
|
||||
</div>
|
||||
<%= render partial: "shared/period_dropdown", locals: { period: @period, path: root_path } %>
|
||||
<%= form_with url: root_path, method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="h-96 flex items-center justify-center text-2xl font-bold">
|
||||
<%= render partial: "shared/line_chart", locals: { series: @net_worth_series } %>
|
||||
|
@ -70,7 +72,9 @@
|
|||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<p><%= t('.new') %></p>
|
||||
<% end %>
|
||||
<%= render partial: "shared/period_dropdown", locals: { period: @period, path: root_path } %>
|
||||
<%= form_with url: root_path, method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<div data-controller="currency-dropdown" class="absolute right-1 bottom-[10px] flex items-end">
|
||||
<button type="button" class="flex items-center justify-between w-20 px-2 py-1 text-sm rounded-lg hover:bg-gray-100 focus:bg-gray-100" data-action="click->currency-dropdown#toggleMenu">
|
||||
<div data-currency-dropdown-target="label"><%= f.object.currency %></div>
|
||||
<%# Example of how account currency value is updated %>
|
||||
<%= f.hidden_field :currency, data: {currency_dropdown_target: "input"} %>
|
||||
<%= lucide_icon("chevron-down", class: "text-gray-500 w-5 h-5" ) %>
|
||||
</button>
|
||||
<ul data-currency-dropdown-target="menu" class="hidden fixed p-1 bg-white rounded-[10px] min-w-[112px] z-50 translate-y-2 border border-alpha-black-100 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)]">
|
||||
<% options.each do |option| %>
|
||||
<li data-action="click->currency-dropdown#selectOption" data-currency-dropdown-target="option" data-value="<%= option %>" class="flex justify-between items-center p-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer rounded-lg <%= "bg-gray-100" if option === f.object.currency %>"><%= option %>
|
||||
<%= inline_svg_tag('icn-check.svg', class: "text-gray-500 fill-current #{'hidden'if option != f.object.currency}") %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<%# locals: (path:, period:) -%>
|
||||
<%= form_with url: path, method: :get, class: "flex items-center gap-4", html: { class: "" } do |f| %>
|
||||
<%= f.select :period, options_for_select([['7D', 'last_7_days'], ['1M', 'last_30_days'], ["1Y", "last_365_days"], ['All', 'all']], selected: params[:period]), {}, { class: "block w-full border border-alpha-black-100 shadow-xs rounded-lg text-sm py-2 pr-8 pl-2 cursor-pointer", onchange: "this.form.submit();" } %>
|
||||
<% end %>
|
16
app/views/shared/_period_select.html.erb
Normal file
16
app/views/shared/_period_select.html.erb
Normal file
|
@ -0,0 +1,16 @@
|
|||
<%# locals: (value: 'all') -%>
|
||||
<% options = [['7D', 'last_7_days'], ['1M', 'last_30_days'], ["1Y", "last_365_days"], ['All', 'all']] %>
|
||||
<div data-controller="select" data-select-active-class="bg-alpha-black-50" class="relative">
|
||||
<button type="button" data-select-target="button" class="flex items-center gap-1 w-full border border-alpha-black-100 shadow-xs rounded-lg text-sm p-2 cursor-pointer">
|
||||
<span data-select-target="buttonText" class="text-gray-900 text-sm"><%= options.find { |option| option[1] == value }[0] %></span>
|
||||
<%= lucide_icon("chevron-down", class: "w-5 h-5 text-gray-500") %>
|
||||
</button>
|
||||
<input type="hidden" name="period" value="<%= value %>" data-select-target="input" data-auto-submit-form-target="auto">
|
||||
<ul data-select-target="list" class="hidden absolute z-10 top-10 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs">
|
||||
<% options.each do |label, value| %>
|
||||
<li tabindex="0" data-select-target="option" data-action="click->select#selectOption" data-value="<%= value %>" class="text-sm text-gray-900 rounded-lg cursor-pointer hover:bg-alpha-black-50 px-5 py-1">
|
||||
<%= label %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
|
@ -1,14 +1,14 @@
|
|||
<%# locals: (transaction:) %>
|
||||
<div class="relative" data-controller="dropdown" data-dropdown-close-on-click-value="false">
|
||||
<div class="flex cursor-pointer" data-action="click->dropdown#toggleMenu">
|
||||
<div class="relative" data-controller="menu">
|
||||
<button data-menu-target="button" class="flex">
|
||||
<%= render partial: "shared/category_badge", locals: transaction.category.nil? ? {} : { name: transaction.category.name, color: transaction.category.color } %>
|
||||
</div>
|
||||
<div class="absolute z-10 hidden w-screen mt-2 max-w-min cursor-default" data-dropdown-target="menu">
|
||||
</button>
|
||||
<div data-menu-target="content" class="absolute z-10 hidden w-screen mt-2 max-w-min cursor-default">
|
||||
<div class="w-64 text-sm font-semibold leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<div class="flex flex-col" data-controller="list-filter">
|
||||
<div class="grow p-1.5">
|
||||
<div class="relative flex items-center bg-white border border-gray-200 rounded-lg">
|
||||
<input placeholder="Search" class="placeholder:text-sm placeholder:text-gray-500 font-normal h-10 relative pl-10 w-full border-none rounded-lg" data-list-filter-target="input" data-action="list-filter#filter" />
|
||||
<input placeholder="Search" type="search" class="placeholder:text-sm placeholder:text-gray-500 font-normal h-10 relative pl-10 w-full border-none rounded-lg" data-list-filter-target="input" data-action="list-filter#filter" />
|
||||
<%= lucide_icon("search", class: "w-5 h-5 text-gray-500 ml-2 absolute inset-0 transform top-1/2 -translate-y-1/2") %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<div class="grow">
|
||||
<%= render partial: "transactions/search_form/search_filter", locals: { form: form } %>
|
||||
</div>
|
||||
<div data-controller="dropdown" data-dropdown-close-on-click-value="false" class="relative">
|
||||
<button type="button" data-action="dropdown#toggleMenu" class="border border-gray-200 block h-full rounded-lg flex items-center gap-2 px-4">
|
||||
<div data-controller="menu" class="relative">
|
||||
<button data-menu-target="button" type="button" class="border border-gray-200 block h-full rounded-lg flex items-center gap-2 px-4">
|
||||
<%= lucide_icon("list-filter", class: "w-5 h-5 text-gray-500") %>
|
||||
<p class="text-sm font-medium text-gray-900">Filter</p>
|
||||
</button>
|
||||
<div class="hidden absolute z-10 top-12 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs min-w-[450px]" data-dropdown-target="menu">
|
||||
<div data-menu-target="content" class="absolute z-10 top-12 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs min-w-[450px]">
|
||||
<div data-controller="tabs" data-tabs-active-class="border-b-2 border-b-black text-gray-900" data-tabs-default-tab-value="txn-account-filter">
|
||||
<div class="flex items-center px-3 text-sm font-medium text-gray-500 gap-4 border-b border-b-alpha-black-50">
|
||||
<button class="py-2 border-b-2" type="button" data-id="txn-account-filter" data-tabs-target="btn" data-action="tabs#select">Account</button>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue