Improve icon buttons accessibility and navigation (#667)

* Rename tooltip source attribute

* Add aria-label to icon buttons/links

* Actually focus cell content when navigating around

* Add some descriptions

* Fix dynamically computed tooltips
This commit is contained in:
Jonatan Kłosko 2021-11-01 18:20:56 +01:00 committed by GitHub
parent 03842d8cd1
commit 021d6ac42e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 106 additions and 67 deletions

View file

@ -3,7 +3,7 @@
/*
Example usage:
<span class="tooltip top" aria-label="Delete">
<span class="tooltip top" data-tooltip="Delete">
...
</span>
*/
@ -28,7 +28,7 @@ Example usage:
/* Tooltip text */
.tooltip:before {
position: absolute;
content: attr(aria-label);
content: attr(data-tooltip);
white-space: pre;
text-align: center;
display: block;

View file

@ -728,6 +728,9 @@ function setFocusedCell(hook, cellId, scroll = true) {
hook.state.focusedSectionId = getSectionIdByCellId(
hook.state.focusedCellId
);
// Focus the primary cell content, this is important for screen readers
const cellBody = cell.querySelector(`[data-element="cell-body"]`);
cellBody.focus();
} else {
hook.state.focusedCellType = null;
hook.state.focusedSectionId = null;

View file

@ -110,7 +110,7 @@ defmodule LivebookWeb.Helpers do
|> assign(:attrs, assigns_to_attributes(assigns, [:icon, :class]))
~H"""
<i class={"ri-#{@icon} #{@class}"} {@attrs}></i>
<i class={"ri-#{@icon} #{@class}"} aria-hidden="true" {@attrs}></i>
"""
end

View file

@ -147,7 +147,7 @@ defmodule LivebookWeb.HomeLive do
defp open_button_tooltip_attrs(file, file_info) do
if regular?(file, file_info) and not writable?(file_info) do
[class: "tooltip top", aria_label: "This file is write-protected, please fork instead"]
[class: "tooltip top", data_tooltip: "This file is write-protected, please fork instead"]
else
[]
end

View file

@ -51,8 +51,8 @@ defmodule LivebookWeb.Output.TableDynamicLive do
<!-- Actions -->
<div class="flex space-x-2">
<%= if :refetch in @features do %>
<span class="tooltip left" aria-label="Refetch">
<button class="icon-button" phx-click="refetch">
<span class="tooltip left" data-tooltip="Refetch">
<button class="icon-button" aria-label="refresh" phx-click="refetch">
<.remix_icon icon="refresh-line" class="text-xl" />
</button>
</span>

View file

@ -170,17 +170,17 @@ defmodule LivebookWeb.SessionLive do
<span><%= user.name || "Anonymous" %></span>
</button>
<%= if client_pid != @self do %>
<span class="tooltip left" aria-label="Follow this user"
<span class="tooltip left" data-tooltip="Follow this user"
data-element="client-follow-toggle"
data-meta="follow">
<button class="icon-button">
<button class="icon-button" aria-label="follow this user">
<.remix_icon icon="pushpin-line" class="text-lg" />
</button>
</span>
<span class="tooltip left" aria-label="Unfollow this user"
<span class="tooltip left" data-tooltip="Unfollow this user"
data-element="client-follow-toggle"
data-meta="unfollow">
<button class="icon-button">
<button class="icon-button" aria-label="unfollow this user">
<.remix_icon icon="pushpin-fill" class="text-lg" />
</button>
</span>
@ -195,6 +195,7 @@ defmodule LivebookWeb.SessionLive do
<div class="w-full max-w-screen-lg px-16 mx-auto py-7">
<div class="flex items-center pb-4 mb-6 space-x-4 border-b border-gray-200">
<h1 class="flex-grow p-1 -ml-1 text-3xl font-semibold text-gray-800 border border-transparent rounded-lg hover:border-blue-200 focus:border-blue-300"
aria-description="notebook title"
id="notebook-name"
data-element="notebook-name"
contenteditable
@ -402,7 +403,7 @@ defmodule LivebookWeb.SessionLive do
wrapped_name = Livebook.Utils.wrap_line("" <> parent_name <> "", 16)
label = "Branches from\n#{wrapped_name}"
[class: "tooltip #{direction}", "aria-label": label]
[class: "tooltip #{direction}", data_tooltip: label]
end
@impl true

View file

@ -70,16 +70,18 @@ defmodule LivebookWeb.SessionLive.BinComponent do
<span class="font-semibold"><%= format_date_relatively(entry.deleted_at) %></span>
</p>
<div class="flex justify-end space-x-2">
<span class="tooltip left" aria-label="Copy source">
<span class="tooltip left" data-tooltip="Copy source">
<button class="icon-button"
aria-label="copy source"
id={"bin-cell-#{cell.id}-clipcopy"}
phx-hook="ClipCopy"
data-target-id={"bin-cell-#{cell.id}-source"}>
<.remix_icon icon="clipboard-line" class="text-lg" />
</button>
</span>
<span class="tooltip left" aria-label="Restore">
<span class="tooltip left" data-tooltip="Restore">
<button class="icon-button"
aria-label="restore"
phx-click="restore"
phx-value-cell_id={entry.cell.id}
phx-target={@myself}>

View file

@ -21,14 +21,15 @@ defmodule LivebookWeb.SessionLive.CellComponent do
<div class="mb-1 flex items-center justify-end">
<div class="relative z-20 flex items-center justify-end space-x-2" data-element="actions">
<.cell_link_button cell_id={@cell_view.id} />
<span class="tooltip top" aria-label="Edit content" data-element="enable-insert-mode-button">
<button class="icon-button">
<span class="tooltip top" data-tooltip="Edit content" data-element="enable-insert-mode-button">
<button class="icon-button" aria-label="edit content">
<.remix_icon icon="pencil-line" class="text-xl" />
</button>
</span>
<span class="tooltip top" aria-label="Insert image" data-element="insert-image-button">
<span class="tooltip top" data-tooltip="Insert image" data-element="insert-image-button">
<%= live_patch to: Routes.session_path(@socket, :cell_upload, @session_id, @cell_view.id),
class: "icon-button" do %>
class: "icon-button",
aria_label: "insert image" do %>
<.remix_icon icon="image-add-line" class="text-xl" />
<% end %>
</span>
@ -240,7 +241,8 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp cell_body(assigns) do
~H"""
<div class="flex relative">
<!-- By setting tabindex="-1" we can programmatically focus this element -->
<div class="flex relative" data-element="cell-body" tabindex="-1">
<div class="w-1 h-full rounded-lg absolute top-0 -left-3" data-element="cell-focus-indicator">
</div>
<div class="w-full">
@ -252,8 +254,8 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp cell_link_button(assigns) do
~H"""
<span class="tooltip top" aria-label="Link">
<a href={"#cell-#{@cell_id}"} class="icon-button">
<span class="tooltip top" data-tooltip="Link">
<a href={"#cell-#{@cell_id}"} class="icon-button" aria-label="link to cell">
<.remix_icon icon="link" class="text-xl" />
</a>
</span>
@ -262,8 +264,10 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp cell_settings_button(assigns) do
~H"""
<span class="tooltip top" aria-label="Cell settings">
<%= live_patch to: Routes.session_path(@socket, :cell_settings, @session_id, @cell_id), class: "icon-button" do %>
<span class="tooltip top" data-tooltip="Cell settings">
<%= live_patch to: Routes.session_path(@socket, :cell_settings, @session_id, @cell_id),
class: "icon-button",
aria_label: "cell settings" do %>
<.remix_icon icon="settings-3-line" class="text-xl" />
<% end %>
</span>
@ -272,8 +276,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp move_cell_up_button(assigns) do
~H"""
<span class="tooltip top" aria-label="Move up">
<span class="tooltip top" data-tooltip="Move up">
<button class="icon-button"
aria-label="move cell up"
phx-click="move_cell"
phx-value-cell_id={@cell_id}
phx-value-offset="-1">
@ -285,8 +290,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp move_cell_down_button(assigns) do
~H"""
<span class="tooltip top" aria-label="Move down">
<span class="tooltip top" data-tooltip="Move down">
<button class="icon-button"
aria-label="move cell down"
phx-click="move_cell"
phx-value-cell_id={@cell_id}
phx-value-offset="1">
@ -298,8 +304,9 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp delete_cell_button(assigns) do
~H"""
<span class="tooltip top" aria-label="Delete">
<span class="tooltip top" data-tooltip="Delete">
<button class="icon-button"
aria-label="delete cell"
phx-click="delete_cell"
phx-value-cell_id={@cell_id}>
<.remix_icon icon="delete-bin-6-line" class="text-xl" />
@ -406,7 +413,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do
|> assign_new(:tooltip, fn -> nil end)
~H"""
<div class={"#{if(@tooltip, do: "tooltip")} bottom distant-medium"} aria-label={@tooltip}>
<div class={"#{if(@tooltip, do: "tooltip")} bottom distant-medium"} data-tooltip={@tooltip}>
<div class="flex items-center space-x-1">
<div class="flex text-xs text-gray-400">
<%= render_block(@inner_block) %>

View file

@ -31,16 +31,18 @@ defmodule LivebookWeb.SessionLive.ExportElixirComponent do
.exs
</span>
<div class="flex justify-end space-x-2">
<span class="tooltip left" aria-label="Copy source">
<span class="tooltip left" data-tooltip="Copy source">
<button class="icon-button"
aria-label="copy source"
id="export-notebook-source-clipcopy"
phx-hook="ClipCopy"
data-target-id="export-notebook-source">
<.remix_icon icon="clipboard-line" class="text-lg" />
</button>
</span>
<span class="tooltip left" aria-label="Download source">
<span class="tooltip left" data-tooltip="Download source">
<a class="icon-button"
aria-label="download source"
href={Routes.session_path(@socket, :download_source, @session.id, "exs")}>
<.remix_icon icon="download-2-line" class="text-lg" />
</a>

View file

@ -38,16 +38,18 @@ defmodule LivebookWeb.SessionLive.ExportLiveMarkdownComponent do
.livemd
</span>
<div class="flex justify-end space-x-2">
<span class="tooltip left" aria-label="Copy source">
<span class="tooltip left" data-tooltip="Copy source">
<button class="icon-button"
aria-label="copy source"
id="export-notebook-source-clipcopy"
phx-hook="ClipCopy"
data-target-id="export-notebook-source">
<.remix_icon icon="clipboard-line" class="text-lg" />
</button>
</span>
<span class="tooltip left" aria-label="Download source">
<span class="tooltip left" data-tooltip="Download source">
<a class="icon-button"
aria-label="download source"
href={Routes.session_path(@socket, :download_source, @session.id, "livemd", include_outputs: @include_outputs)}>
<.remix_icon icon="download-2-line" class="text-lg" />
</a>

View file

@ -8,32 +8,36 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
<%= if @file do %>
<%= if @dirty do %>
<%= if @autosave_interval_s do %>
<span class="tooltip left" aria-label="Autosave pending">
<span class="tooltip left" data-tooltip="Autosave pending">
<%= live_patch to: Routes.session_path(@socket, :file_settings, @session_id),
class: "icon-button icon-outlined-button border-blue-400 hover:bg-blue-50 focus:bg-blue-50" do %>
class: "icon-button icon-outlined-button border-blue-400 hover:bg-blue-50 focus:bg-blue-50",
aria_label: "autosave pending, click to open file settings" do %>
<.remix_icon icon="save-line" class="text-xl text-blue-500" />
<% end %>
</span>
<% else %>
<span class="tooltip left" aria-label="No autosave configured, make sure to save manually">
<span class="tooltip left" data-tooltip="No autosave configured, make sure to save manually">
<%= live_patch to: Routes.session_path(@socket, :file_settings, @session_id),
class: "icon-button icon-outlined-button border-yellow-200 hover:bg-red-50 focus:bg-red-50" do %>
class: "icon-button icon-outlined-button border-yellow-200 hover:bg-red-50 focus:bg-red-50",
aria_label: "no autosave configured, click to open file settings" do %>
<.remix_icon icon="save-line" class="text-xl text-yellow-300" />
<% end %>
</span>
<% end %>
<% else %>
<span class="tooltip left" aria-label="Notebook saved">
<span class="tooltip left" data-tooltip="Notebook saved">
<%= live_patch to: Routes.session_path(@socket, :file_settings, @session_id),
class: "icon-button icon-outlined-button border-green-300 hover:bg-green-50 focus:bg-green-50" do %>
class: "icon-button icon-outlined-button border-green-300 hover:bg-green-50 focus:bg-green-50",
aria_label: "notebook saved, click to open file settings" do %>
<.remix_icon icon="save-line" class="text-xl text-green-400" />
<% end %>
</span>
<% end %>
<% else %>
<span class="tooltip left" aria-label="Choose a file to save the notebook">
<span class="tooltip left" data-tooltip="Choose a file to save the notebook">
<%= live_patch to: Routes.session_path(@socket, :file_settings, @session_id),
class: "icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100" do %>
class: "icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100",
aria_label: "choose a file to save the notebook" do %>
<.remix_icon icon="save-line" class="text-xl text-gray-400" />
<% end %>
</span>
@ -44,16 +48,17 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
status={elem(@global_status, 0)}
cell_id={elem(@global_status, 1)} />
<% else %>
<span class="tooltip left" aria-label="Choose a runtime to run the notebook in">
<span class="tooltip left" data-tooltip="Choose a runtime to run the notebook in">
<%= live_patch to: Routes.session_path(@socket, :runtime_settings, @session_id),
class: "icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100" do %>
class: "icon-button icon-outlined-button border-gray-200 hover:bg-gray-100 focus:bg-gray-100",
aria_label: "choose a runtime to run the notebook in" do %>
<.remix_icon icon="loader-3-line" class="text-xl text-gray-400" />
<% end %>
</span>
<% end %>
<%# Note: this indicator is shown/hidden using CSS based on the current mode %>
<span class="tooltip left" aria-label="Insert mode" data-element="insert-mode-indicator">
<span class="tooltip left" data-tooltip="Insert mode" data-element="insert-mode-indicator">
<span class="text-sm font-medium text-gray-400 cursor-default">
ins
</span>
@ -64,8 +69,9 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
defp global_status(%{status: :evaluating} = assigns) do
~H"""
<span class="tooltip left" aria-label="Go to evaluating cell">
<span class="tooltip left" data-tooltip="Go to evaluating cell">
<button class="border-blue-400 icon-button icon-outlined-button hover:bg-blue-50 focus:bg-blue-50"
aria-label="go to evaluating cell"
data-element="focus-cell-button"
data-target={@cell_id}>
<.remix_icon icon="loader-3-line" class="text-xl text-blue-500 animate-spin" />
@ -76,8 +82,9 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
defp global_status(%{status: :evaluated} = assigns) do
~H"""
<span class="tooltip left" aria-label="Go to last evaluated cell">
<span class="tooltip left" data-tooltip="Go to last evaluated cell">
<button class="border-green-300 icon-button icon-outlined-button hover:bg-green-50 focus:bg-green-50"
aria-label="go to last evaluated cell"
data-element="focus-cell-button"
data-target={@cell_id}>
<.remix_icon icon="loader-3-line" class="text-xl text-green-400" />
@ -88,8 +95,9 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
defp global_status(%{status: :stale} = assigns) do
~H"""
<span class="tooltip left" aria-label="Go to first stale cell">
<span class="tooltip left" data-tooltip="Go to first stale cell">
<button class="border-yellow-200 icon-button icon-outlined-button hover:bg-yellow-50 focus:bg-yellow-50"
aria-label="go to first stale cell"
data-element="focus-cell-button"
data-target={@cell_id}>
<.remix_icon icon="loader-3-line" class="text-xl text-yellow-300" />
@ -100,10 +108,11 @@ defmodule LivebookWeb.SessionLive.IndicatorsComponent do
defp global_status(%{status: :fresh} = assigns) do
~H"""
<span class="tooltip left" aria-label="Ready to evaluate">
<button class="border-gray-200 cursor-default icon-button icon-outlined-button hover:bg-gray-100 focus:bg-gray-100">
<span class="tooltip left" data-tooltip="Ready to evaluate">
<div class="border-gray-200 icon-button icon-outlined-button hover:bg-gray-100 focus:bg-gray-100"
aria-label="ready to evaluate">
<.remix_icon icon="loader-3-line" class="text-xl text-gray-400" />
</button>
</div>
</span>
"""
end

View file

@ -71,7 +71,7 @@ defmodule LivebookWeb.SessionLive.PersistenceLive do
<div class="flex space-x-2 items-center">
<span class="text-gray-700 whitespace-nowrap">File:</span>
<%= if @new_attrs.file do %>
<span class="tooltip right" aria-label={file_system_label(@new_attrs.file.file_system)}>
<span class="tooltip right" data-tooltip={file_system_label(@new_attrs.file.file_system)}>
<span class="flex items-center">
[<.file_system_icon file_system={@new_attrs.file.file_system} />]
</span>

View file

@ -7,6 +7,7 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
<div class="flex space-x-4 items-center" data-element="section-headline">
<h2 class="flex-grow text-gray-800 font-semibold text-2xl px-1 -ml-1 rounded-lg border
border-transparent hover:border-blue-200 focus:border-blue-300"
aria-description="section title"
data-element="section-name"
id={@section_view.html_id}
contenteditable
@ -18,15 +19,17 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
<%# ^ Note it's important there's no space between <h2> and </h2>
because we want the content to exactly match section name. %>
<div class="flex space-x-2 items-center" data-element="section-actions">
<span class="tooltip top" aria-label="Link">
<a href={"##{@section_view.html_id}"} class="icon-button">
<span class="tooltip top" data-tooltip="Link">
<a href={"##{@section_view.html_id}"} class="icon-button" aria-label="link to section">
<.remix_icon icon="link" class="text-xl" />
</a>
</span>
<%= if @section_view.valid_parents != [] and not @section_view.has_children? do %>
<div class="relative" id={"section-#{@section_view.id}-branch-menu"} phx-hook="Menu" data-element="menu">
<span class="tooltip top" aria-label="Branch out from">
<button class="icon-button" data-toggle>
<span class="tooltip top" data-tooltip="Branch out from">
<button class="icon-button"
aria-label="branch out from other section"
data-toggle>
<.remix_icon icon="git-branch-line" class="text-xl flip-horizontally" />
</button>
</span>
@ -52,25 +55,28 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
</div>
</div>
<% end %>
<span class="tooltip top" aria-label="Move up">
<span class="tooltip top" data-tooltip="Move up">
<button class="icon-button"
aria-label="move section up"
phx-click="move_section"
phx-value-section_id={@section_view.id}
phx-value-offset="-1">
<.remix_icon icon="arrow-up-s-line" class="text-xl" />
</button>
</span>
<span class="tooltip top" aria-label="Move down">
<span class="tooltip top" data-tooltip="Move down">
<button class="icon-button"
aria-label="move section down"
phx-click="move_section"
phx-value-section_id={@section_view.id}
phx-value-offset="1">
<.remix_icon icon="arrow-down-s-line" class="text-xl" />
</button>
</span>
<span class="tooltip top" aria-label={if @section_view.has_children?, do: "Cannot delete this section because\nother sections branch from it", else: "Delete"}>
<span class="tooltip top" data-tooltip={if @section_view.has_children?, do: "Cannot delete this section because\nother sections branch from it", else: "Delete"}>
<%= live_patch to: Routes.session_path(@socket, :delete_section, @session_id, @section_view.id),
class: "icon-button #{if @section_view.has_children?, do: "disabled"}" do %>
class: "icon-button #{if @section_view.has_children?, do: "disabled"}",
aria_label: "delete section" do %>
<.remix_icon icon="delete-bin-6-line" class="text-xl" />
<% end %>
</span>
@ -78,7 +84,7 @@ defmodule LivebookWeb.SessionLive.SectionComponent do
</div>
<%= if @section_view.parent do %>
<h3 class="mt-1 flex items-end space-x-1 text-sm font-semibold text-gray-800">
<span class="tooltip bottom" aria-label={"This section branches out from the main flow\nand can be evaluated in parallel"}>
<span class="tooltip bottom" data-tooltip={"This section branches out from the main flow\nand can be evaluated in parallel"}>
<.remix_icon icon="git-branch-line" class="text-lg font-normal flip-horizontally leading-none" />
</span>
<span class="leading-none">from <%= @section_view.parent.name %></span>

View file

@ -54,8 +54,9 @@ defmodule LivebookWeb.SettingsLive do
<h2 class="text-xl text-gray-800 font-semibold">
File systems
</h2>
<span class="tooltip top" aria-label="Copy as environment variables">
<span class="tooltip top" data-tooltip="Copy as environment variables">
<button class="icon-button"
aria-label="copy as environment variables"
id={"file-systems-env-clipcopy"}
phx-hook="ClipCopy"
data-target-id={"file-systems-env-source"}

View file

@ -23,8 +23,8 @@ defmodule LivebookWeb.SidebarHelpers do
def logo_item(assigns) do
~H"""
<span>
<%= live_patch to: Routes.home_path(@socket, :page) do %>
<img src="/images/logo.png" height="40" width="40" alt="livebook" />
<%= live_patch to: Routes.home_path(@socket, :page), aria_label: "go to homepage" do %>
<img src="/images/logo.png" height="40" width="40" alt="" />
<% end %>
</span>
"""
@ -32,8 +32,9 @@ defmodule LivebookWeb.SidebarHelpers do
def button_item(assigns) do
~H"""
<span class="tooltip right distant" aria-label={@label}>
<span class="tooltip right distant" data-tooltip={@label}>
<button class="text-2xl text-gray-400 hover:text-gray-50 focus:text-gray-50 rounded-xl h-10 w-10 flex items-center justify-center"
aria-label={@label}
data-element={@data_element}>
<.remix_icon icon={@icon} />
</button>
@ -43,9 +44,10 @@ defmodule LivebookWeb.SidebarHelpers do
def link_item(assigns) do
~H"""
<span class="tooltip right distant" aria-label={@label}>
<span class="tooltip right distant" data-tooltip={@label}>
<%= live_patch to: @path,
class: "text-gray-400 hover:text-gray-50 focus:text-gray-50 rounded-xl h-10 w-10 flex items-center justify-center #{if(@active, do: "text-gray-50 bg-gray-700")}" do %>
class: "text-gray-400 hover:text-gray-50 focus:text-gray-50 rounded-xl h-10 w-10 flex items-center justify-center #{if(@active, do: "text-gray-50 bg-gray-700")}",
aria_label: @label do %>
<.remix_icon icon={@icon} class="text-2xl" />
<% end %>
</span>
@ -60,8 +62,10 @@ defmodule LivebookWeb.SidebarHelpers do
def user_item(assigns) do
~H"""
<span class="tooltip right distant" aria-label="User profile">
<%= live_patch to: @path, class: "text-gray-400 rounded-xl h-8 w-8 flex items-center justify-center" do %>
<span class="tooltip right distant" data-tooltip="User profile">
<%= live_patch to: @path,
class: "text-gray-400 rounded-xl h-8 w-8 flex items-center justify-center",
aria_label: "user profile" do %>
<.user_avatar user={@current_user} text_class="text-xs" />
<% end %>
</span>

View file

@ -17,7 +17,9 @@ defmodule LivebookWeb.UserHelpers do
|> assign_new(:text_class, fn -> "" end)
~H"""
<div class={"#{@class} rounded-full flex items-center justify-center"} style={"background-color: #{@user.hex_color}"}>
<div class={"#{@class} rounded-full flex items-center justify-center"}
style={"background-color: #{@user.hex_color}"}
aria-hidden="true">
<div class={"#{@text_class} text-gray-100 font-semibold"}>
<%= avatar_text(@user.name) %>
</div>

View file

@ -106,7 +106,7 @@ defmodule LivebookWeb.HomeLiveTest do
|> has_element?()
assert view
|> element(~s{[aria-label="This file is write-protected, please fork instead"]})
|> element(~s{[data-tooltip="This file is write-protected, please fork instead"]})
|> has_element?()
end
end