Merge pull request #342 from basecamp/icon-helper

Icon helper
This commit is contained in:
Andy Smith
2025-04-02 16:10:01 -05:00
committed by GitHub
35 changed files with 173 additions and 146 deletions
+9 -43
View File
@@ -27,29 +27,12 @@
opacity var( --transition),
scale var( --transition);
img {
-webkit-touch-callout: none;
pointer-events: none;
user-select: none;
}
/* Default icon styles */
&:where(:has(img, svg)) {
&:where(:has(.icon)) {
text-align: start;
img, svg {
block-size: var(--btn-icon-size, 1.3em);
inline-size: var(--btn-icon-size, 1.3em);
max-inline-size: unset;
}
img:not([class]) {
filter: invert(0);
@media (prefers-color-scheme: dark) {
filter: invert(1);
}
.icon {
--icon-size: var(--btn-icon-size, 1.3em);
}
}
@@ -71,6 +54,7 @@
}
img {
--icon-size: 100%;
block-size: 100%;
inline-size: 100%;
max-inline-size: unset;
@@ -85,7 +69,7 @@
/* Circle buttons */
&.btn--circle,
&:where(:has(.for-screen-reader):has(img, svg)) {
&:where(:has(.for-screen-reader):has(.icon)) {
--btn-border-radius: 50%;
--btn-padding: 0;
@@ -108,7 +92,7 @@
:is(input[type=radio]),
:is(input[type=checkbox]) {
--hover-size: 0;
appearance: none;
border-radius: var(--btn-border-radius);
cursor: pointer;
@@ -119,7 +103,7 @@
position: absolute;
}
img.checked {
.checked {
display: none;
}
}
@@ -129,17 +113,7 @@
--btn-color: var(--color-ink-reversed);
--outline-color: var(--color-ink);
img {
filter: invert(1);
}
@media (prefers-color-scheme: dark) {
img {
filter: invert(0);
}
}
img.checked {
.checked {
display: block;
}
}
@@ -203,14 +177,6 @@
:is(.btn--link, .btn--negative, .btn--positive, .btn--reversed) {
--btn-border-color: var(--color-bg);
img:not([class]) {
filter: invert(1);
@media (prefers-color-scheme: dark) {
filter: invert(0);
}
}
}
.btn--small {
@@ -220,7 +186,7 @@
.btn--success {
animation: success 1s ease-out;
img {
.icon {
animation: zoom-fade 300ms ease-out;
}
}
-16
View File
@@ -54,22 +54,6 @@
}
}
.colorize--white {
filter: invert(1);
@media (prefers-color-scheme: dark) {
filter: invert(0);
}
}
.colorize--black {
filter: invert(0);
@media (prefers-color-scheme: dark) {
filter: invert(1);
}
}
.color-picker {
--panel-border-color: var(--bubble-color);
--panel-border-radius: 2em;
+74
View File
@@ -0,0 +1,74 @@
.icon {
-webkit-touch-callout: none;
background-color: currentColor;
block-size: var(--icon-size, 1em);
display: inline-block;
flex-shrink: 0;
inline-size: var(--icon-size, 1em);
mask-image: var(--svg);
mask-repeat: no-repeat;
mask-size: cover;
pointer-events: none;
user-select: none;
}
.icon--activity { --svg: url("activity.svg "); }
.icon--add { --svg: url("add.svg "); }
.icon--alert { --svg: url("alert.svg "); }
.icon--arrow-left { --svg: url("arrow-left.svg "); }
.icon--arrow-right { --svg: url("arrow-right.svg "); }
.icon--art { --svg: url("art.svg "); }
.icon--assigned { --svg: url("assigned.svg "); }
.icon--bell-off { --svg: url("bell-off.svg "); }
.icon--bell { --svg: url("bell.svg "); }
.icon--blob { --svg: url("blob.svg "); }
.icon--bolt { --svg: url("bolt.svg "); }
.icon--bookmark-outline { --svg: url("bookmark-outline.svg "); }
.icon--bookmark { --svg: url("bookmark.svg "); }
.icon--bubble-add { --svg: url("bubble-add.svg "); }
.icon--bubbles { --svg: url("bubbles.svg "); }
.icon--calendar-add { --svg: url("calendar-add.svg "); }
.icon--calendar { --svg: url("calendar.svg "); }
.icon--camera { --svg: url("camera.svg "); }
.icon--chart { --svg: url("chart.svg "); }
.icon--check { --svg: url("check.svg "); }
.icon--close { --svg: url("close.svg "); }
.icon--comment { --svg: url("comment.svg "); }
.icon--copy-paste { --svg: url("copy-paste.svg "); }
.icon--crown { --svg: url("crown.svg "); }
.icon--drag { --svg: url("drag.svg "); }
.icon--email { --svg: url("email.svg "); }
.icon--everyone { --svg: url("everyone.svg "); }
.icon--filter { --svg: url("filter.svg "); }
.icon--globe { --svg: url("globe.svg "); }
.icon--grid { --svg: url("grid.svg "); }
.icon--history { --svg: url("history.svg "); }
.icon--home { --svg: url("home.svg "); }
.icon--hourglass { --svg: url("hourglass.svg "); }
.icon--inbox { --svg: url("inbox.svg "); }
.icon--logout { --svg: url("logout.svg "); }
.icon--menu-dots-horizontal { --svg: url("menu-dots-horizontal.svg "); }
.icon--minus { --svg: url("minus.svg "); }
.icon--password { --svg: url("password.svg "); }
.icon--pencil { --svg: url("pencil.svg "); }
.icon--person { --svg: url("person.svg "); }
.icon--picture-add { --svg: url("picture-add.svg "); }
.icon--picture-double { --svg: url("picture-double.svg "); }
.icon--picture-remove { --svg: url("picture-remove.svg "); }
.icon--pinned { --svg: url("pinned.svg "); }
.icon--pop { --svg: url("pop.svg "); }
.icon--qr-code { --svg: url("qr-code.svg "); }
.icon--reaction { --svg: url("reaction.svg "); }
.icon--refresh { --svg: url("refresh.svg "); }
.icon--remove-med { --svg: url("remove-med.svg "); }
.icon--remove { --svg: url("remove.svg "); }
.icon--rename { --svg: url("rename.svg "); }
.icon--settings { --svg: url("settings.svg "); }
.icon--share { --svg: url("share.svg "); }
.icon--sort-ascending { --svg: url("sort-ascending.svg "); }
.icon--sort-descending { --svg: url("sort-descending.svg "); }
.icon--tag { --svg: url("tag.svg "); }
.icon--temperature { --svg: url("temperature.svg "); }
.icon--thumb-up { --svg: url("thumb-up.svg "); }
.icon--trash { --svg: url("trash.svg "); }
.icon--unpinned { --svg: url("unpinned.svg"); }
+5 -2
View File
@@ -3,7 +3,10 @@ module ApplicationHelper
tag.title @page_title || "Fizzy"
end
def icon_tag(name, aria: { hidden: true }, size: 24, **options)
image_tag "#{name}.svg", aria: aria, size: size, **options
def icon_tag(name, **options)
classes = class_names "icon icon--#{name}", options.delete(:class)
options["aria-hidden"] = true
content_tag :span, "", class: classes, **options
end
end
+1 -1
View File
@@ -2,7 +2,7 @@ module FiltersHelper
def filter_chip_tag(text, params)
link_to bubbles_path(params), class: "btn txt-small btn--remove fill-selected" do
concat tag.span(text)
concat image_tag("close.svg", aria: { hidden: true }, size: 24)
concat icon_tag("close")
end
end
+1 -1
View File
@@ -18,7 +18,7 @@ module TranslationsHelper
def translation_button(translation_key)
tag.div(class: "position-relative", data: { controller: "popover", action: "keydown.esc->popover#close click@document->popover#closeOnClickOutside", popover_orientation_top_class: "popover-orientation-top" }) do
tag.button(type: "button", class: "btn", tabindex: -1, data: { action: "popover#toggle" }) do
concat image_tag("globe.svg", size: 20, role: "presentation", class: "color-icon")
concat image_tag("globe.svg", size: 20, role: "presentation")
concat tag.span("Translate", class: "for-screen-reader")
end +
tag.dialog(class: "lanuage-list-menu popover shadow", data: { popover_target: "menu" }) do
+3 -3
View File
@@ -11,7 +11,7 @@
<div class="flex align-center gap">
<div data-controller="dialog" data-dialog-modal-value="true" class="flex-inline">
<%= tag.button class: "btn", data: { action: "dialog#open" } do %>
<%= image_tag "qr-code.svg", aria: { hidden: "true" }, size: 24, class: "colorize--black" %>
<%= icon_tag "qr-code" %>
<span class="for-screen-reader">Show join link QR code</span>
<% end %>
@@ -28,12 +28,12 @@
</div>
<%= button_to_copy_to_clipboard(url) do %>
<%= image_tag "copy-paste.svg", aria: { hidden: "true" }, size: 24, class: "colorize--black" %>
<%= icon_tag "copy-paste" %>
<span class="for-screen-reader">Copy join link</span>
<% end %>
<%= button_to account_join_code_path, method: :put, class: "btn btn--regenerate" do %>
<%= image_tag "refresh.svg", aria: { hidden: "true" }, size: 24, class: "colorize--black" %>
<%= icon_tag "refresh" %>
<span class="for-screen-reader">Regenerate join link</span>
<% end %>
</div>
+1 -1
View File
@@ -9,7 +9,7 @@
<label class="btn txt-small flex-item-no-shrink" for="<%= dom_id(user, :role) %>">
<span class="for-screen-reader">Role: <%= true ? "Administrator" : "Member" %></span>
<%= image_tag "crown.svg", size: 20, aria: { hidden: "true" } %>
<%= icon_tag "crown" %>
<%= check_box_tag :role, { data: { action: "form#submit" }, hidden: true, id: dom_id(user, :role) }, "administrator", "member" %>
</label>
+1 -1
View File
@@ -10,7 +10,7 @@
<span class="color-picker__color">
<label class="btn btn--circle" style="--btn-background: <%= color %>" title="<%= color %>">
<%= form.radio_button :color, color %>
<%= image_tag "check.svg", aria: { hidden: "true" }, size: 24, class: "checked" %>
<%= icon_tag "check.svg", class: "checked" %>
<span class="for-screen-reader"><%= color %></span>
</label>
</span>
+3 -3
View File
@@ -1,13 +1,13 @@
<%= turbo_frame_tag dom_id(@bubble, :pin) do %>
<% if @bubble.pinned_by? Current.user %>
<%= button_to bucket_bubble_pin_path(@bubble.bucket, @bubble), method: :delete, class: "btn btn--reversed" do %>
<%= image_tag "pinned.svg", size: 16, aria: { hidden: true } %>
<%= icon_tag "pinned" %>
<span class="for-screen-reader">Un-pin this card</span>
<% end %>
<% else %>
<%= button_to bucket_bubble_pin_path(@bubble.bucket, @bubble), class: "btn" do %>
<%= image_tag "unpinned.svg", size: 16, aria: { hidden: true } %>
<%= icon_tag "unpinned" %>
<span class="for-screen-reader">Pin this card</span>
<% end %>
<% end %>
<% end %>
<% end %>
@@ -2,6 +2,6 @@
<%= tag.hashtag %>
<% if bubble.tagged_with?(tag) %>
<%= image_tag "check.svg", aria: { hidden: "true" } %>
<%= icon_tag "check" %>
<% end %>
</div>
+2 -2
View File
@@ -1,12 +1,12 @@
<%= turbo_frame_tag dom_id(@bubble, :watch) do %>
<% if @bubble.watched_by? Current.user %>
<%= button_to bucket_bubble_watch_path(@bubble.bucket, @bubble), method: :delete, class: "btn btn--reversed" do %>
<%= image_tag "bell.svg", size: 16, aria: { hidden: true } %>
<%= icon_tag "bell" %>
<span class="for-screen-reader">Stop watching</span>
<% end %>
<% else %>
<%= button_to bucket_bubble_watch_path(@bubble.bucket, @bubble), class: "btn" do %>
<%= image_tag "bell-off.svg", size: 16, aria: { hidden: true } %>
<%= icon_tag "bell-off" %>
<span class="for-screen-reader">Watch this</span>
<% end %>
<% end %>
+1 -1
View File
@@ -11,7 +11,7 @@
<hr class="separator--horizontal flex-item-grow" style="--border-color: var(--color-subtle-dark); --border-style: dashed" aria-hidden="true">
<%= image_tag "check.svg", size: 20, class: "toggler__visible-when-on colorize--black flex-item-no-shrink", aria: { hidden: "true" } %>
<%= icon_tag "check", class: "toggler__visible-when-on" %>
<label class="switch toggler__visible-when-off flex-item-no-shrink">
<%= check_box_tag "user_ids[]", user.id, selected, class: "switch__input", id: nil %>
+1 -1
View File
@@ -32,7 +32,7 @@
<%= access_menu_tag @bucket do %>
<li class="flex align-center gap margin-none">
<figure class="avatar flex-item-no-shrink" style="--avatar-border-radius: 0; --avatar-size: 4ch;">
<%= image_tag "everyone.svg", aria: { hidden: "true" }, class: "colorize--black" %>
<%= icon_tag "everyone" %>
<span class="for-screen-reader">Everyone</span>
</figure>
+3 -3
View File
@@ -10,9 +10,9 @@
<%= local_datetime_tag comment.created_at, style: :shortdate, class: "txt-ink translucent" %>
<% end %>
<%= link_to edit_bucket_bubble_comment_path(comment.bubble.bucket, comment.bubble, comment),
<%= link_to edit_bucket_bubble_comment_path(comment.bubble.bucket, comment.bubble, comment),
class: "comment__edit btn btn--plain txt-xx-small fill-transparent translucent flex-item-justify-end" do %>
<%= image_tag "menu-dots-horizontal.svg", class: "colorize--black" %>
<%= icon_tag "menu-dots-horizontal" %>
<span class="for-screen-reader">Edit this comment</span>
<% end %>
</div>
@@ -23,4 +23,4 @@
<%= render "comments/reactions/reactions", comment: comment %>
</div>
<% end %>
<% end %>
<% end %>
+1 -1
View File
@@ -14,7 +14,7 @@
<%= tag.button type: :submit, class: "btn btn--negative flex-item-justify-end", form: dom_id(@comment, :delete_form),
data: { turbo_confirm: "Are you sure you want to delete this comment?" } do %>
<%= icon_tag "trash", size: 16 %>
<%= icon_tag "trash" %>
<span class="for-screen-reader">Delete</span>
<% end %>
</div>
@@ -3,7 +3,7 @@
class="reaction flex-inline postion--relative max-width align-center fill-white gap"
data-controller="reaction-delete"
data-reaction-delete-reacter-id-value="<%= reaction.reacter.id %>"
data-controller="reaction-delete" data-reaction-delete-perform-class="reaction--deleting"
data-controller="reaction-delete" data-reaction-delete-perform-class="reaction--deleting"
data-reaction-delete-reveal-class="expanded" data-reaction-delete-reacter-id-value="<%= reaction.reacter.id %>">
<figure class="reaction__avatar margin-none flex-item-no-shrink">
<%= avatar_tag reaction.reacter, aria: { label: "#{reaction.reacter.name} reacted #{reaction.content}" }, loading: :lazy %>
@@ -12,14 +12,14 @@
<%= tag.span reaction.content, role: "button",
class: [ "txt-small", { "txt-medium": reaction.all_emoji? } ],
data: { action: "click->reaction-delete#reveal keydown.enter->reaction-delete#reveal:prevent", reaction_delete_target: "content" } %>
<%= button_to bucket_bubble_comment_reaction_path(comment.bubble.bucket, comment.bubble, comment, reaction),
method: :delete,
class: "btn btn--negative flex-item-justify-end reaction__delete",
data: { action: "reaction-delete#perform", reaction_delete_target: "button" } do %>
<%= image_tag "minus.svg", size: 20, aria: { hidden: "true" } %>
<%= icon_tag "minus" %>
<span class="for-screen-reader">Delete this reaction</span>
<% end %>
</div>
<span id="delete_reaction_accessible_label" class="for-screen-reader">Press enter to delete this reaction</span>
<% end %>
<% end %>
@@ -4,15 +4,15 @@
<div class="flex-inline flex-wrap gap" id="<%= dom_id(comment, :reactions) %>" data-turbo-streaming-target="container">
<%= render partial: "comments/reactions/reaction", collection: comment.reactions.ordered, locals: { comment: comment }, cached: true %>
</div>
<%= turbo_frame_tag comment, :new_reaction do %>
<div class="flex-inline" data-controller="soft-keyboard">
<%= link_to new_bucket_bubble_comment_reaction_path(comment.bubble.bucket, comment.bubble, comment), role: "button",
class: "txt-small btn reaction__action", action: "soft-keyboard#open" do %>
<%= image_tag "reaction.svg", size: 20, aria: { hidden: "true" } %>
<%= icon_tag "reaction" %>
<span class="for-screen-reader">Add a reaction</span>
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>
+3 -3
View File
@@ -1,5 +1,5 @@
<%= turbo_frame_tag dom_id(@comment, :new_reaction) do %>
<%= form_with url: bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment),
<%= form_with url: bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment),
class: "reaction reaction__form flex-inline postion--relative max-width align-center fill-white gap expanded",
html: { aria: { label: "New reaction" } },
data: { controller: "form", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel" } do |form| %>
@@ -13,13 +13,13 @@
</label>
<%= form.button class: "btn btn--reversed", type: "submit" do %>
<%= image_tag "check.svg", aria: { hidden: "true" } %>
<%= icon_tag "check" %>
<span class="for-screen-reader">Submit</span>
<% end %>
<%= link_to bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment), role: "button",
data: { turbo_frame: dom_id(@comment, :reactions), form_target: "cancel" }, class: "btn btn--negative" do %>
<%= image_tag "minus.svg", aria: { hidden: "true" } %>
<%= icon_tag "minus" %>
<span class="for-screen-reader">Cancel</span>
<% end %>
<% end %>
+3 -3
View File
@@ -5,7 +5,7 @@
class: "event panel center center-block flex-inline align-start justify-start gap position-relative",
style: "--bubble-color: #{ bubble.color }; background-color: color-mix(in srgb, var(--bubble-color) 10%, var(--color-bg));
color: color-mix(in srgb, var(--bubble-color) 40%, var(--color-ink));",
data: { related_element_target: "related",
data: { related_element_target: "related",
related_element_group_value: bubble.id,
action: "mouseover->related-element#highlight mouseout->related-element#unhighlight" } do %>
<div class="avatar txt-x-small flex-item-no-shrink">
@@ -19,8 +19,8 @@
</strong>
<% if event_column(event) == 2 %>
<span class="event__icon flex-item-justify-end">
<%= image_tag "#{event_action_icon(event)}.svg", size: 24, aria: { hidden: true }, class: "colorize--white" %>
<span class="event__icon flex-item-justify-end txt-reversed">
<%= icon_tag event_action_icon(event) %>
</span>
<% end %>
</div>
+4 -4
View File
@@ -7,22 +7,22 @@
</span>
</button>
<dialog class="events__popup popup panel flex-column full-width align-start gap-half fill-white shadow"
<dialog class="events__popup popup panel flex-column full-width align-start gap-half fill-white shadow"
style="z-index: 5; inset: 0 0 auto auto;" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half txt-nowrap">Filter by Collection…</strong>
<%= form_with url: events_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: events_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<%= link_to "Show everything", events_path(clear_filter: true), class: "btn popup__item txt-nowrap" %>
<% @buckets.each do |bucket| %>
<div class="btn popup__item">
<%= form.check_box "bucket_ids[]", {
<%= form.check_box "bucket_ids[]", {
checked: (params[:bucket_ids] || cookies[:bucket_filter]&.split(","))&.include?(bucket.id.to_s),
data: { action: "change->form#submit" },
include_hidden: false,
}, bucket.id %>
<%= form.label "bucket_ids[]", bucket.name, for: dom_id(bucket, :filter), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
+7 -7
View File
@@ -14,37 +14,37 @@
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half overflow-ellipsis">Assigned to…</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:assignee_ids, :assignment_status).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<%= link_to bubbles_path(filter.as_params.except(:assignee_ids, :assignment_status)), class: "btn popup__item" do %>
<span class="overflow-ellipsis">Clear all</span>
<% end %>
<div class="btn popup__item">
<%= form.check_box "assignment_status", {
<%= form.check_box "assignment_status", {
checked: filter.assignment_status.unassigned?,
data: { action: "change->form#submit" },
include_hidden: false,
}, "unassigned" %>
<%= form.label :assignment_status, "No one", class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% Current.account.users.active.order(:name).each do |user| %>
<div class="btn popup__item">
<%= form.check_box "assignee_ids[]", {
<%= form.check_box "assignee_ids[]", {
checked: filter.assignees.include?(user),
data: { action: "change->form#submit" },
include_hidden: false,
}, user.id %>
<%= form.label "assignee_ids[]", user.name, for: dom_id(user, :filter), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
+4 -4
View File
@@ -11,22 +11,22 @@
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half">In Collection</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:bucket_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<% Current.user.buckets.order(:name).each do |bucket| %>
<div class="btn popup__item">
<%= form.check_box "bucket_ids[]", {
<%= form.check_box "bucket_ids[]", {
checked: filter.buckets.include?(bucket),
data: { action: "change->form#submit" },
include_hidden: false,
}, bucket.id %>
<%= form.label "bucket_ids[]", bucket.name, for: dom_id(bucket, :filter), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
+5 -5
View File
@@ -1,5 +1,5 @@
<% if filter.creators.any? %>
<div class="quick-filter position-relative" data-controller="dialog"
<div class="quick-filter position-relative" data-controller="dialog"
data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<button class="btn input input--select flex-inline txt-small" data-action="click->dialog#open:stop">
<span class="overflow-ellipsis">
@@ -11,11 +11,11 @@
</span>
</button>
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
aria-label="Added by…" aria-description="Added by…"
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half">Added by…</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:creator_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
@@ -34,7 +34,7 @@
}, Current.user.id %>
<%= form.label :creator_ids, "Me", for: form.field_id(:creator_ids, Current.user.id), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
@@ -47,7 +47,7 @@
}, user.id %>
<%= form.label :creator_ids, user.name, for: form.field_id(:creator_ids, user.id), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
+2 -2
View File
@@ -4,7 +4,7 @@
<span class="btn btn--placeholder txt-small" aria-hidden="true"></span>
<h2 class="txt-large flex align-center gap-half margin-none">
<%= icon_tag "filter", size: 30 %>
<%= icon_tag "filter" %>
<span>Filter</span>
</h2>
@@ -116,7 +116,7 @@
<label class="btn filter__button">
<%= check_box_tag "assignment_status", "unassigned", filter.assignment_status.unassigned?,
class: "visually-hidden", data: {
action: "filter-form#clearCategory",
action: "filter-form#clearCategory",
filter_form_name_param: "assignee_ids[],assigner_ids[]" } %>
<span>No one</span>
<%= icon_tag "close" %>
+6 -6
View File
@@ -9,20 +9,20 @@
aria-label="Sort by…" aria-description="Sort by…"
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half">Sort by…</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:indexed_by).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<div class="btn popup__item">
<%= form.radio_button :indexed_by, filter.default_indexed_by,
<%= form.radio_button :indexed_by, filter.default_indexed_by,
checked: filter.default_indexed_by?,
class: "default-value",
data: { action: "change->form#submit" } %>
<%= form.label :indexed_by, "Most active", value: filter.default_indexed_by, class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% Filter::INDEXES.each do |index| %>
@@ -32,9 +32,9 @@
data: { action: "change->form#submit" } %>
<%= form.label :indexed_by, index.humanize, value: index, class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
</dialog>
</div>
</div>
+3 -3
View File
@@ -14,12 +14,12 @@
aria-label="In stage…" aria-description="In stage…"
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half">In stage…</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:stage_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<% workflow = Current.account.workflows.first %>
<% workflow.stages.each do |stage| %>
<div class="btn popup__item">
@@ -31,7 +31,7 @@
}, stage.id %>
<%= form.label :stage_ids, stage.name, for: form.field_id(:stage_ids, stage.id), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
+6 -6
View File
@@ -12,29 +12,29 @@
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<strong class="popup__title margin-block-start-half pad-inline-half overflow-ellipsis">Tagged…</strong>
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:tag_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<%= link_to bubbles_path(filter.as_params.except(:tag_ids)), class: "btn popup__item" do %>
<span class="overflow-ellipsis">Clear all</span>
<% end %>
<% Current.account.tags.order(:title).each do |tag| %>
<div class="btn popup__item">
<%= form.check_box "tag_ids[]", {
<%= form.check_box "tag_ids[]", {
checked: filter.tags.include?(tag),
data: { action: "change->form#submit" },
include_hidden: false,
}, tag.id %>
<%= form.label "tag_ids[]", tag.hashtag, for: dom_id(tag, :filter), class: "overflow-ellipsis" %>
<%= icon_tag "check", size: 18, class: "checked flex-item-justify-end" %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% end %>
<% end %>
</dialog>
</div>
</div>
<% end %>
+3 -3
View File
@@ -8,7 +8,7 @@
<%= translation_button :user_name %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.text_field :name, class: "input", autocomplete: "name", placeholder: "Name", autofocus: true, required: true, data: { "1p-ignore": true } %>
<%= image_tag "person.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "person", class: "txt-large" %>
</label>
</div>
@@ -16,7 +16,7 @@
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.email_field :email_address, class: "input", autocomplete: "username", placeholder: "Email address", required: true %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "email", class: "txt-large" %>
</label>
</div>
@@ -24,7 +24,7 @@
<%= translation_button :password %>
<label class="flex align-center gap input input--actor txt-large">
<%= form.password_field :password, class: "input", autocomplete: "new-password", placeholder: "Password", required: true, maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "password", class: "txt-large" %>
</label>
</div>
<button type="submit" id="log_in" class="btn btn--reversed center">
+1 -1
View File
@@ -3,7 +3,7 @@
<form method="dialog" class="lightbox__btn">
<button class="btn fill-white" title="Close (esc)">
<%= image_tag "remove.svg", aria: { hidden: "true" } %>
<%= icon_tag "remove.svg" %>
<span class="for-screen-reader">Close image viewer (esc)</span>
</button>
</form>
+1 -1
View File
@@ -10,7 +10,7 @@
<h1 class="txt-x-large"><%= @page_title %></h1>
<%= link_to notifications_settings_path, class: "btn flex-item-justify-end" do %>
<%= image_tag "settings.svg", size: 20 %>
<%= icon_tag "settings" %>
<span class="for-screen-reader">Notification settings</span>
<% end %>
</nav>
+2 -2
View File
@@ -8,7 +8,7 @@
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor">
<%= form.email_field :email_address, required: true, class: "input full-width", autofocus: true, autocomplete: "username", placeholder: "Enter your email address" %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "email", class: "txt-large" %>
</label>
</div>
@@ -16,7 +16,7 @@
<%= translation_button :password %>
<label class="flex align-center gap input input--actor">
<%= form.password_field :password, required: true, class: "input full-width", autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "password", class: "txt-large" %>
</label>
</div>
+2 -2
View File
@@ -13,7 +13,7 @@
<div class="flex align-center gap">
<div data-controller="dialog" data-dialog-modal-value="true" class="flex-inline">
<%= tag.button class: "btn", data: { action: "dialog#open" } do %>
<%= image_tag "qr-code.svg", aria: { hidden: "true" }, size: 24, class: "colorize--black" %>
<%= icon_tag "qr-code" %>
<span class="for-screen-reader">Show auto-login QR code</span>
<% end %>
@@ -30,7 +30,7 @@
</div>
<%= button_to_copy_to_clipboard(url) do %>
<%= image_tag "copy-paste.svg", aria: { hidden: "true" }, size: 24, class: "colorize--black" %>
<%= icon_tag "copy-paste" %>
<span class="for-screen-reader">Copy auto-login link</span>
<% end %>
</div>
+4 -4
View File
@@ -25,7 +25,7 @@
<% if @user.avatar.attached? %>
<%= tag.button type: :submit, form: "avatar-delete-form", class: "btn btn--negative txt-small", data: { turbo_confirm: "Are you sure you want to remove your avatar? This can't be undone." } do %>
<%= image_tag "minus.svg", aria: { hidden: "true" }, size: 20 %>
<%= icon_tag "minus" %>
<span class="for-screen-reader">Delete avatar</span>
<% end %>
<% end %>
@@ -35,21 +35,21 @@
<%= translation_button :user_name %>
<label class="flex align-center gap input input--actor">
<%= form.text_field :name, class: "input full-width", autocomplete: "name", placeholder: "Name", autofocus: true, required: true, data: { "1p-ignore": true, action: "keydown.esc@document->form#cancel" } %>
<%= image_tag "person.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "person", class: "txt-large" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor">
<%= form.email_field :email_address, class: "input full-width", autocomplete: "username", placeholder: "Email address", required: true %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "email", class: "txt-large" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :password %>
<label class="flex align-center gap input input--actor">
<%= form.password_field :password, class: "input full-width", autocomplete: "new-password", placeholder: "Password", required: false, maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "password", class: "txt-large" %>
</label>
</div>
<button type="submit" id="log_in" class="btn btn--reversed center">
+3 -3
View File
@@ -16,21 +16,21 @@
<%= translation_button :user_name %>
<label class="flex align-center gap input input--actor">
<%= form.text_field :name, class: "input full-width", autocomplete: "name", placeholder: "Name", autofocus: true, required: true, data: { "1p-ignore": true } %>
<%= image_tag "person.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "person", class: "txt-large" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :email_address %>
<label class="flex align-center gap input input--actor">
<%= form.email_field :email_address, class: "input full-width", autocomplete: "username", placeholder: "Email address", required: true %>
<%= image_tag "email.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "email", class: "txt-large" %>
</label>
</div>
<div class="flex align-center gap">
<%= translation_button :password %>
<label class="flex align-center gap input input--actor">
<%= form.password_field :password, class: "input full-width", autocomplete: "new-password", placeholder: "Password", required: true, maxlength: 72 %>
<%= image_tag "password.svg", aria: { hidden: "true" }, size: 30, class: "colorize--black" %>
<%= icon_tag "password", class: "txt-large" %>
</label>
</div>
<button type="submit" id="log_in" class="btn btn--reversed center">