Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Integrate Zag.js to improve acessibility #104

Draft
wants to merge 75 commits into
base: main
Choose a base branch
from
Draft
Changes from 7 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
c7da662
add files related to zag
selenil Nov 18, 2024
3a85322
modify cli to work with zag hook
selenil Nov 18, 2024
34d187e
add unique_id helper
selenil Nov 18, 2024
9eb93f1
make collapsible component accessible
selenil Nov 20, 2024
b70fb82
fix some issues
selenil Nov 20, 2024
65f780a
Merge branch 'feature/accessibility-hook' into feature/accessibility-…
bluzky Nov 28, 2024
a9752bc
Merge pull request #87 from selenil/feature/accessibility-hook
bluzky Nov 28, 2024
293dfed
fix collapsible
bluzky Nov 29, 2024
7bec0ca
Merge branch 'main' into feature/accessibility-hook
bluzky Nov 30, 2024
ba5be74
WIP
bluzky Dec 6, 2024
b3027cc
WIP
bluzky Dec 7, 2024
6da12eb
Improve select
bluzky Dec 7, 2024
0d0e307
Improve select with zag hook
bluzky Dec 8, 2024
a9a790d
Fix select with zag
bluzky Dec 8, 2024
d9d29f7
Merge pull request #103 from bluzky/feature/select-accessibility
bluzky Dec 8, 2024
f6b9346
Clean unused code
bluzky Dec 8, 2024
2ef5118
Merge pull request #108 from bluzky/feature/select-accessibility
bluzky Dec 8, 2024
fce00ef
Merge remote-tracking branch 'origin/main' into feature/accessibility…
bluzky Dec 8, 2024
1d25dc9
Fix hidden at loading
bluzky Dec 8, 2024
5d40409
Update select
bluzky Dec 8, 2024
c3b8bc7
Update js with fixes when testing on storybook
bluzky Dec 9, 2024
6fb81ed
Improve JS code for component
bluzky Dec 9, 2024
c611c20
Merge pull request #109 from bluzky/feature/acessibility-improve-select
bluzky Dec 9, 2024
9cb9ec9
WIP
selenil Dec 9, 2024
d4078f1
Improve Toggle group accessibility
bluzky Dec 10, 2024
941aa82
Merge pull request #111 from bluzky/feature/accessibility-toggle-group
bluzky Dec 10, 2024
8300ddc
wip trying fix radio group
bluzky Dec 10, 2024
2b1ec67
add support for transforming items in a collection
selenil Dec 11, 2024
4fc8e0f
remove todo comment
selenil Dec 11, 2024
7f4ed00
parse collections using the data-option attribute
selenil Dec 22, 2024
b2bde49
Merge pull request #110 from selenil/feature/zag-collections
bluzky Dec 23, 2024
d02dd55
Update tooltip
bluzky Dec 25, 2024
7c1a9f6
Update radio group to work with zagjs
bluzky Dec 25, 2024
11e4d12
Update collapsible and select to match new zag component
bluzky Dec 25, 2024
0d94231
Merge pull request #115 from bluzky/feature/accessibility-radio-group
bluzky Dec 25, 2024
a91a1ea
Update toggle group to match new component
bluzky Dec 25, 2024
fea64a7
Merge pull request #116 from bluzky/feature/accessibility-radio-group
bluzky Dec 25, 2024
bc82ae7
Merge remote-tracking branch 'origin/feature/accessibility-hook' into…
bluzky Dec 25, 2024
f5e0a67
Add zag for tooltip
bluzky Dec 25, 2024
5231d7b
Merge pull request #117 from bluzky/feature/tooltip-accessibility
bluzky Dec 25, 2024
14a0761
improve parts handling
selenil Dec 26, 2024
2818e47
wip integrate zag for tabs
selenil Dec 26, 2024
76605de
Merge pull request #118 from selenil/feature/improve-parts-handling
bluzky Jan 5, 2025
8269bf4
implement event listeners system
selenil Jan 8, 2025
11a437f
add show_tab function
selenil Jan 8, 2025
61c3382
add validation to listeners
selenil Jan 8, 2025
0d50a67
Update dropdown menu
bluzky Jan 9, 2025
6fe1d4f
Merge pull request #125 from selenil/feature/zag-event-listeners
bluzky Jan 10, 2025
c94612e
add listeners support
selenil Jan 10, 2025
0b610f7
add options support
selenil Jan 10, 2025
4dbb207
improve documentation
selenil Jan 10, 2025
a7be91a
improve show_tab function
selenil Jan 10, 2025
9855220
Merge pull request #119 from selenil/feature/improve-tabs
bluzky Jan 20, 2025
3de961f
Implement zagjs for dropdown menu
bluzky Jan 20, 2025
0e7360d
integrate zag with slider
selenil Jan 20, 2025
adceb25
improve documentation for slider component
selenil Jan 20, 2025
25cdbe8
support bind zag api values to elements
selenil Jan 22, 2025
a91ed22
Merge pull request #132 from selenil/feature/improve-slider
bluzky Jan 22, 2025
9341b6b
Merge pull request #131 from bluzky/feature/dropdown-menu-zag
bluzky Jan 22, 2025
fcd7200
Merge pull request #134 from selenil/feature/add-support-for-api-bind
bluzky Jan 23, 2025
ca3b346
add support for output in slider
selenil Jan 23, 2025
0ebe6ed
integrate zag with progress component
selenil Jan 23, 2025
70c5ce1
Merge pull request #138 from selenil/feature/add-support-for-output-t…
bluzky Jan 24, 2025
2486fbb
Merge pull request #139 from selenil/feature/improve-progress
bluzky Jan 24, 2025
678b25a
improve tooltip component
selenil Jan 24, 2025
73d6833
fix typos
selenil Jan 24, 2025
345c089
improve hover card component
selenil Jan 24, 2025
7703c8b
add createZagHook function
selenil Feb 3, 2025
e594f35
install zag types package
selenil Feb 3, 2025
b82b8e5
modify salad.add task to work with the new zag setup
selenil Feb 3, 2025
67b11cb
Merge pull request #145 from selenil/feature/avoid-copying-zag-hook
bluzky Feb 5, 2025
52a18b1
improve accordion component
selenil Feb 5, 2025
0f30e28
improve zag hook
selenil Feb 5, 2025
18bd539
Merge pull request #147 from selenil/feature/improve-zag-hook
bluzky Feb 10, 2025
dbed2cd
Merge pull request #142 from selenil/feature/improve-multiple-components
bluzky Feb 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions lib/mix/tasks/salad.add.ex
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ defmodule Mix.Tasks.Salad.Add do
:ok <- File.mkdir_p(Path.dirname(target_path)),
modified_content = insert_target_module_name(source_content, file_name),
:ok <- File.write(target_path, modified_content),
:ok <- setup_zag_integration(source_content, file_name),
:ok <- maybe_perform_additional_setup(file_name) do
Mix.shell().info("#{file_name} component installed successfully ✅")
else
@@ -131,6 +132,36 @@ defmodule Mix.Tasks.Salad.Add do
:ok
end

