Skip to content

Commit

Permalink
add extra_class styling option for clear buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmarcon committed Feb 6, 2024
1 parent 23d3976 commit a054017
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
* add slot to render custom clear button
* add option to extend clear button style

## 1.3.2 (2024-01-26)

Expand Down
12 changes: 7 additions & 5 deletions lib/live_select/component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule LiveSelect.Component do
allow_clear: false,
available_option_class: nil,
clear_button_class: nil,
clear_button_extra_class: nil,
user_defined_options: false,
container_class: nil,
container_extra_class: nil,
Expand Down Expand Up @@ -45,7 +46,8 @@ defmodule LiveSelect.Component do
tailwind: [
active_option: ~W(text-white bg-gray-600),
available_option: ~W(cursor-pointer hover:bg-gray-400 rounded),
clear_button: ~W(hidden),
clear_button: ~W(hidden cursor-pointer),
clear_tag_button: ~W(cursor-pointer),
container: ~W(h-full text-black relative),
dropdown: ~W(absolute rounded-md shadow z-50 bg-gray-100 inset-x-0 top-full),
option: ~W(rounded px-4 py-1),
Expand All @@ -59,7 +61,8 @@ defmodule LiveSelect.Component do
daisyui: [
active_option: ~W(active),
available_option: ~W(cursor-pointer),
clear_button: ~W(hidden),
clear_button: ~W(hidden cursor-pointer),
clear_tag_button: ~W(cursor-pointer),
container: ~W(dropdown dropdown-open),
dropdown:
~W(dropdown-content z-[1] menu menu-compact shadow rounded-box bg-base-200 p-1 w-full),
Expand Down Expand Up @@ -607,8 +610,7 @@ defmodule LiveSelect.Component do
String.split(class_override)
end

defp class(:none, element, nil, _class_extend)
when element not in [:clear_button, :clear_tag_button] do
defp class(:none, element, nil, _class_extend) do
raise """
When using `style: :none`, please use only `#{element}_class` and not `#{element}_extra_class`
"""
Expand Down Expand Up @@ -681,7 +683,7 @@ defmodule LiveSelect.Component do
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class={["w-5 h-5", @class]}
class={["w-5 h-5"]}
>
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
</svg>
Expand Down
10 changes: 6 additions & 4 deletions lib/live_select/component.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
:if={!option[:sticky]}
type="button"
data-idx={idx}
class={class(@style, :clear_tag_button, nil, @clear_button_class)}
class={
class(@style, :clear_tag_button, @clear_button_class, @clear_button_extra_class)
}
>
<%= if @clear_button == [] do %>
<.x class="cursor-pointer" />
<.x />
<% else %>
<%= render_slot(@clear_button) %>
<% end %>
Expand Down Expand Up @@ -60,10 +62,10 @@
type="button"
phx-click="clear"
phx-target={@myself}
class={class(@style, :clear_button, nil, @clear_button_class)}
class={class(@style, :clear_button, @clear_button_class, @clear_button_extra_class)}
>
<%= if @clear_button == [] do %>
<.x class="cursor-pointer" />
<.x />
<% else %>
<%= render_slot(@clear_button) %>
<% end %>
Expand Down
7 changes: 6 additions & 1 deletion lib/mix/tasks/dump_style_table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ defmodule Mix.Tasks.DumpStyleTable do
end)
|> List.flatten()
|> Enum.group_by(&elem(&1, 0))
|> Map.new(fn {el, list} -> {el, Enum.map(list, &Tuple.delete_at(&1, 0)) |> Enum.sort()} end)
|> Enum.map(fn {el, list} -> {el, Enum.map(list, &Tuple.delete_at(&1, 0)) |> Enum.sort()} end)
|> Enum.sort_by(&elem(&1, 0))
|> Enum.with_index()
|> Enum.map(fn {{el, styles}, idx} ->
header =
Expand All @@ -34,11 +35,15 @@ defmodule Mix.Tasks.DumpStyleTable do
|> IO.write()
end

defp class_override_option(:clear_tag_button), do: class_override_option(:clear_button)

defp class_override_option(el) do
option_name = to_string(el) <> "_class"
if option_name in class_options(), do: option_name, else: ""
end

defp class_extend_option(:clear_tag_button), do: class_extend_option(:clear_button)

defp class_extend_option(el) do
option_name = to_string(el) <> "_extra_class"
if option_name in class_options(), do: option_name, else: ""
Expand Down
1 change: 1 addition & 0 deletions lib/support/live_select_web/live/showcase_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule LiveSelectWeb.ShowcaseLive do
:active_option_class,
:available_option_class,
:clear_button_class,
:clear_button_extra_class,
:container_class,
:container_extra_class,
:dropdown_class,
Expand Down
13 changes: 7 additions & 6 deletions styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,18 @@ The following table shows the default styles for each element and the options yo

| Element | Default daisyui classes | Default tailwind classes | Class override option | Class extend option |
|----|----|----|----|----|
| *tag* | badge badge-primary p-1.5 text-sm | bg-blue-400 flex p-1 rounded-lg text-sm | tag_class | tag_extra_class |
| *clear_button* | hidden | hidden | clear_button_class | |
| *active_option* | active | bg-gray-600 text-white | active_option_class | |
| *available_option* | cursor-pointer | cursor-pointer hover:bg-gray-400 rounded | available_option_class | |
| *clear_button* | cursor-pointer hidden | cursor-pointer hidden | clear_button_class | clear_button_extra_class |
| *clear_tag_button* | cursor-pointer | cursor-pointer | clear_button_class | clear_button_extra_class |
| *container* | dropdown dropdown-open | h-full relative text-black | container_class | container_extra_class |
| *text_input* | input input-bordered pr-6 w-full | disabled:bg-gray-100 disabled:placeholder:text-gray-400 disabled:text-gray-400 pr-6 rounded-md w-full | text_input_class | text_input_extra_class |
| *text_input_selected* | input-primary | border-gray-600 text-gray-600 | text_input_selected_class | |
| *option* | | px-4 py-1 rounded | option_class | option_extra_class |
| *dropdown* | bg-base-200 dropdown-content menu menu-compact p-1 rounded-box shadow w-full z-[1] | absolute bg-gray-100 inset-x-0 rounded-md shadow top-full z-50 | dropdown_class | dropdown_extra_class |
| *available_option* | cursor-pointer | cursor-pointer hover:bg-gray-400 rounded | available_option_class | |
| *option* | | px-4 py-1 rounded | option_class | option_extra_class |
| *selected_option* | disabled | text-gray-400 | selected_option_class | |
| *tag* | badge badge-primary p-1.5 text-sm | bg-blue-400 flex p-1 rounded-lg text-sm | tag_class | tag_extra_class |
| *tags_container* | flex flex-wrap gap-1 p-1 | flex flex-wrap gap-1 p-1 | tags_container_class | tags_container_extra_class |
| *text_input* | input input-bordered pr-6 w-full | disabled:bg-gray-100 disabled:placeholder:text-gray-400 disabled:text-gray-400 pr-6 rounded-md w-full | text_input_class | text_input_extra_class |
| *text_input_selected* | input-primary | border-gray-600 text-gray-600 | text_input_selected_class | |

For example, if you want to remove rounded borders from the options, have the active option use white text on a red background,
and use green as a background color for tags instead of blue, render [live_select/1](`LiveSelect.live_select/1`)
Expand Down
32 changes: 26 additions & 6 deletions test/live_select/component_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ defmodule LiveSelect.ComponentTest do
)
end

test "class for clear button can be set", %{form: form} do
test "class for clear button can be overridden", %{form: form} do
component =
render_component(
&LiveSelect.live_select/1,
Expand All @@ -734,11 +734,31 @@ defmodule LiveSelect.ComponentTest do
if(@style, do: [style: @style], else: [])
)

assert Floki.attribute(component, selectors()[:clear_button], "class") == [
((get_in(expected_class(), [@style || default_style(), :clear_button]) || "") <>
" foo")
|> String.trim()
]
assert Floki.attribute(component, selectors()[:clear_button], "class") == ["foo"]
end

if @style != :none do
test "class for clear button can be extended", %{form: form} do
component =
render_component(
&LiveSelect.live_select/1,
[
mode: :single,
field: form[:city_search],
options: ["A", "B", "C"],
value: "B",
allow_clear: true,
clear_button_extra_class: "foo"
] ++
if(@style, do: [style: @style], else: [])
)

assert Floki.attribute(component, selectors()[:clear_button], "class") == [
((get_in(expected_class(), [@style || default_style(), :clear_button]) || "") <>
" foo")
|> String.trim()
]
end
end

for element <- [
Expand Down
6 changes: 4 additions & 2 deletions test/support/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ defmodule LiveSelect.TestHelpers do
daisyui: [
active_option: ~S(active),
available_option: ~S(cursor-pointer),
clear_button: ~S(hidden),
clear_button: ~S(hidden cursor-pointer),
clear_tag_button: ~S(cursor-pointer),
container: ~S(dropdown dropdown-open),
dropdown:
~S(dropdown-content z-[1] menu menu-compact shadow rounded-box bg-base-200 p-1 w-full),
Expand All @@ -23,7 +24,8 @@ defmodule LiveSelect.TestHelpers do
tailwind: [
active_option: ~S(text-white bg-gray-600),
available_option: ~S(cursor-pointer hover:bg-gray-400 rounded),
clear_button: ~S(hidden),
clear_button: ~S(hidden cursor-pointer),
clear_tag_button: ~S(cursor-pointer),
container: ~S(h-full text-black relative),
dropdown: ~S(absolute rounded-md shadow z-50 bg-gray-100 inset-x-0 top-full),
option: ~S(rounded px-4 py-1),
Expand Down

0 comments on commit a054017

Please sign in to comment.