Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0113e5c
Turn some labels into divs
Flo0807 Jun 5, 2025
ae85161
Add missing name to input
Flo0807 Jun 5, 2025
763b451
Add missing id to select input
Flo0807 Jun 5, 2025
df9e13f
Turn has many label into div
Flo0807 Jun 5, 2025
f9d9f73
Turn multi select label into div
Flo0807 Jun 5, 2025
4448198
Use `dynamic_tag` for `input_label/1` component
Flo0807 Jun 5, 2025
1ef56de
Pass`for` to `input_label/1` for most of the fields
Flo0807 Jun 5, 2025
785967d
Use description list elements on show view
Flo0807 Jun 5, 2025
73e0546
Put for into rest
Flo0807 Jun 13, 2025
2aad5bb
Update tests
Flo0807 Jun 13, 2025
e32edbc
Use p element for has many through label
Flo0807 Jun 13, 2025
d6299a7
Add aria-labelledby to new-relational button
Flo0807 Jun 13, 2025
25cb43c
Turn label for multi select fields into p-element
Flo0807 Jun 13, 2025
1391bdf
Merge branch 'develop' into feature/a11y
Flo0807 Jun 13, 2025
5b8de9f
Merge branch 'develop' into feature/a11y
Flo0807 Jun 27, 2025
5cd7a94
Update `show_panel` and `field_container` component
Flo0807 Jun 27, 2025
b4a860e
Add screen reader support for delete button in InlineCRUD component
Flo0807 Jun 27, 2025
7c4ebe7
Wrap sidebar items in ul-element
Flo0807 Jun 27, 2025
4cb47f1
Merge branch 'develop' into feature/a11y
Flo0807 Jul 30, 2025
9b4d17f
Transform inline crud checkboxes to buttons
Flo0807 Jul 30, 2025
888a5a3
Add text for screen readers to table action header
Flo0807 Jul 30, 2025
b1a559a
Add screenreader text to mobile theme selector
Flo0807 Jul 30, 2025
20417a1
Add missing translation
Flo0807 Jul 30, 2025
1b4b500
Improve accessibility of upload input
Flo0807 Jul 31, 2025
513e4fe
Remove button elements from links
Flo0807 Jul 31, 2025
c15d89e
Fix wrong key is being used in select_relational_field
Flo0807 Jul 31, 2025
89750da
Adapt tests to new html structure
Flo0807 Jul 31, 2025
931a8bd
Merge branch 'develop' into feature/a11y
Flo0807 Aug 1, 2025
9cefd80
Move changes to v0.15 upgrade guide
Flo0807 Aug 1, 2025
33bf946
Merge branch 'develop' into feature/a11y
Flo0807 Aug 22, 2025
0e881fe
Add title and aria-label to topbar dropdown
Flo0807 Aug 22, 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
6 changes: 3 additions & 3 deletions demo/lib/demo_web/components/layouts/admin.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
{"Sunset", "sunset"}
]}
/>
<Backpex.HTML.Layout.topbar_dropdown class="mr-2 md:mr-0">
<Backpex.HTML.Layout.topbar_dropdown class="mr-2 md:mr-0" title="User menu" aria-label="Open user menu">
<:label>
<label tabindex="0" class="btn btn-square btn-ghost">
<div class="btn btn-square btn-ghost">
<Backpex.HTML.CoreComponents.icon name="hero-user" class="size-6" />
</label>
</div>
</:label>
<li>
<.link href="https://backpex.live" class="text-error flex justify-between hover:bg-base-200">
Expand Down
8 changes: 4 additions & 4 deletions demo/test/demo_web/live/category_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule DemoWeb.Live.CategoryLiveTest do
conn
|> visit(~p"/admin/categories")
|> assert_has("h1", text: "Categories", exact: true)
|> assert_has("button", text: "New Category", exact: true)
|> assert_has("a", text: "New Category", exact: true)
|> assert_has("button[disabled]", text: "Delete", exact: true)
|> assert_has("div", text: "Items 1 to 3 (3 total)", exact: true)
|> assert_has("table tbody tr", count: 3)
Expand Down Expand Up @@ -52,7 +52,7 @@ defmodule DemoWeb.Live.CategoryLiveTest do
conn
|> visit(~p"/admin/categories/#{category.id}/show")
|> assert_has("h1", text: "Category", exact: true)
|> assert_has("p", text: "Name", exact: true)
|> assert_has("dt", text: "Name", exact: true)
|> assert_has("p", text: category.name, exact: true)
end
end
Expand All @@ -64,7 +64,7 @@ defmodule DemoWeb.Live.CategoryLiveTest do
conn
|> visit(~p"/admin/categories/#{category.id}/edit")
|> assert_has("h1", text: "Edit Category", exact: true)
|> assert_has("button", text: "Cancel", exact: true)
|> assert_has("a", text: "Cancel", exact: true)
|> assert_has("button", text: "Save", exact: true)
end

