Merge pull request #898 from basecamp/more-navigable-lists
More navigable lists
This commit is contained in:
@@ -65,7 +65,7 @@
|
||||
&:focus-visible {
|
||||
.input--file:has(&) {
|
||||
outline: 0.15rem solid var(--color-selected-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,12 +177,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.switch__input:disabled + & {
|
||||
--switch-color: var(--color-ink-medium) !important;
|
||||
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.switch__input:checked + & {
|
||||
--switch-color: var(--color-link);
|
||||
|
||||
@@ -190,6 +184,13 @@
|
||||
transform: translateX(1.2em);
|
||||
}
|
||||
}
|
||||
|
||||
.switch__input:disabled + & {
|
||||
--switch-color: var(--color-ink-medium);
|
||||
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Containers that act like (and contain) inputs */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@layer components {
|
||||
.settings {
|
||||
--settings-spacer: var(--block-space);
|
||||
--settings-item-padding-inline: 0.5ch;
|
||||
|
||||
display: grid;
|
||||
gap: calc(var(--settings-spacer) * 2);
|
||||
@@ -55,14 +56,21 @@
|
||||
|
||||
.settings__user-list {
|
||||
flex: 1 1 auto;
|
||||
inline-size: 100%;
|
||||
list-style: none;
|
||||
margin: calc(var(--settings-spacer) / -4) 0;
|
||||
margin: calc(var(--settings-spacer) / -4) calc(-1 * var(--settings-item-padding-inline));
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
|
||||
li {
|
||||
border-radius: 0.5em;
|
||||
|
||||
/* Add padding if it's not already on a link within */
|
||||
&:not(:has(a:first-child)) { padding-inline-end: var(--settings-item-padding-inline); }
|
||||
&:not(:has(a:last-child)) { padding-inline-end: var(--settings-item-padding-inline); }
|
||||
}
|
||||
|
||||
a {
|
||||
padding-block: calc(var(--settings-spacer) / 4);
|
||||
padding: calc(var(--settings-spacer) / 4) var(--settings-item-padding-inline);
|
||||
|
||||
@media(any-hover: hover) {
|
||||
&:hover {
|
||||
@@ -70,5 +78,24 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only add a BG color when you can actually navigate */
|
||||
.settings__user-filter:focus-within & {
|
||||
[aria-selected] {
|
||||
background: var(--color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings__user-list-tips {
|
||||
border-top: 1px solid var(--color-ink-light);
|
||||
color: var(--color-ink-dark);
|
||||
font-size: var(--text-small);
|
||||
padding-block-start: var(--settings-spacer);
|
||||
|
||||
.settings__user-filter--bg & {
|
||||
margin-inline: calc(-1 * var(--settings-spacer));
|
||||
padding-inline: var(--settings-spacer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
module AccessesHelper
|
||||
def access_menu_tag(collection, **options, &)
|
||||
tag.menu class: [ options[:class], { "toggler--toggled": collection.all_access? } ], data: {
|
||||
controller: "filter toggle-class",
|
||||
controller: "filter toggle-class navigable-list",
|
||||
action: "keydown->navigable-list#navigate filter:changed->navigable-list#reset",
|
||||
navigable_list_focus_on_selection_value: true,
|
||||
navigable_list_actionable_items_value: true,
|
||||
toggle_class_toggle_class: "toggler--toggled" }, &
|
||||
end
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ module AvatarsHelper
|
||||
end
|
||||
|
||||
def avatar_preview_tag(user, hidden_for_screen_reader: false, **options)
|
||||
tag.span class: "avatar",
|
||||
tag.span class: class_names("avatar", options.delete(:class)),
|
||||
aria: { hidden: hidden_for_screen_reader, label: user.name },
|
||||
tabindex: hidden_for_screen_reader ? -1 : nil do
|
||||
avatar_image_tag(user, **options)
|
||||
|
||||
@@ -106,9 +106,13 @@ export default class extends Controller {
|
||||
#toggleCurrentItem(event) {
|
||||
if (this.actionableItemsValue && this.currentItem && this.#visibleItems.length) {
|
||||
const toggleable = this.currentItem.querySelector("input[type=checkbox]")
|
||||
const isDisabled = toggleable.hasAttribute("disabled")
|
||||
|
||||
if (toggleable) {
|
||||
toggleable.checked = !toggleable.checked
|
||||
toggleable.dispatchEvent(new Event('change', { bubbles: true }))
|
||||
if (!isDisabled) {
|
||||
toggleable.checked = !toggleable.checked
|
||||
toggleable.dispatchEvent(new Event('change', { bubbles: true }))
|
||||
}
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<li class="flex align-center gap-half" data-filter-target="item">
|
||||
<li class="flex align-center gap-half" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= link_to user, class: "txt-ink flex gap-half align-center min-width" do %>
|
||||
<%= avatar_preview_tag user, hidden_for_screen_reader: true %>
|
||||
<strong class="overflow-ellipsis"><%= user.name %></strong>
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
<div class="settings__panel settings__panel--users panel shadow center" data-controller="filter">
|
||||
<%= tag.div class: "settings__panel settings__panel--users panel shadow center", data: {
|
||||
controller: "filter navigable-list",
|
||||
action: "keydown->navigable-list#navigate filter:changed->navigable-list#reset",
|
||||
navigable_list_focus_on_selection_value: true,
|
||||
navigable_list_actionable_items_value: true
|
||||
} do %>
|
||||
<h2 class="divider txt-large">People on the account</h2>
|
||||
<%#= render "accounts/invite" # Scheduled work in https://3.basecamp.com/2914079/buckets/37331921/todos/8746162337 %>
|
||||
|
||||
@@ -8,5 +13,9 @@
|
||||
<ul class="settings__user-list" data-filter-target="list">
|
||||
<%= render partial: "accounts/user", collection: users %>
|
||||
</ul>
|
||||
|
||||
<footer class="settings__user-list-tips">
|
||||
Press <kbd class="kbd">↑</kbd><kbd class="kbd">↓</kbd> to move, <kbd class="kbd">enter</kbd> to visit profile, <kbd class="kbd">SHIFT+ENTER</kbd> to toggle.
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -21,13 +21,9 @@
|
||||
<h3 class="card__title overflow-line-clamp">
|
||||
<%= card.title %>
|
||||
</h3>
|
||||
|
||||
<%= link_to collection_card_path(card.collection, card), draggable: false, class: "card__link", title: card_title_tag(card), data: { action: "dialog#close", turbo_frame: "_top" } do %>
|
||||
<span class="for-screen-reader"><%= card.title %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= render "cards/stagings/stages", card: card if card.doing? %>
|
||||
<%= render "cards/display/preview/stages", card: card if card.doing? %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,6 +32,10 @@
|
||||
<%= render "cards/display/common/background", card: card %>
|
||||
</footer>
|
||||
|
||||
<%= link_to collection_card_path(card.collection, card), draggable: false, class: "card__link", title: card_title_tag(card), data: { action: "dialog#close", turbo_frame: "_top" } do %>
|
||||
<span class="for-screen-reader"><%= card.title %></span>
|
||||
<% end %>
|
||||
|
||||
<% if card.entropic? %>
|
||||
<%= render "cards/display/preview/bubble", card: card %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="display-contents" id="<%= dom_id(card, :assignees) %>">
|
||||
<% card.assignees.each do |assignee| %>
|
||||
<%= avatar_tag assignee %>
|
||||
<%= avatar_tag assignee, tabindex: (local_assigns.key?(:preview) && local_assigns[:preview]) ? -1 : 0 %>
|
||||
<% end %>
|
||||
|
||||
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" <%= "hidden" if card.closed? %>>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="card__meta" id="<%= dom_id(card, :meta) %>">
|
||||
|
||||
<div class="card__meta-grid card__meta-grid--author">
|
||||
<%= avatar_tag card.creator, class: "card__meta-author" %>
|
||||
<%= avatar_tag card.creator, class: "card__meta-author", tabindex: (local_assigns.key?(:preview) && local_assigns[:preview]) ? -1 : 0 %>
|
||||
|
||||
<span class="card__meta-text card__meta-text--added overflow-ellipsis">
|
||||
Added <%= local_datetime_tag(card.created_at, style: :daysago) %>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<%= render "cards/display/common/assignees", card: card %>
|
||||
<%= render "cards/display/common/assignees", card: card, preview: true %>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<%= render "cards/display/common/meta", card: card do %>
|
||||
<%= render "cards/display/common/meta", card: card, preview: true do %>
|
||||
<%= render "cards/display/preview/assignees", card: card %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<%= render "cards/display/common/people", card: card do%>
|
||||
<%= render "cards/display/preview/assignees", card: card %>
|
||||
<%= render "cards/display/preview/assignees", card: card, preview: true %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<li class="flex align-center gap-half" data-filter-target="item">
|
||||
|
||||
<li class="flex align-center gap-half" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= link_to user, class: "txt-ink flex gap-half align-center min-width" do %>
|
||||
<%= avatar_preview_tag user, hidden_for_screen_reader: true %>
|
||||
<strong class="overflow-ellipsis"><%= user.name %></strong>
|
||||
|
||||
@@ -24,4 +24,8 @@
|
||||
<%= access_toggles_for selected_users, selected: true %>
|
||||
<%= access_toggles_for unselected_users, selected: false %>
|
||||
</ul>
|
||||
|
||||
<footer class="settings__user-list-tips">
|
||||
Press <kbd class="kbd">↑</kbd><kbd class="kbd">↓</kbd> to move, <kbd class="kbd">enter</kbd> to visit profile, <kbd class="kbd">SHIFT+ENTER</kbd> to toggle.
|
||||
</footer>
|
||||
<% end %>
|
||||
|
||||
Reference in New Issue
Block a user