Improve tab navigation (#109)

* Ignore editor for tab movement

* Improve tab behaviour within notebook

* Highlight focused regular buttons

* Show tooltips on focused elements
This commit is contained in:
Jonatan Kłosko 2021-03-23 14:10:34 +01:00 committed by GitHub
parent 2846503da6
commit af79a0fd2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 71 additions and 51 deletions

View file

@ -5,7 +5,7 @@
}
.button:not(:disabled) {
@apply hover:bg-gray-50;
@apply hover:bg-gray-50 focus:bg-gray-50;
}
.button:disabled {
@ -21,7 +21,7 @@
}
.button-danger:not(:disabled) {
@apply hover:bg-red-100;
@apply hover:bg-red-100 focus:bg-red-100;
}
.button-primary {
@ -29,7 +29,7 @@
}
.button-primary:not(:disabled) {
@apply hover:bg-blue-700;
@apply hover:bg-blue-700 focus:bg-blue-700;
}
.choice-button {
@ -40,6 +40,18 @@
@apply bg-blue-100 border-blue-600;
}
.icon-button {
@apply p-1 flex items-center justify-center text-gray-400 hover:text-gray-800;
}
.icon-button:focus {
@apply rounded-full bg-gray-100;
}
.icon-button i {
line-height: 1;
}
/* Form fields */
.input {
@ -88,9 +100,3 @@
.tabs .tab.active {
@apply text-blue-600 border-blue-600;
}
/* Icons */
.action-icon {
@apply text-gray-400 hover:text-gray-800;
}

View file

@ -42,13 +42,16 @@ solely client-side operations.
@apply border-blue-300 border-opacity-100;
}
[data-element="cell"]:not([data-js-focused]) [data-element="actions"] {
@apply invisible;
[data-element="cell"]:not([data-js-focused])
[data-element="actions"]:not(:focus-within) {
/* Note: using opacity, so the buttons are focusable (via tab navigation)
and when focused we show the actions back. */
@apply opacity-0 pointer-events-none;
}
[data-element="cell"]:not([data-js-focused]):hover
[data-element="primary-actions"] {
@apply visible;
[data-element="actions"][data-primary] {
@apply opacity-100 pointer-events-auto;
}
[data-element="section-list-item"][data-js-is-viewed] {

View file

@ -11,7 +11,7 @@ Example usage:
/* Tooltip element wrapping the actual hoverable element */
.tooltip {
position: relative;
--distance: 0px;
--distance: 4px;
--arrow-size: 5px;
--show-delay: 0.5s;
}
@ -55,12 +55,14 @@ Example usage:
transition-delay: 0s;
}
.tooltip:hover:before {
.tooltip:hover:before,
.tooltip:focus-within:before {
visibility: visible;
transition-delay: var(--show-delay);
}
.tooltip:hover:after {
.tooltip:hover:after,
.tooltip:focus-within:after {
visibility: visible;
transition-delay: var(--show-delay);
}

View file

@ -78,6 +78,7 @@ class LiveEditor {
renderLineHighlight: "none",
theme: "custom",
fontFamily: "JetBrains Mono",
tabIndex: -1,
});
this.editor.getModel().updateOptions({

View file

@ -16,31 +16,34 @@ defmodule LivebookWeb.CellComponent do
def render_cell_content(%{cell: %{type: :markdown}} = assigns) do
~L"""
<div class="mb-1 flex items-center justify-end" data-element="actions">
<div class="relative z-10 flex items-center justify-end space-x-2">
<div class="mb-1 flex items-center justify-end">
<div class="relative z-10 flex items-center justify-end space-x-2" data-element="actions">
<span class="tooltip top" aria-label="Edit content">
<button data-element="enable-insert-mode-button">
<%= remix_icon("pencil-line", class: "text-xl action-icon") %>
<button class="icon-button" data-element="enable-insert-mode-button">
<%= remix_icon("pencil-line", class: "text-xl") %>
</button>
</span>
<span class="tooltip top" aria-label="Move up">
<button phx-click="move_cell"
<button class="icon-button"
phx-click="move_cell"
phx-value-cell_id="<%= @cell.id %>"
phx-value-offset="-1">
<%= remix_icon("arrow-up-s-line", class: "text-xl action-icon") %>
<%= remix_icon("arrow-up-s-line", class: "text-xl") %>
</button>
</span>
<span class="tooltip top" aria-label="Move down">
<button phx-click="move_cell"
<button class="icon-button"
phx-click="move_cell"
phx-value-cell_id="<%= @cell.id %>"
phx-value-offset="1">
<%= remix_icon("arrow-down-s-line", class: "text-xl action-icon") %>
<%= remix_icon("arrow-down-s-line", class: "text-xl") %>
</button>
</span>
<span class="tooltip top" aria-label="Delete">
<button phx-click="delete_cell"
<button class="icon-button"
phx-click="delete_cell"
phx-value-cell_id="<%= @cell.id %>">
<%= remix_icon("delete-bin-6-line", class: "text-xl action-icon") %>
<%= remix_icon("delete-bin-6-line", class: "text-xl") %>
</button>
</span>
</div>
@ -64,10 +67,10 @@ defmodule LivebookWeb.CellComponent do
def render_cell_content(%{cell: %{type: :elixir}} = assigns) do
~L"""
<div class="mb-1 flex justify-between" data-element="actions">
<div class="relative z-10 flex items-center justify-end space-x-2" data-element="primary-actions">
<div class="mb-1 flex justify-between">
<div class="relative z-10 flex items-center justify-end space-x-2" data-element="actions" data-primary>
<%= if @cell_info.evaluation_status == :ready do %>
<button class="text-gray-600 hover:text-gray-800 flex space-x-1 items-center"
<button class="text-gray-600 hover:text-gray-800 focus:text-gray-800 flex space-x-1 items-center"
phx-click="queue_cell_evaluation"
phx-value-cell_id="<%= @cell.id %>">
<%= remix_icon("play-circle-fill", class: "text-xl") %>
@ -76,7 +79,7 @@ defmodule LivebookWeb.CellComponent do
</span>
</button>
<% else %>
<button class="text-gray-600 hover:text-gray-800 flex space-x-1 items-center"
<button class="text-gray-600 hover:text-gray-800 focus:text-gray-800 flex space-x-1 items-center"
phx-click="cancel_cell_evaluation"
phx-value-cell_id="<%= @cell.id %>">
<%= remix_icon("stop-circle-fill", class: "text-xl") %>
@ -86,30 +89,33 @@ defmodule LivebookWeb.CellComponent do
</button>
<% end %>
</div>
<div class="relative z-10 flex items-center justify-end space-x-2">
<div class="relative z-10 flex items-center justify-end space-x-2" data-element="actions">
<span class="tooltip top" aria-label="Cell settings">
<%= live_patch to: Routes.session_path(@socket, :cell_settings, @session_id, @cell.id) do %>
<%= remix_icon("list-settings-line", class: "text-xl action-icon") %>
<%= live_patch to: Routes.session_path(@socket, :cell_settings, @session_id, @cell.id), class: "icon-button" do %>
<%= remix_icon("list-settings-line", class: "text-xl") %>
<% end %>
</span>
<span class="tooltip top" aria-label="Move up">
<button phx-click="move_cell"
<button class="icon-button"
phx-click="move_cell"
phx-value-cell_id="<%= @cell.id %>"
phx-value-offset="-1">
<%= remix_icon("arrow-up-s-line", class: "text-xl action-icon") %>
<%= remix_icon("arrow-up-s-line", class: "text-xl") %>
</button>
</span>
<span class="tooltip top" aria-label="Move down">
<button phx-click="move_cell"
<button class="icon-button"
phx-click="move_cell"
phx-value-cell_id="<%= @cell.id %>"
phx-value-offset="1">
<%= remix_icon("arrow-down-s-line", class: "text-xl action-icon") %>
<%= remix_icon("arrow-down-s-line", class: "text-xl") %>
</button>
</span>
<span class="tooltip top" aria-label="Delete">
<button phx-click="delete_cell"
<button class="icon-button"
phx-click="delete_cell"
phx-value-cell_id="<%= @cell.id %>">
<%= remix_icon("delete-bin-6-line", class: "text-xl action-icon") %>
<%= remix_icon("delete-bin-6-line", class: "text-xl") %>
</button>
</span>
</div>

View file

@ -4,15 +4,15 @@ defmodule LivebookWeb.InsertCellComponent do
def render(assigns) do
~L"""
<div class="relative top-0.5 m-0 flex justify-center">
<div class="absolute z-10 <%= if(@persistent, do: "opacity-100", else: "opacity-0") %> hover:opacity-100 flex space-x-2 justify-center items-center">
<button class="py-1 px-2 text-sm text-gray-600 font-medium rounded-lg border border-gray-200 bg-gray-50 hover:bg-gray-100"
<div class="absolute z-10 <%= if(@persistent, do: "opacity-100", else: "opacity-0") %> hover:opacity-100 focus-within:opacity-100 flex space-x-2 justify-center items-center">
<button class="py-1 px-2 text-sm text-gray-600 font-medium rounded-lg border border-gray-200 bg-gray-50 hover:bg-gray-100 focus:bg-gray-100"
phx-click="insert_cell"
phx-value-type="markdown"
phx-value-section_id="<%= @section_id %>"
phx-value-index="<%= @index %>">
+ Markdown
</button>
<button class="py-1 px-2 text-sm text-gray-600 font-medium rounded-lg border border-gray-200 bg-gray-50 hover:bg-gray-100"
<button class="py-1 px-2 text-sm text-gray-600 font-medium rounded-lg border border-gray-200 bg-gray-50 hover:bg-gray-100 focus:bg-gray-100"
phx-click="insert_cell"
phx-value-type="elixir"
phx-value-section_id="<%= @section_id %>"

View file

@ -18,8 +18,8 @@ defmodule LivebookWeb.SectionComponent do
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="Delete">
<button phx-click="delete_section" phx-value-section_id="<%= @section.id %>" tabindex="-1">
<%= remix_icon("delete-bin-6-line", class: "text-xl action-icon") %>
<button class="icon-button" phx-click="delete_section" phx-value-section_id="<%= @section.id %>" tabindex="-1">
<%= remix_icon("delete-bin-6-line", class: "text-xl") %>
</button>
</span>
</div>

View file

@ -79,19 +79,21 @@ defmodule LivebookWeb.SessionLive do
</div>
<% end %>
<span class="tooltip right distant" aria-label="Sections">
<button class="text-2xl text-gray-600 hover:text-gray-50" data-element="sections-panel-toggle">
<button class="text-2xl text-gray-600 hover:text-gray-50 focus:text-gray-50" data-element="sections-panel-toggle">
<%= remix_icon("booklet-fill") %>
</button>
</span>
<span class="tooltip right distant" aria-label="Notebook settings">
<%= live_patch to: Routes.session_path(@socket, :settings, @session_id, "file") do %>
<%= remix_icon("settings-4-fill", class: "text-2xl text-gray-600 hover:text-gray-50 #{if(@live_action == :settings, do: "text-gray-50")}") %>
<%= live_patch to: Routes.session_path(@socket, :settings, @session_id, "file"),
class: "text-gray-600 hover:text-gray-50 focus:text-gray-50 #{if(@live_action == :settings, do: "text-gray-50")}" do %>
<%= remix_icon("settings-4-fill", class: "text-2xl") %>
<% end %>
</span>
<div class="flex-grow"></div>
<span class="tooltip right distant" aria-label="Keyboard shortcuts">
<%= live_patch to: Routes.session_path(@socket, :shortcuts, @session_id) do %>
<%= remix_icon("keyboard-box-fill", class: "text-2xl text-gray-600 hover:text-gray-50") %>
<%= live_patch to: Routes.session_path(@socket, :shortcuts, @session_id),
class: "text-gray-600 hover:text-gray-50 focus:text-gray-50" do %>
<%= remix_icon("keyboard-box-fill", class: "text-2xl") %>
<% end %>
</span>
</div>

View file

@ -17,8 +17,8 @@ defmodule LivebookWeb.SessionsComponent do
</div>
</div>
<div class="relative">
<button data-element="menu-toggle">
<%= remix_icon("more-2-fill", class: "text-xl action-icon") %>
<button class="icon-button" data-element="menu-toggle">
<%= remix_icon("more-2-fill", class: "text-xl") %>
</button>
<div class="absolute right-0 z-20 rounded-lg shadow-center bg-white flex flex-col py-2" data-element="menu">
<button class="flex space-x-3 px-5 py-2 items-center text-gray-500 hover:bg-gray-50"