Expand All @@ -89,7 +89,7 @@ defmodule DemoWeb.Live.CategoryLiveTest do
conn
|> visit(~p"/admin/categories/new")
|> assert_has("h1", text: "New Category", exact: true)
|> assert_has("button", text: "Cancel", exact: true)
|> assert_has("a", text: "Cancel", exact: true)
|> assert_has("button", text: "Save", exact: true)
end

Expand Down
10 changes: 5 additions & 5 deletions demo/test/demo_web/live/tag_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule DemoWeb.Live.TagLiveTest do
conn
|> visit(~p"/admin/tags")
|> assert_has("h1", text: "Tags", exact: true)
|> assert_has("button", text: "New Tag", exact: true)
|> assert_has("a", text: "New Tag", exact: true)
|> assert_has("button[disabled]", text: "Delete", exact: true)
|> assert_has("div", text: "Items 1 to 3 (3 total)", exact: true)
|> assert_has("table tbody tr", count: 3)
Expand Down Expand Up @@ -52,8 +52,8 @@ defmodule DemoWeb.Live.TagLiveTest do
conn
|> visit(~p"/admin/tags/#{tag.id}/show")
|> assert_has("h1", text: "Tag", exact: true)
|> assert_has("p", text: "Name", exact: true)
|> assert_has("p", text: "Inserted At", exact: true)
|> assert_has("dt", text: "Name", exact: true)
|> assert_has("dt", text: "Inserted At", exact: true)
|> assert_has("p", text: tag.name, exact: true)
end
end
Expand All @@ -65,7 +65,7 @@ defmodule DemoWeb.Live.TagLiveTest do
conn
|> visit(~p"/admin/tags/#{tag.id}/edit")
|> assert_has("h1", text: "Edit Tag", exact: true)
|> assert_has("button", text: "Cancel", exact: true)
|> assert_has("a", text: "Cancel", exact: true)
|> assert_has("button", text: "Save", exact: true)
end

Expand All @@ -90,7 +90,7 @@ defmodule DemoWeb.Live.TagLiveTest do
conn
|> visit(~p"/admin/tags/new")
|> assert_has("h1", text: "New Tag", exact: true)
|> assert_has("button", text: "Cancel", exact: true)
|> assert_has("a", text: "Cancel", exact: true)
|> assert_has("button", text: "Save", exact: true)
end

Expand Down
4 changes: 2 additions & 2 deletions demo/test/demo_web/live/ticket_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ defmodule DemoWeb.TicketLiveTest do
conn
|> visit(~p"/admin/tickets/#{ticket.id}/show")
|> assert_has("h1", text: "Ticket", exact: true)
|> assert_has("p", text: "Subject", exact: true)
|> assert_has("p", text: "Body", exact: true)
|> assert_has("dt", text: "Subject", exact: true)
|> assert_has("dt", text: "Body", exact: true)
|> assert_has("p", text: ticket.subject, exact: true)
|> assert_has("p", text: ticket.body, exact: true)
end
Expand Down
2 changes: 1 addition & 1 deletion guides/get_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ To get you started quickly, we provide a layout you can copy & paste into your a
<:topbar>
<Backpex.HTML.Layout.topbar_branding />

