Skip to content

Commit

Permalink
Add as_child tag to mimic as_child attribute from shadcn
Browse files Browse the repository at this point in the history
  • Loading branch information
bluzky committed Nov 22, 2024
1 parent a04f04d commit 52f97d2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/salad_ui/collapsible.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ defmodule SaladUI.Collapsible do

attr :open, :boolean, default: true, doc: "Initial state of collapsible content"
attr :class, :string, default: nil
attr :rest, :global, include: ~w(title)
slot(:inner_block, required: true)

def collapsible(assigns) do
Expand All @@ -37,6 +38,7 @@ defmodule SaladUI.Collapsible do
phx-mounted={@open && JS.exec("phx-toggle-collapsible", to: "##{@id}")}
class={classes(["inline-block relative collapsible-root", @class])}
id={@id}
{@rest}
>
<%= render_slot(@inner_block) %>
</div>
Expand Down
40 changes: 39 additions & 1 deletion lib/salad_ui/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,17 @@ defmodule SaladUI.Helpers do
end

@doc """
Generates a dynamically named HTML tag.
This component is used to render dynamic tag based on the `tag` attribute. `tag` attribute can be a string or a function component.
This is just a wrapper around `dynamic_tag` function from Phoenix LiveView which only support string tag.
## Examples
```heex
<.dynamic tag={@tag} class="bg-primary text-primary-foreground">
Hello World
</.dynamic>
```
"""
def dynamic(%{tag: name} = assigns) when is_function(name, 1) do
assigns = Map.delete(assigns, :tag)
Expand All @@ -261,6 +271,34 @@ defmodule SaladUI.Helpers do
dynamic_tag(assigns)
end

@doc """
This component mimic behavior of `asChild` attribute from shadcn/ui.
It works by passing all attribute from `as_child` tag to `tag` function component, add pass `child` attribute to the `as_tag` attribute of the `tag` function component.
The `tag` function component should accept `as_tag` attribute to render the child component.
## Examples
```heex
<.as_child tag={&dropdown_menu_trigger/1} child={&sidebar_menu_button/1} class="bg-primary text-primary-foreground">
Hello World
</.as_child>
```
Normally this can be archieved by using `dropdown_menu_trigger` component directly but this will fire copile warning.
```heex
<.dropdown_menu_trigger as_tag={&sidebar_menu_button/1} class="bg-primary text-primary-foreground">
Hello World
</.dropdown_menu_trigger>
"""
def as_child(%{tag: tag, child: child_tag} = assigns) when is_function(tag, 1) do
assigns
|> Map.drop([:tag, :child])
|> assign(:as_tag, child_tag)
|> tag.()
end

# Translate error message
# borrowed from https://github.com/petalframework/petal_components/blob/main/lib/petal_components/field.ex#L414
defp translate_error({msg, opts}) do
Expand Down

0 comments on commit 52f97d2

Please sign in to comment.