defp setup_zag_integration(source, file_name) do
# grab the component we are targeting in Zag
case Regex.run(~r/data-component="([^"]+)"/, source) do
[_, target_zag_component] ->
zag_imports_path = Path.join(File.cwd!(), "assets/js/zag/index.js")
export_statement = "export * as #{target_zag_component} from \"@zag-js/#{target_zag_component}\";\n"

existing_content = File.read!(zag_imports_path)

unless String.contains?(existing_content, export_statement) do
File.write!(zag_imports_path, export_statement, [:append])
end

unless Mix.env() == :test do
Mix.shell().cmd("npm install @zag-js/#{target_zag_component} --prefix assets")
end

:ok

_ ->
Mix.shell().info("""
The component you are trying to install (#{file_name}) does not have a data-component attribute set, so you cannot use Zag with it. The component will lack accessibility support and interactive features
""")

continue? = Mix.shell().yes?("Do you want to continue with the installation?")

if continue?, do: :ok, else: {:error, "Installation aborted"}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Error handling should clean up any partial installation when user aborts

Consider adding cleanup logic to remove any files or changes made before the abort

end
end

defp get_module_name do
Mix.Project.config()[:app]
|> Atom.to_string()
20 changes: 20 additions & 0 deletions lib/mix/tasks/salad.init.ex
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ defmodule Mix.Tasks.Salad.Init do
:ok <- patch_css(color_scheme, assets_path),
:ok <- patch_js(assets_path),
:ok <- copy_tailwind_colors(assets_path),
:ok <- copy_zag_files(assets_path),
:ok <- patch_tailwind_config(opts),
:ok <- maybe_write_helpers_module(component_path, app_name, opts),
:ok <- maybe_write_component_module(component_path, app_name, opts),
@@ -155,6 +156,25 @@ defmodule Mix.Tasks.Salad.Init do
:ok
end

