Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions .claude/rules/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ undigested, so hard-reload (Cmd+Shift+R) after a rebuild. **Dev does not use
build on every CSS/template/JS change instead. Edits to `components.css` reach
the browser within ~2s; if they ever don't, suspect that watcher first.

**Text colour is never inherited onto a link or a button — every control on a
coloured surface names its own.** `components.css` sets `a, button { color:
var(--color-brand-600) }` for the classic pages, and *any* rule on the element
beats a colour the element merely **inherits** from an ancestor — specificity
never enters into it, so the utility layer winning over the components layer does
not help here. Put `text-white` on the coloured bar and the link inside it still
renders brand-600: that is how the acting-as banner shipped a brand-600 link and
button on a brand-700 bar, blue on blue and barely legible, while the sentence
beside them (a `<span>`, which no element rule names) was correctly white. So
when a surface sets a text colour for its contents, repeat that colour on every
`<a>` and `<button>` inside it; `<.button>` and the kit's other controls already
do. `acting_as_organization_test.exs` guards the banner's two.

### Don'ts

- No theme toggle (dark = system).
Expand Down
12 changes: 10 additions & 2 deletions lib/vutuv_web/live/shell_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,17 @@ defmodule VutuvWeb.ShellLive do
<span class="font-semibold">
{gettext("You are writing as %{name}.", name: @acting_as_name)}
</span>
<%!-- Both controls name `text-white` themselves rather than taking it
from the bar. `components.css` styles the classic pages with
`a, button { color: var(--color-brand-600) }`, and a rule on the
element beats a colour INHERITED from an ancestor — so on this
brand-700 bar the link and the button came out brand-600 on brand-700,
which is barely legible. The same trap waits for any control on a
coloured surface. --%>
<.link
navigate={@acting_as_path}
class="underline decoration-white/50 underline-offset-2 hover:decoration-white"
id="open-acting-as-page"
class="font-medium text-white underline decoration-white/60 underline-offset-2 hover:decoration-white"
>
{gettext("Open the page")}
</.link>
Expand All @@ -511,7 +519,7 @@ defmodule VutuvWeb.ShellLive do
href={~p"/system/act_as"}
method="delete"
id="stop-acting-as"
class="ml-auto inline-flex min-h-10 items-center rounded-lg bg-white/15 px-3 font-semibold hover:bg-white/25"
class="ml-auto inline-flex min-h-10 items-center rounded-lg bg-white/20 px-3 font-semibold text-white hover:bg-white/30"
>
{gettext("Write as myself again")}
</.link>
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Vutuv.MixProject do
def project do
[
app: :vutuv,
version: "7.268.1",
version: "7.268.2",
elixir: "~> 1.20",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
Expand Down
19 changes: 19 additions & 0 deletions test/vutuv_web/acting_as_organization_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ defmodule VutuvWeb.ActingAsOrganizationTest do
assert html =~ "stop-acting-as"
end

test "both controls in the banner set their own text colour", %{conn: conn} do
%{conn: conn} = switched_in(conn)

doc = conn |> get(~p"/feed") |> html_response(200) |> LazyHTML.from_document()

# Not cosmetics: `components.css` styles the legacy pages with
# `a, button { color: var(--color-brand-600) }`, and a rule on the element
# beats a colour INHERITED from an ancestor — so on the brand-700 bar both
# controls came out brand-600 on brand-700, which is unreadable. Every
# control on a coloured surface has to name its own colour.
for id <- ~w(open-acting-as-page stop-acting-as) do
assert [class] = doc |> LazyHTML.query("##{id}") |> LazyHTML.attribute("class"),
"the banner has no ##{id}"

assert class =~ "text-white",
"##{id} inherits its colour, so the legacy `a, button` rule wins"
end
end

test "a member without the publisher role cannot", %{conn: conn} do
{conn, owner} = create_and_login_user(conn)
organization = active_organization_for(owner)
Expand Down