<Backpex.HTML.Layout.topbar_dropdown class="mr-2 md:mr-0">
<Backpex.HTML.Layout.topbar_dropdown class="mr-2 md:mr-0" title="User menu" aria-label="Open user menu">
<:label>
<label tabindex="0" class="btn btn-square btn-ghost">
<Backpex.HTML.CoreComponents.icon name="hero-user" class="size-6" />
Expand Down
14 changes: 14 additions & 0 deletions guides/upgrading/v0.15.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,17 @@ def fields do
]
end
```

## Component changes

- `Backpex.HTML.Layout.field_container/1` now uses a `dl` element instead of a `div` element to better align with HTML semantics.

## Add translations

Make sure to add the following translations:

- `"Delete row with index %{index}"`
- `"Actions"`
- `"Select theme"`

See the [the backpex.pot file for v0.14.0](https://github.com/naymspace/backpex/blob/0.14.0/priv/gettext/backpex.pot) in our GitHub repository for all available translations to match on.
2 changes: 1 addition & 1 deletion lib/backpex/fields/belongs_to.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ defmodule Backpex.Fields.BelongsTo do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@owner_key]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="select"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/boolean.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ defmodule Backpex.Fields.Boolean do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="toggle"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/currency.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ defmodule Backpex.Fields.Currency do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="number"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/date.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ defmodule Backpex.Fields.Date do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="date"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/date_time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ defmodule Backpex.Fields.DateTime do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="datetime-local"
Expand Down
9 changes: 5 additions & 4 deletions lib/backpex/fields/has_many.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,14 @@ defmodule Backpex.Fields.HasMany do
<div id={@name}>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label as="p" text={@field_options[:label]} />
</:label>
<div class="dropdown w-full">
<label
<div
tabindex="0"
role="button"
class={[
"input block h-fit w-full p-2",
"input block h-fit w-full cursor-pointer p-2",
@errors == [] && "bg-transparent",
@errors != [] && "input-error bg-error/10"
]}
Expand All @@ -167,7 +168,7 @@ defmodule Backpex.Fields.HasMany do
</label>
</div>
</div>
</label>
</div>
<Form.error :for={msg <- @errors} class="mt-1">{msg}</Form.error>
<div tabindex="0" class="dropdown-content z-[1] menu bg-base-100 rounded-box w-full overflow-y-auto shadow">
<div class="max-h-72 p-2">
Expand Down
26 changes: 20 additions & 6 deletions lib/backpex/fields/has_many_through.ex
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,11 @@ defmodule Backpex.Fields.HasManyThrough do
>
{label}
</th>
<th></th>
<th>
<span class="sr-only">
{Backpex.__("Actions", @live_resource)}
</span>
</th>
</tr>
</thead>
<tbody class="text-base-content/75">
Expand Down Expand Up @@ -244,11 +248,11 @@ defmodule Backpex.Fields.HasManyThrough do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label id={"has-many-through-label-#{@name}"} as="p" text={@field_options[:label]} />
</:label>

<div :if={@listables != []} class="ring-base-content/10 rounded-box mb-4 overflow-x-auto ring-1">
<table class="table">
<table class="table" aria-labelledby={"has-many-through-label-#{@name}"}>
<thead class="bg-base-200/50 text-base-content uppercase">
<tr>
<th
Expand All @@ -263,7 +267,11 @@ defmodule Backpex.Fields.HasManyThrough do
>
{label}
</th>
<th></th>
<th>
<span class="sr-only">
{Backpex.__("Actions", @live_resource)}
</span>
</th>
</tr>
</thead>
<tbody class="text-base-content/90">
Expand Down Expand Up @@ -361,7 +369,13 @@ defmodule Backpex.Fields.HasManyThrough do
</div>
</.modal>

<button type="button" class="btn btn-sm btn-outline btn-primary" phx-click="new-relational" phx-target={@myself}>
<button
type="button"
class="btn btn-sm btn-outline btn-primary"
phx-click="new-relational"
phx-target={@myself}
aria-labelledby={"has-many-through-label-#{@name}"}
>
{@relational_title}
</button>

Expand Down Expand Up @@ -537,7 +551,7 @@ defmodule Backpex.Fields.HasManyThrough do
~H"""
<Layout.field_container>
<:label>
<Layout.input_label text={@label} />
<Layout.input_label for={@form[@owner_key]} text={@label} />
</:label>
<BackpexForm.input
type="select"
Expand Down
48 changes: 26 additions & 22 deletions lib/backpex/fields/inline_crud.ex
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ defmodule Backpex.Fields.InlineCRUD do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label id={"inline-crud-label-#{@name}"} as="p" text={@field_options[:label]} />
</:label>

<div class="flex flex-col">
Expand All @@ -141,44 +141,48 @@ defmodule Backpex.Fields.InlineCRUD do
:for={{child_field_name, child_field_options} <- @child_fields}
class={child_field_class(child_field_options, assigns)}
>
<p :if={f_nested.index == 0} class="mb-1 text-xs">
<span
:if={f_nested.index == 0}
id={"inline-crud-header-label-#{@name}-#{child_field_name}"}
class="mb-1 text-xs"
>
{child_field_options.label}
</p>
</span>
<BackpexForm.input
type={input_type(child_field_options) |> Atom.to_string()}
field={f_nested[child_field_name]}
aria-labelledby={"inline-crud-header-label-#{@name}-#{child_field_name} inline-crud-label-#{@name}"}
translate_error_fun={Backpex.Field.translate_error_fun(child_field_options, assigns)}
phx-debounce={Backpex.Field.debounce(child_field_options, assigns)}
phx-throttle={Backpex.Field.throttle(child_field_options, assigns)}
/>
</div>

<div class={if f_nested.index == 0, do: "mt-5", else: nil}>
<label for={"#{@name}-checkbox-delete-#{f_nested.index}"}>
<input
id={"#{@name}-checkbox-delete-#{f_nested.index}"}
type="checkbox"
name={"change[#{@name}_delete][]"}
value={f_nested.index}
class="hidden"
/>

<div class="btn btn-outline btn-error" aria-label={Backpex.__("Delete", @live_resource)}>
<Backpex.HTML.CoreComponents.icon name="hero-trash" class="h-5 w-5" />
</div>
</label>
</div>
<button
type="button"
name={"change[#{@name}_delete][]"}
class={["btn btn-outline btn-error", f_nested.index == 0 && "mt-5"]}
phx-click={JS.dispatch("change")}
value={f_nested.index}
aria-label={Backpex.__({"Delete row with index %{index}", %{index: f_nested.index}}, @live_resource)}
>
<Backpex.HTML.CoreComponents.icon name="hero-trash" class="size-5" />
</button>
</div>
</.inputs_for>

<input type="hidden" name={"change[#{@name}_delete][]"} />
</div>
<input

<button
type="button"
name={"change[#{@name}_order][]"}
type="checkbox"
aria-label={Backpex.__("Add entry", @live_resource)}
class="btn btn-outline btn-sm btn-primary"
/>
phx-click={JS.dispatch("change")}
value="new"
>
{Backpex.__("Add entry", @live_resource)}
</button>

<%= if help_text = Backpex.Field.help_text(@field_options, assigns) do %>
<Backpex.HTML.Form.help_text class="mt-1">{help_text}</Backpex.HTML.Form.help_text>
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/multi_select.ex
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ defmodule Backpex.Fields.MultiSelect do
<div id={@name}>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label as="p" text={@field_options[:label]} />
</:label>
<Form.multi_select
field={@form[@name]}
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/number.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule Backpex.Fields.Number do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="number"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/select.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ defmodule Backpex.Fields.Select do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="select"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/text.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ defmodule Backpex.Fields.Text do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :center)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="text"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/textarea.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule Backpex.Fields.Textarea do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="textarea"
Expand Down
2 changes: 1 addition & 1 deletion lib/backpex/fields/time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ defmodule Backpex.Fields.Time do
<div>
<Layout.field_container>
<:label align={Backpex.Field.align_label(@field_options, assigns, :top)}>
<Layout.input_label text={@field_options[:label]} />
<Layout.input_label for={@form[@name]} text={@field_options[:label]} />
</:label>
<BackpexForm.input
type="time"
Expand Down
Loading
Loading