defp copy_zag_files(assets_path) do
Mix.shell().info("Copying zag files to assets folder")
source_path = Path.join(assets_path, "zag")
target_path = Path.join(File.cwd!(), "assets/js/zag")

File.mkdir_p!(target_path)

Enum.each(File.ls!(source_path), fn file ->
unless File.exists?(Path.join(target_path, file)) do
File.cp!(Path.join(source_path, file), Path.join(target_path, file))
end
end)

Mix.shell().info("\nZagHook installed successfully")
Mix.shell().info("Do not forget to import it into your app.js file and pass it to your live socket")

:ok
end

defp patch_tailwind_config(opts) do
Mix.shell().info("Patching tailwind.config.js")
tailwind_config_path = Path.join(File.cwd!(), "assets/tailwind.config.js")
34 changes: 16 additions & 18 deletions lib/salad_ui/collapsible.ex
Original file line number Diff line number Diff line change
@@ -20,23 +20,26 @@ defmodule SaladUI.Collapsible do

attr :id, :string,
required: true,
doc: "Id to identify collapsible component, collapsible_trigger uses this id to toggle content visibility"
doc: "Id to identify collapsible component"

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

def collapsible(assigns) do
assigns =
assign(assigns, :open, normalize_boolean(assigns[:open]))
assigns = assign(assigns, :open, normalize_boolean(assigns[:open]))

~H"""
<div
data-state="closed"
phx-toggle-collapsible={toggle_collapsible(@id)}
phx-mounted={@open && JS.exec("phx-toggle-collapsible", to: "##{@id}")}
class={classes(["inline-block relative collapsible-root", @class])}
data-component="collapsible"
data-parts={Jason.encode!(["trigger", "content"])}
data-options={Jason.encode!(%{open: :bool})}
data-open={@open}
data-listeners={Jason.encode!(@listeners)}
phx-hook="ZagHook"
class={classes(["inline-block relative", @class])}
id={@id}
{@rest}
>
@@ -55,12 +58,7 @@ defmodule SaladUI.Collapsible do

def collapsible_trigger(assigns) do
~H"""
<.dynamic
tag={@as_tag}
onclick={exec_closest("phx-toggle-collapsible", ".collapsible-root")}
class={@class}
{@rest}
>
<div data-part="trigger" class={@class}>
<%= render_slot(@inner_block) %>
</.dynamic>
"""
@@ -76,9 +74,10 @@ defmodule SaladUI.Collapsible do
def collapsible_content(assigns) do
~H"""
<div
data-part="content"
class={
classes([
"collapsible-content hidden transition-all duration-200 ease-in-out",
"transition-all duration-200 ease-in-out",
@class
])
}
@@ -93,9 +92,8 @@ defmodule SaladUI.Collapsible do
Show collapsible content.
"""
def toggle_collapsible(js \\ %JS{}, id) do
js
|> JS.toggle(
to: "##{id} .collapsible-content",
JS.toggle(js,
to: "##{id} [data-part='content']",
in: {"ease-out duration-200", "opacity-0", "opacity-100"},
out: {"ease-out", "opacity-100", "opacity-70"},
time: 200
6 changes: 6 additions & 0 deletions lib/salad_ui/helpers.ex
Original file line number Diff line number Diff line change
@@ -135,6 +135,12 @@ defmodule SaladUI.Helpers do
"#{shared_classes} #{variation_classes}"
end

def unique_id(seed \\ 16, length \\ 22) do
seed
|> :crypto.strong_rand_bytes()
|> Base.url_encode64()
|> binary_part(0, length)
end
@doc """
Common function for building variant

Loading