Skip to content

Commit 7a9bf61

Browse files
author
selenil
committed
feat: add accordion component story
1 parent 2ccfef6 commit 7a9bf61

File tree

2 files changed

+156
-0
lines changed

2 files changed

+156
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
defmodule BloomSiteWeb.Components.Accordion do
2+
use Phoenix.Component
3+
4+
@moduledoc """
5+
Accordion component.
6+
7+
## Examples
8+
9+
<.accordion id="my-accordion">
10+
<:header>
11+
Open me!
12+
</:header>
13+
<:panel>
14+
I'm open!
15+
</:panel>
16+
</.accordion>
17+
"""
18+
alias Phoenix.LiveView.JS
19+
20+
slot :header, required: true do
21+
attr(:color, :string)
22+
attr(:hover_color, :string)
23+
attr(:text_color, :string)
24+
attr(:icon_color, :string)
25+
end
26+
27+
slot :panel, required: true do
28+
attr(:color, :string)
29+
attr(:text_color, :string)
30+
end
31+
32+
attr(:id, :string, required: true, doc: "A unique id to identify the accordion")
33+
34+
attr(:open, :boolean,
35+
default: false,
36+
doc: "Whether the accordion should appear open or not."
37+
)
38+
39+
def accordion(assigns) do
40+
~H"""
41+
<div id={@id} class="relative overflow-hidden rounded-lg border border-gray-200">
42+
<button
43+
:for={header <- @header}
44+
id={"#{@id}-header"}
45+
aria-expanded={@open}
46+
aria-controls={"#{@id}-content"}
47+
class={[
48+
"flex w-full cursor-pointer items-center justify-between px-4 py-3 text-left transition-colors duration-200 ease-in-out focus:outline-none",
49+
"bg-#{Map.get(header, :color, "gray-100")}",
50+
"hover:bg-#{Map.get(header, :hover_color, "gray-200")}",
51+
"text-#{Map.get(header, :text_color, "gray-800")}"
52+
]}
53+
phx-click={toggle(@id)}
54+
>
55+
<span class="font-medium"><%= render_slot(header) %></span>
56+
<span
57+
id={"#{@id}-icon"}
58+
aria-hidden="true"
59+
class={[
60+
"#{if @open, do: "hero-chevron-up", else: "hero-chevron-down"}",
61+
"h-5 w-5 cursor-pointer",
62+
"text-#{Map.get(header, :icon_color, "gray-500")}"
63+
]}
64+
/>
65+
</button>
66+
<div
67+
:for={panel <- @panel}
68+
id={"#{@id}-content"}
69+
role="region"
70+
aria-hidden={!@open}
71+
aria-labelledby={"#{@id}-header"}
72+
class={[
73+
"#{if @open, do: "block", else: "hidden"}",
74+
"hero-#{if @open, do: "block", else: "hidden"}",
75+
"px-4 py-3",
76+
"bg-#{Map.get(panel, :color, "white")}",
77+
"text-#{Map.get(panel, :text_color, "gray-800")}"
78+
]}
79+
>
80+
<%= render_slot(panel) %>
81+
</div>
82+
</div>
83+
"""
84+
end
85+
86+
@doc """
87+
Toogles the accordion panel, opening or closing it.
88+
Also handles changing icons for each state.
89+
"""
90+
def toggle(js \\ %JS{}, id) do
91+
js
92+
|> JS.toggle(
93+
to: "##{id}-content",
94+
in:
95+
{"transition-all transform ease-out duration-300",
96+
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
97+
"opacity-100 translate-y-0 sm:scale-100"},
98+
out:
99+
{"transition-all transform ease-in duration-200",
100+
"opacity-100 translate-y-0 sm:scale-100",
101+
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"}
102+
)
103+
|> JS.toggle_class("rotate-180", to: "##{id}-icon")
104+
|> JS.toggle_attribute({"aria-expanded", "true", "false"}, to: "##{id}-header")
105+
end
106+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
defmodule BloomSite.Storybook.BloomComponents.Accordion do
2+
use PhoenixStorybook.Story, :component
3+
4+
def function, do: &BloomSiteWeb.Components.Accordion.accordion/1
5+
6+
# Make sure the width of the accordion is not too small
7+
def template do
8+
"""
9+
<div class="w-full">
10+
<.psb-variation/>
11+
</div>
12+
"""
13+
end
14+
15+
def variations do
16+
[
17+
%Variation{
18+
id: :default,
19+
slots: [
20+
"""
21+
<:header>
22+
What is Bloom?
23+
</:header>
24+
""",
25+
"""
26+
<:panel>
27+
Bloom is an opinionated extension to Phoenix core_components.
28+
</:panel>
29+
"""
30+
]
31+
},
32+
%Variation{
33+
id: :with_color,
34+
slots: [
35+
"""
36+
<:header color="red-500" hover_color="red-800" text_color="white" icon_color="white">
37+
How do I customize the colors?
38+
</:header>
39+
""",
40+
"""
41+
<:panel>
42+
Use the colors attributes in the slots and pass them a color from the tailwind palette.
43+
</:panel>
44+
"""
45+
]
46+
}
47+
]
48+
end
49+
50+
end

0 commit comments

Comments
 (0)