Current section

41 Versions

Jump to

Compare versions

7 files changed
+408 additions
-6 deletions
  @@ -180,7 +180,7 @@ List of available components.
180 180 | [Navbar](https://daisyui.com/components/navbar) | âś… | âś… |
181 181 | [Pagination](https://daisyui.com/components/pagination) | âś… | âś… |
182 182 | [Steps](https://daisyui.com/components/steps) | ❌ | ❌ |
183 - | [Tabs](https://daisyui.com/components/tab) | ❌ | ❌ |
183 + | [Tabs](https://daisyui.com/components/tab) | ✅ | ❌ |
184 184
185 185 ### Feedback
  @@ -1,7 +1,7 @@
1 1 {<<"links">>,
2 2 [{<<"GitHub">>,<<"https://github.com/phcurado/daisy_ui_components">>}]}.
3 3 {<<"name">>,<<"daisy_ui_components">>}.
4 - {<<"version">>,<<"0.8.1">>}.
4 + {<<"version">>,<<"0.8.2">>}.
5 5 {<<"description">>,<<"DaisyUI component library for LiveView">>}.
6 6 {<<"elixir">>,<<"~> 1.14">>}.
7 7 {<<"app">>,<<"daisy_ui_components">>}.
  @@ -22,6 +22,7 @@
22 22 <<"lib/daisy_ui_components/navbar.ex">>,
23 23 <<"lib/daisy_ui_components/progress.ex">>,
24 24 <<"lib/daisy_ui_components/badge.ex">>,
25 + <<"lib/daisy_ui_components/tabs.ex">>,
25 26 <<"lib/daisy_ui_components/footer.ex">>,
26 27 <<"lib/daisy_ui_components/table.ex">>,
27 28 <<"lib/daisy_ui_components/dropdown.ex">>,
  @@ -76,6 +76,7 @@ defmodule DaisyUIComponents do
76 76 import DaisyUIComponents.Stat
77 77 import DaisyUIComponents.Swap
78 78 import DaisyUIComponents.Table
79 + import DaisyUIComponents.Tabs
79 80 import DaisyUIComponents.TextInput
80 81 import DaisyUIComponents.Textarea
81 82 import DaisyUIComponents.Toggle
  @@ -0,0 +1,397 @@
1 + defmodule DaisyUIComponents.Tabs do
2 + @moduledoc """
3 + Tab component used to show a list of links in a tabbed format.
4 +
5 + Renders a list of tab links or toggles with radio toggle and content or label with radio toggle and content
6 +
7 + https://daisyui.com/components/tab/
8 +
9 + ## Basic Example:
10 + <.tabs>
11 + <.tab title="Tab 1" />
12 + <.tab title="Tab 2" active />
13 + <.tab title="Tab 3" disabled />
14 + </.tabs>
15 +
16 + ## Renders:
17 + <div role="tablist" class="tabs">
18 + <a role="tab" class="tab">Tab 1</a>
19 + <a role="tab" class="tab tab-active">Tab 2</a>
20 + <a role="tab" class="tab tab-disabled">Tab 3</a>
21 + </div>
22 +
23 + ## Basic Example with inner block content
24 + ## NOTE: if title attribute is provided, the inner block will not be rendered
25 + <.tabs>
26 + <.tab>
27 + <span>extra content</span>
28 + Tab 1
29 + </.tab>
30 + <.tab active>
31 + Tab 2
32 + </.tab>
33 + <.tab disabled>
34 + Tab 3
35 + </.tab>
36 + </.tabs>
37 +
38 + ## Renders:
39 +
40 + <div role="tablist" class="tabs">
41 + <a role="tab" class="tab">
42 + <span>extra content</span>
43 + Tab 1
44 + </a>
45 + <a role="tab" class="tab tab-active">
46 + Tab 2
47 + </a>
48 + <a role="tab" class="tab tab-disabled">
49 + Tab 3
50 + </a>
51 + </div>
52 +
53 + ## Tabs with button type
54 + <.tabs>
55 + <.tab type="button" title="Tab 1" />
56 + <.tab type="button" title="Tab 2" active />
57 + <.tab type="button" title="Tab 3" disabled />
58 + </.tabs>
59 +
60 + ## Renders:
61 +
62 + <div role="tablist" class="tabs">
63 + <button class="tab">Tab 1</button>
64 + <button class="tab tab-active">Tab 2</button>
65 + <button class="tab tab-disabled">Tab 3</button>
66 + </div>
67 +
68 + ## Tabs with radio type
69 + ## These tabs must provide a title attribute
70 + <.tabs>
71 + <.tab type="radio" title="Tab 1" name="tabs" />
72 + <.tab type="radio" title="Tab 2" name="tabs" active />
73 + <.tab type="radio" title="Tab 3" name="tabs" disabled />
74 + </.tabs>
75 +
76 + ## Renders:
77 + <div role="tablist" class="tabs">
78 + <input type="radio" name="tabs" class="tab" aria-label="Tab 1" />
79 + <input type="radio" name="tabs" class="tab" aria-label="Tab 2" checked="checked" />
80 + <input type="radio" name="tabs" class="tab tab-disabled" aria-label="Tab 3" />
81 + </div>
82 +
83 + ## Tabs with label type
84 + ## These tabs could have a title attribute or inner block content
85 + <.tabs>
86 + <.tab type="label" title="Tab 1" name="tabs" />
87 + <.tab type="label" title="Tab 2" name="tabs" active />
88 + <.tab type="label" title="Tab 3" name="tabs" disabled />
89 + </.tabs>
90 +
91 + ## Renders:
92 + <div role="tablist" class="tabs">
93 + <label class="tab">
94 + <input type="radio" name="tabs" />
95 + Tab 1
96 + </label>
97 + <label class="tab">
98 + <input type="radio" name="tabs" checked="checked" />
99 + Tab 2
100 + </label>
101 + <label class="tab tab-disabled">
102 + <input type="radio" name="tabs" />
103 + Tab 3
104 + </label>
105 + </div>
106 +
107 + ## Tabs with label type and and content
108 + <.tabs lift position="bottom">
109 + <.tab type="label" title="Tab 1" name="my_tabs_with_content" />
110 + <.tab_content class="bg-base-100 border-base-300 p-6">Tab content 1</.tab_content>
111 + <.tab type="label" title="Tab 2" name="my_tabs_with_content" active />
112 + <.tab_content class="bg-base-100 border-base-300 p-6">Tab content 2</.tab_content>
113 + <.tab type="label" title="Tab 3" name="my_tabs_with_content" disabled />
114 + <.tab_content class="bg-base-100 border-base-300 p-6">Tab content 3</.tab_content>
115 + </.tabs>
116 +
117 + ## Renders:
118 + <div role="tablist" class="tabs tabs-lift tabs-bottom">
119 + <label class="tab">
120 + <input type="radio" name="my_tabs_with_content" /> Tab 1
121 + </label>
122 + <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 1</div>
123 +
124 + <label class="tab tab-active">
125 + <input type="radio" name="my_tabs_with_content" checked="checked" /> Tab 2
126 + </label>
127 + <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 2</div>
128 +
129 + <label class="tab tab-disabled">
130 + <input type="radio" name="my_tabs_with_content" /> Tab 3
131 + </label>
132 + <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 3</div>
133 + </div>
134 + """
135 +
136 + use DaisyUIComponents, :component
137 +
138 + attr :class, :any, default: nil
139 + attr :size, :string, values: sizes()
140 + attr :box, :boolean, default: false
141 + attr :border, :boolean, default: false
142 + attr :lift, :boolean, default: false
143 + attr :position, :string, values: ~w(top bottom)
144 + attr :rest, :global
145 +
146 + slot :inner_block
147 +
148 + def tabs(assigns) do
149 + assigns =
150 + assign(assigns, :class, tabs_classes(assigns))
151 +
152 + ~H"""
153 + <div role="tablist" class={@class} {@rest}>
154 + {render_slot(@inner_block)}
155 + </div>
156 + """
157 + end
158 +
159 + attr :title, :string
160 + attr :class, :any, default: nil
161 + attr :type, :string, values: ~w(link button radio label), default: "link"
162 + attr :name, :string, default: nil
163 + attr :active, :boolean, default: false
164 + attr :disabled, :boolean, default: false
165 + attr :rest, :global
166 +
167 + slot :inner_block
168 +
169 + def tab(%{type: "label", title: _title} = assigns) do
170 + assigns =
171 + assign(assigns, :class, tab_classes(assigns))
172 +
173 + ~H"""
174 + <.tab_label title={@title} name={@name} class={@class} active={@active} {@rest} />
175 + """
176 + end
177 +
178 + def tab(%{type: "label"} = assigns) do
179 + assigns =
180 + assign(assigns, :class, tab_classes(assigns))
181 +
182 + ~H"""
183 + <.tab_label name={@name} class={@class} active={@active} {@rest}>
184 + {render_slot(@inner_block)}
185 + </.tab_label>
186 + """
187 + end
188 +
189 + def tab(%{type: "radio", title: _title} = assigns) do
190 + assigns =
191 + assign(assigns, :class, radio_tab_classes(assigns))
192 +
193 + ~H"""
194 + <.tab_radio title={@title} name={@name} class={@class} active={@active} {@rest} />
195 + """
196 + end
197 +
198 + def tab(%{type: "radio"} = _assigns) do
199 + raise ArgumentError,
200 + "title attribute is required for radio type tab. Radio type tab cannot have inner block content"
201 + end
202 +
203 + def tab(%{type: "button", title: _title} = assigns) do
204 + assigns =
205 + assign(assigns, :class, tab_classes(assigns))
206 +
207 + ~H"""
208 + <.tab_button title={@title} class={@class} {@rest} />
209 + """
210 + end
211 +
212 + def tab(%{type: "button"} = assigns) do
213 + assigns =
214 + assign(assigns, :class, tab_classes(assigns))
215 +
216 + ~H"""
217 + <.tab_button class={@class} {@rest}>
218 + {render_slot(@inner_block)}
219 + </.tab_button>
220 + """
221 + end
222 +
223 + def tab(%{title: _title} = assigns) do
224 + assigns =
225 + assign(assigns, :class, tab_classes(assigns))
226 +
227 + ~H"""
228 + <.tab_link title={@title} class={@class} {@rest} />
229 + """
230 + end
231 +
232 + def tab(assigns) do
233 + assigns =
234 + assign(assigns, :class, tab_classes(assigns))
235 +
236 + ~H"""
237 + <.tab_link class={@class} {@rest}>
238 + {render_slot(@inner_block)}
239 + </.tab_link>
240 + """
241 + end
242 +
243 + attr :title, :string
244 + attr :name, :string, required: true
245 + attr :class, :any, default: nil
246 + attr :active, :boolean, default: false
247 + attr :rest, :global
248 +
249 + slot :inner_block
250 +
251 + def tab_label(%{title: _title} = assigns) do
252 + ~H"""
253 + <label class={@class} {@rest}>
254 + <input type="radio" name={@name} checked={@active && "checked"} />
255 + {@title}
256 + </label>
257 + """
258 + end
259 +
260 + def tab_label(assigns) do
261 + ~H"""
262 + <label class={@class} {@rest}>
263 + <input type="radio" name={@name} checked={@active && "checked"} />
264 + {render_slot(@inner_block)}
265 + </label>
266 + """
267 + end
268 +
269 + attr :title, :string, required: true
270 + attr :name, :string, required: true
271 + attr :class, :any, default: nil
272 + attr :active, :boolean, default: false
273 + attr :rest, :global
274 +
275 + def tab_radio(assigns) do
276 + ~H"""
277 + <input
278 + type="radio"
279 + name={@name}
280 + class={@class}
281 + aria-label={@title}
282 + checked={@active && "checked"}
283 + {@rest}
284 + />
285 + """
286 + end
287 +
288 + attr :title, :string
289 + attr :class, :any, default: nil
290 + attr :rest, :global
291 +
292 + slot :inner_block
293 +
294 + def tab_button(%{title: _title} = assigns) do
295 + ~H"""
296 + <button class={@class} {@rest}>
297 + {@title}
298 + </button>
299 + """
300 + end
301 +
302 + def tab_button(assigns) do
303 + ~H"""
304 + <button class={@class} {@rest}>
305 + {render_slot(@inner_block)}
306 + </button>
307 + """
308 + end
309 +
310 + attr :title, :string
311 + attr :class, :any, default: nil
312 + attr :rest, :global
313 +
314 + slot :inner_block
315 +
316 + def tab_link(%{title: _title} = assigns) do
317 + ~H"""
318 + <a role="tab" class={@class} {@rest}>
319 + {@title}
320 + </a>
321 + """
322 + end
323 +
324 + def tab_link(assigns) do
325 + ~H"""
326 + <a role="tab" class={@class} {@rest}>
327 + {render_slot(@inner_block)}
328 + </a>
329 + """
330 + end
331 +
332 + attr :class, :any, default: nil
333 + attr :rest, :global
334 +
335 + slot :inner_block
336 +
337 + def tab_content(assigns) do
338 + assigns =
339 + assign(assigns, :class, tab_content_classes(assigns))
340 +
341 + ~H"""
342 + <div class={@class} {@rest}>
343 + {render_slot(@inner_block)}
344 + </div>
345 + """
346 + end
347 +
348 + # Wrapper Classes
349 + defp tabs_classes(assigns) do
350 + classes([
351 + "tabs",
352 + tabs_size(assigns[:size]),
353 + maybe_add_class(assigns[:border], "tabs-border"),
354 + maybe_add_class(assigns[:box], "tabs-box"),
355 + maybe_add_class(assigns[:lift], "tabs-lift"),
356 + position(assigns[:position]),
357 + assigns.class
358 + ])
359 + end
360 +
361 + # Individual Tab Classes
362 + defp tab_classes(assigns) do
363 + classes([
364 + "tab",
365 + maybe_add_class(assigns[:active], "tab-active"),
366 + maybe_add_class(assigns[:disabled], "tab-disabled")
367 + ])
368 + end
369 +
370 + defp radio_tab_classes(assigns) do
371 + # Instead of "tab-active" class, the checked attribute is used for radio tabs
372 + classes([
373 + "tab",
374 + maybe_add_class(assigns[:disabled], "tab-disabled")
375 + ])
376 + end
377 +
378 + defp tab_content_classes(assigns) do
379 + classes([
380 + "tab-content",
381 + assigns.class
382 + ])
383 + end
384 +
385 + # Sizes
386 + defp tabs_size("xs"), do: "tabs-xs"
387 + defp tabs_size("sm"), do: "tabs-sm"
388 + defp tabs_size("md"), do: "tabs-md"
389 + defp tabs_size("lg"), do: "tabs-lg"
390 + defp tabs_size("xl"), do: "tabs-xl"
391 + defp tabs_size(_size), do: nil
392 +
393 + # Positions
394 + defp position("top"), do: "tabs-top"
395 + defp position("bottom"), do: "tabs-bottom"
396 + defp position(_position), do: nil
397 + end
  @@ -9,9 +9,11 @@ defmodule DaisyUIComponents.Toggle do
9 9 use DaisyUIComponents, :component
10 10
11 11 attr :class, :any, default: nil
12 + attr :checked, :boolean, default: nil, doc: "the checked flag for checkbox inputs"
13 + attr :value, :any, default: nil
12 14 attr :color, :string, values: colors()
13 15 attr :size, :string, values: sizes()
14 - attr :rest, :global, include: ~w(checked)
16 + attr :rest, :global, include: ~w(name)
15 17
16 18 def toggle(assigns) do
17 19 assigns =
  @@ -27,7 +29,7 @@ defmodule DaisyUIComponents.Toggle do
27 29 )
28 30
29 31 ~H"""
30 - <input type="checkbox" class={@class} {@rest} />
32 + <input class={@class} type="checkbox" checked={@checked} value={@value} {@rest} />
31 33 """
32 34 end
Loading more files…