mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-10 07:55:21 +02:00
Add toggle field to custom form builder + Component
This commit is contained in:
parent
3f5522add3
commit
8aa6cb37d8
14 changed files with 101 additions and 58 deletions
|
@ -391,19 +391,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* Switches */
|
||||
.switch {
|
||||
@apply block bg-gray-100 w-9 h-5 rounded-full cursor-pointer;
|
||||
@apply after:content-[''] after:block after:absolute after:top-0.5 after:left-0.5 after:bg-white after:w-4 after:h-4 after:rounded-full;
|
||||
@apply after:transition-transform after:duration-300 after:ease-in-out;
|
||||
@apply peer-checked:bg-green-600 peer-checked:after:translate-x-4;
|
||||
@apply transition-colors duration-300;
|
||||
|
||||
@variant theme-dark {
|
||||
background-color: var(--color-gray-700);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltips */
|
||||
.tooltip {
|
||||
@apply hidden absolute;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# An extension to `button_to` helper. All options are passed through to the `button_to` helper with some additional
|
||||
# options available.
|
||||
class ButtonComponent < ButtonishComponent
|
||||
attr_reader :confirm
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# An extension to `link_to` helper. All options are passed through to the `link_to` helper with some additional
|
||||
# options available.
|
||||
class LinkComponent < ButtonishComponent
|
||||
attr_reader :frame
|
||||
|
||||
|
|
5
app/components/toggle_component.html.erb
Normal file
5
app/components/toggle_component.html.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
<div class="relative inline-block select-none">
|
||||
<%= hidden_field_tag name, unchecked_value, id: nil %>
|
||||
<%= check_box_tag name, checked_value, checked, class: "sr-only peer", disabled: disabled, id: id, **opts %>
|
||||
<%= label_tag name, " ".html_safe, class: label_classes, for: id %>
|
||||
</div>
|
26
app/components/toggle_component.rb
Normal file
26
app/components/toggle_component.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
class ToggleComponent < ViewComponent::Base
|
||||
attr_reader :id, :name, :checked, :disabled, :checked_value, :unchecked_value, :opts
|
||||
|
||||
def initialize(id:, name: nil, checked: false, disabled: false, checked_value: "1", unchecked_value: "0", **opts)
|
||||
@id = id
|
||||
@name = name
|
||||
@checked = checked
|
||||
@disabled = disabled
|
||||
@checked_value = checked_value
|
||||
@unchecked_value = unchecked_value
|
||||
@opts = opts
|
||||
end
|
||||
|
||||
def label_classes
|
||||
class_names(
|
||||
"block w-9 h-5 cursor-pointer",
|
||||
"rounded-full bg-gray-100 theme-dark:bg-gray-700",
|
||||
"transition-colors duration-300",
|
||||
"after:content-[''] after:block after:bg-white after:absolute after:rounded-full",
|
||||
"after:top-0.5 after:left-0.5 after:w-4 after:h-4",
|
||||
"after:transition-transform after:duration-300 after:ease-in-out",
|
||||
"peer-checked:bg-green-600 peer-checked:after:translate-x-4",
|
||||
"peer-disabled:opacity-70 peer-disabled:cursor-not-allowed"
|
||||
)
|
||||
end
|
||||
end
|
|
@ -48,6 +48,31 @@ class StyledFormBuilder < ActionView::Helpers::FormBuilder
|
|||
}
|
||||
end
|
||||
|
||||
# A custom styled "toggle" switch input. Underlying input is a `check_box` (uses same API)
|
||||
def toggle(method, options = {}, checked_value = "1", unchecked_value = "0")
|
||||
if object
|
||||
id = "#{object.id}_#{object_name}_#{method}"
|
||||
name = "#{object_name}[#{method}]"
|
||||
checked = object.send(method)
|
||||
else
|
||||
id = "#{method}_toggle_id"
|
||||
name = method
|
||||
checked = options[:checked]
|
||||
end
|
||||
|
||||
@template.render(
|
||||
ToggleComponent.new(
|
||||
id: id,
|
||||
name: name,
|
||||
checked: checked,
|
||||
disabled: options[:disabled],
|
||||
checked_value: checked_value,
|
||||
unchecked_value: unchecked_value,
|
||||
**options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def submit(value = nil, options = {})
|
||||
# Rails superclass logic to extract the submit text
|
||||
value, options = nil, value if value.is_a?(Hash)
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
</p>
|
||||
|
||||
<% unless account.scheduled_for_deletion? %>
|
||||
<%= render "shared/toggle_form", model: account, attribute: :is_active, turbo_frame: "_top" %>
|
||||
<%= styled_form_with model: account, data: { turbo_frame: "_top", controller: "auto-submit-form" } do |f| %>
|
||||
<%= f.toggle :is_active, { data: { auto_submit_form_target: "auto" } } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,14 +29,14 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div class="relative inline-block select-none ml-6">
|
||||
<%= check_box_tag :auto_fill, "1", params[:auto_fill].present?, class: "sr-only peer", data: {
|
||||
action: "change->budget-form#toggleAutoFill",
|
||||
budget_form_income_param: { key: "budget_expected_income", value: sprintf("%.2f", @budget.estimated_income) },
|
||||
budget_form_spending_param: { key: "budget_budgeted_spending", value: sprintf("%.2f", @budget.estimated_spending) }
|
||||
} %>
|
||||
<label for="auto_fill" class="switch"></label>
|
||||
</div>
|
||||
<%= render ToggleComponent.new(
|
||||
id: "auto_fill",
|
||||
data: {
|
||||
action: "change->budget-form#toggleAutoFill",
|
||||
budget_form_income_param: { key: "budget_expected_income", value: sprintf("%.2f", @budget.estimated_income) },
|
||||
budget_form_spending_param: { key: "budget_budgeted_spending", value: sprintf("%.2f", @budget.estimated_spending) }
|
||||
}
|
||||
) %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@
|
|||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<%= render "shared/toggle_form", model: rule, attribute: :active %>
|
||||
<%= styled_form_with model: rule, data: { controller: "auto-submit-form" } do |f| %>
|
||||
<%= f.toggle :active, { data: { auto_submit_form_target: "auto" } } %>
|
||||
<% end %>
|
||||
|
||||
<%= render MenuComponent.new do |menu| %>
|
||||
<% menu.with_item(variant: "link", text: "Edit", href: edit_rule_path(rule), icon: "pencil", data: { turbo_frame: "modal" }) %>
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
<p class="text-secondary text-sm"><%= t(".description") %></p>
|
||||
</div>
|
||||
|
||||
<%= styled_form_with model: Setting.new, url: settings_hosting_path, method: :patch, data: { controller: "auto-submit-form", "auto-submit-form-trigger-event-value" => "blur" } do |form| %>
|
||||
<div class="relative inline-block select-none">
|
||||
<%= form.check_box :require_invite_for_signup, class: "sr-only peer", "data-auto-submit-form-target": "auto", "data-autosubmit-trigger-event": "input", disabled: !Current.user.admin? %>
|
||||
<%= form.label :require_invite_for_signup, " ".html_safe, class: "switch" %>
|
||||
</div>
|
||||
<%= styled_form_with model: Setting.new,
|
||||
url: settings_hosting_path,
|
||||
method: :patch,
|
||||
data: { controller: "auto-submit-form", auto_submit_form_trigger_event_value: "change" } do |form| %>
|
||||
<%= form.toggle :require_invite_for_signup, { data: { auto_submit_form_target: "auto" } } %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
@ -19,11 +19,11 @@
|
|||
<p class="text-secondary text-sm"><%= t(".email_confirmation_description") %></p>
|
||||
</div>
|
||||
|
||||
<%= styled_form_with model: Setting.new, url: settings_hosting_path, method: :patch, data: { controller: "auto-submit-form", "auto-submit-form-trigger-event-value" => "blur" } do |form| %>
|
||||
<div class="relative inline-block select-none">
|
||||
<%= form.check_box :require_email_confirmation, class: "sr-only peer", "data-auto-submit-form-target": "auto", "data-autosubmit-trigger-event": "input", disabled: !Current.user.admin? %>
|
||||
<%= form.label :require_email_confirmation, " ".html_safe, class: "switch" %>
|
||||
</div>
|
||||
<%= styled_form_with model: Setting.new,
|
||||
url: settings_hosting_path,
|
||||
method: :patch,
|
||||
data: { controller: "auto-submit-form", auto_submit_form_trigger_event_value: "change" } do |form| %>
|
||||
<%= form.toggle :require_email_confirmation, { data: { auto_submit_form_target: "auto" } } %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<%# locals: (model:, attribute:, turbo_frame: nil) %>
|
||||
|
||||
<%= form_with model: model,
|
||||
namespace: model.id,
|
||||
class: "flex items-center",
|
||||
data: { controller: "auto-submit-form", turbo_frame: turbo_frame } do |form| %>
|
||||
<div class="relative inline-block select-none">
|
||||
<%= form.check_box attribute, { class: "sr-only peer", data: { "auto-submit-form-target": "auto" } } %>
|
||||
<%= form.label attribute, " ".html_safe, class: "switch" %>
|
||||
</div>
|
||||
<% end %>
|
|
@ -72,13 +72,7 @@
|
|||
<p class="text-secondary"><%= t(".exclude_subtitle") %></p>
|
||||
</div>
|
||||
|
||||
<div class="relative inline-block select-none">
|
||||
<%= f.check_box :excluded,
|
||||
class: "sr-only peer",
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
<label for="entry_excluded"
|
||||
class="switch"></label>
|
||||
</div>
|
||||
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
|
|
@ -109,13 +109,7 @@
|
|||
<p class="text-secondary">One-time transactions will be excluded from certain budgeting calculations and reports to help you see what's really important.</p>
|
||||
</div>
|
||||
|
||||
<div class="relative inline-block select-none">
|
||||
<%= f.check_box :excluded,
|
||||
class: "sr-only peer",
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
<label for="entry_excluded"
|
||||
class="switch"></label>
|
||||
</div>
|
||||
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
|
15
test/components/previews/toggle_component_preview.rb
Normal file
15
test/components/previews/toggle_component_preview.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class ToggleComponentPreview < ViewComponent::Preview
|
||||
# @param disabled toggle
|
||||
def default(disabled: false)
|
||||
render(
|
||||
ToggleComponent.new(
|
||||
id: "toggle-component-id",
|
||||
name: "toggle-component-name",
|
||||
checked: false,
|
||||
disabled: disabled,
|
||||
checked_value: "on",
|
||||
unchecked_value: "off"
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue