separate editor FAB and panel for cleaner animation
All checks were successful
deploy / deploy (push) Successful in 1m32s

Split the editor sheet into two distinct elements:
- .editor-fab: floating action button, always a pill in the corner
- .editor-panel: sliding panel that animates in/out independently

This enables proper CSS keyframe animations (slide-up/down on mobile,
slide-in/out on desktop) with a closing class for exit transitions.
Simplified the JS hook to only handle close behaviour.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-03-07 19:01:32 +00:00
parent 3f96769840
commit bd07c9c7d9
6 changed files with 230 additions and 249 deletions

View File

@@ -125,13 +125,13 @@ defmodule BerrypodWeb.Shop.CustomPageTest do
{:ok, view, _html} = live(conn, "/editable")
# Editor sheet should be visible for admins
assert has_element?(view, ".editor-sheet")
assert has_element?(view, ".editor-panel")
# Click the edit button in the sheet to enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Now the editor sheet content should be visible (sheet state changes to open)
assert has_element?(view, ".editor-sheet-content")
assert has_element?(view, ".editor-panel-content")
end
end
end

View File

@@ -32,7 +32,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
test "editor sheet is not shown for non-admins", %{conn: conn} do
{:ok, _view, html} = live(conn, "/")
refute html =~ "editor-sheet"
refute html =~ "editor-panel"
refute html =~ "Edit page"
end
end
@@ -42,14 +42,14 @@ defmodule BerrypodWeb.PageEditorHookTest do
conn = log_in_user(conn, user)
{:ok, view, _html} = live(conn, "/")
assert has_element?(view, ".editor-sheet")
assert has_element?(view, ".editor-panel")
assert has_element?(view, "button", "Edit page")
end
test "non-admin does not see editor sheet", %{conn: conn} do
{:ok, view, _html} = live(conn, "/")
refute has_element?(view, ".editor-sheet")
refute has_element?(view, ".editor-panel")
refute has_element?(view, "button", "Edit page")
end
end
@@ -63,41 +63,41 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Sheet starts collapsed
assert has_element?(view, ".editor-sheet[data-state='collapsed']")
assert has_element?(view, ".editor-panel[data-state='collapsed']")
# Click edit button (the specific edit button class)
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Now editing, sheet expanded
assert has_element?(view, ".editor-sheet[data-editing='true']")
assert has_element?(view, ".editor-sheet-content")
assert has_element?(view, ".editor-panel[data-editing='true']")
assert has_element?(view, ".editor-panel-content")
assert has_element?(view, ".block-card")
end
test "sheet shows the page title when editing", %{conn: conn} do
{:ok, view, _html} = live(conn, "/")
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
assert has_element?(view, ".editor-sheet-page-title", "Home page")
assert has_element?(view, ".editor-panel-page-title", "Home page")
end
test "sheet state changes when entering edit mode and collapsing", %{conn: conn} do
{:ok, view, _html} = live(conn, "/")
# Starts collapsed
assert has_element?(view, ".editor-sheet[data-state='collapsed']")
assert has_element?(view, ".editor-panel[data-state='collapsed']")
# Enter edit mode - expands to open
view |> element(".editor-sheet-edit-btn") |> render_click()
assert has_element?(view, ".editor-sheet[data-state='open']")
view |> element(".editor-fab") |> render_click()
assert has_element?(view, ".editor-panel[data-state='open']")
# Collapse sheet (still in edit mode, just previewing)
render_click(view, "editor_set_sheet_state", %{"state" => "collapsed"})
assert has_element?(view, ".editor-sheet[data-state='collapsed']")
assert has_element?(view, ".editor-panel[data-state='collapsed']")
# Still in edit mode
assert has_element?(view, ".editor-sheet[data-editing='true']")
assert has_element?(view, ".editor-panel[data-editing='true']")
end
end
@@ -110,7 +110,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Home page default: hero is first block
first_card = view |> element(".block-card:first-child")
@@ -134,9 +134,9 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
refute has_element?(view, ".editor-sheet-dirty")
refute has_element?(view, ".editor-panel-dirty")
# Move a block to trigger dirty state
blocks = Pages.get_page("home").blocks
@@ -146,7 +146,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
|> element("button[phx-click='editor_move_up'][phx-value-id='#{second_id}']")
|> render_click()
assert has_element?(view, ".editor-sheet-dirty")
assert has_element?(view, ".editor-panel-dirty")
end
end
@@ -159,7 +159,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Move a block to make changes
blocks = Pages.get_page("home").blocks
@@ -188,7 +188,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Get the first block type before reset (should be reversed, so last default)
first_before_reset = view |> element(".block-card:first-child") |> render()
@@ -222,7 +222,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
blocks = Pages.get_page("home").blocks
second_id = Enum.at(blocks, 1)["id"]
@@ -247,7 +247,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
blocks = Pages.get_page("home").blocks
second_id = Enum.at(blocks, 1)["id"]
@@ -268,7 +268,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
blocks = Pages.get_page("home").blocks
second_id = Enum.at(blocks, 1)["id"]
@@ -287,7 +287,7 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
# Initially both disabled
assert has_element?(view, "button[phx-click='editor_undo'][disabled]")
@@ -316,13 +316,13 @@ defmodule BerrypodWeb.PageEditorHookTest do
{:ok, view, _html} = live(conn, "/about")
# Editor sheet visible for admin
assert has_element?(view, ".editor-sheet")
assert has_element?(view, ".editor-panel")
# Enter edit mode
view |> element(".editor-sheet-edit-btn") |> render_click()
view |> element(".editor-fab") |> render_click()
assert has_element?(view, ".editor-sheet-content")
assert has_element?(view, ".editor-sheet-page-title", "About")
assert has_element?(view, ".editor-panel-content")
assert has_element?(view, ".editor-panel-page-title", "About")
assert has_element?(view, ".block-card")
end
end