Merge branch 'main' into comboboxes

* main:
  Ensure @filter isn't nil
  Bump boost size, adjust assignee alignment
  Stub duplicate finder button
  Move pop action
  Remove some of the more vertical ones
  List name next to assignee
  Bump font size
  Display tags inside the bubble
  Needs a little structure
  Pull back comment decoration
  Tighten up menu
  Tighten-up workflow panel
This commit is contained in:
Jose Farias
2024-11-25 14:00:52 -06:00
14 changed files with 133 additions and 98 deletions
+1
View File
@@ -0,0 +1 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m3.25 13.25a1 1 0 0 1 -1-1v-6a1 1 0 0 1 1-1h11a1 1 0 0 1 .98.8.25.25 0 0 0 .245.2h1.525a.25.25 0 0 0 .25-.25v-.75a2 2 0 0 0 -2-2h-13a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h1.75a.25.25 0 0 0 .25-.25v-1.5a.25.25 0 0 0 -.25-.25z"/><path d="m21.25 7.75h-13a2.5 2.5 0 0 0 -2.5 2.5v8a2.5 2.5 0 0 0 2.5 2.5h13a2.5 2.5 0 0 0 2.5-2.5v-8a2.5 2.5 0 0 0 -2.5-2.5zm-13 9.5v-6a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v6a1 1 0 0 1 -1 1h-11a1 1 0 0 1 -1-1z"/></svg>

After

Width:  |  Height:  |  Size: 500 B

+29 -30
View File
@@ -80,8 +80,9 @@
aspect-ratio: 6/9;
display: flex;
font-size: 6cqi;
inset: 70cqi 7cqi auto auto;
min-inline-size: 7ch;
min-inline-size: 4.5ch;
padding: 0;
place-items: center;
transform: rotate(var(--rotation));
@@ -115,40 +116,14 @@
}
}
&.bubble__tag {
inset: auto auto -6cqi 15cqi;
+ & {
inset: auto auto 8cqi 5cqi;
+ & {
inset: auto auto 22cqi -2cqi;
}
}
@media (hover: hover) {
.windshield .bubble:hover & {
transform: translate(-1rem, -1rem);
}
.windshield .bubble:hover & + & {
transform: translate(-1.25rem, -1.25rem);
}
.windshield .bubble:hover & + & + & {
transform: translate(-1.5rem, -1.5rem);
}
}
}
&.bubble__assignee {
aspect-ratio: 1;
font-size: 4.5cqi;
inset: 4cqb auto auto -2cqi;
inset: 6cqb auto auto -2cqi;
padding: 0.2em;
+ & {
inset: 1cqb auto auto 10cqi;
inset: 1cqb auto auto 9cqi;
+ & {
inset: -1cqb auto auto 25cqi;
@@ -181,6 +156,20 @@
transform: translate(1.5rem, -0.5rem);;
}
}
.assignee__name {
display: none;
.bubble__perma & {
color: var(--bubble-color);
display: block;
font-size: var(--text-medium);
font-weight: normal;
inset: -2em auto auto auto;
position: absolute;
text-align: center;
}
}
}
&.bubble__date {
@@ -188,8 +177,9 @@
aspect-ratio: 5/7;
cursor: pointer;
font-size: 4.5cqi;
font-size: 5cqi;
inset: 1cqb 1cqi auto auto;
text-align: center;
transform: rotate(var(--rotation));
.bubble__date-text {
@@ -311,6 +301,15 @@
max-inline-size: 100%;
}
.bubble__tags{
font-size: var(--text-small);
margin-block-start: 0.3cqb;
.bubble__perma & {
font-size: var(--text-medium);
}
}
.bubble__title {
-webkit-line-clamp: var(--lines, 5);
-webkit-box-orient: vertical;
+19 -8
View File
@@ -1,9 +1,9 @@
.comments {
--avatar-size: 2.33em;
--comment-padding-block: 1.2em;
--comment-padding-inline: 1.5em;
--comment-padding-block: 0.65lh;
--comment-padding-inline: 2ch;
max-inline-size: 70ch;
max-inline-size: 120ch;
row-gap: var(--comment-padding-block);
> :first-child {
@@ -11,6 +11,16 @@
}
}
.comment {
max-inline-size: 66ch;
margin-block: var(--comment-padding-block);
margin-inline: 0 auto;
textarea {
padding: var(--comment-padding-block) var(--comment-padding-inline);
}
}
.comment__avatar {
margin-block-start: calc(var(--comment-padding-block) * 0.5);
margin-inline: auto calc(var(--comment-padding-inline) * -0.75);
@@ -35,12 +45,11 @@
}
.comment__content {
margin-inline: 0 var(--avatar-size);
margin-inline: auto var(--avatar-size);
padding: var(--comment-padding-block) var(--comment-padding-inline);
.comment--mine & {
background-color: var(--color-selected);
margin-inline: var(--avatar-size) 0;
margin-inline: var(--avatar-size) auto;
}
.comment:has(+ .event-summary) & {
@@ -50,6 +59,7 @@
.comment--mine {
flex-direction: row-reverse;
margin-inline: auto 0;
.comment__author {
flex-direction: row-reverse;
@@ -73,8 +83,9 @@
}
.event-summary {
color: var(--bubble-color);
font-weight: 600;
margin-block: calc(var(--comment-padding-block) * -1);
padding: calc(var(--comment-padding-block) * 0.5) var(--comment-padding-inline);
gap: 0.5ch;
/* margin-block: calc(var(--comment-padding-block) * -1); */
padding: calc(var(--comment-padding-block) * 0.5) var(--comment-padding-inline);
}
+1 -1
View File
@@ -1,5 +1,5 @@
module BubblesHelper
BUBBLE_ROTATION = %w[ 90 80 75 60 45 35 25 5 -45 -40 -75 ]
BUBBLE_ROTATION = %w[ 75 60 45 35 25 5 ]
def bubble_rotation(bubble)
value = BUBBLE_ROTATION[Zlib.crc32(bubble.to_param) % BUBBLE_ROTATION.size]
+1 -1
View File
@@ -1,6 +1,6 @@
module CommentsHelper
def comment_tag(comment, &)
tag.div id: dom_id(comment), class: "comment flex align-start full-width",
tag.div id: dom_id(comment), class: "comment flex-inline align-start full-width",
data: { creator_id: comment.creator_id, created_by_current_user_target: "creation" }, &
end
+6 -15
View File
@@ -1,17 +1,8 @@
<% bubble.assignees.each do |assignee| %>
<div class="bubble__bubble bubble__meta bubble__assignee">
<details name="assignments" class="position-relative" data-controller="expandable" data-action="focusout->expandable#closeOnFocusOutside">
<summary class="btn btn--plain fill-transparent">
<%= avatar_image_tag assignee, loading: :lazy, class: "avatar flex-item-no-shrink" %>
<span class="for-screen-reader">Assign to…</span>
</summary>
<%= form_with url: bucket_bubble_assignment_swaps_path(bubble.bucket, bubble), data: { controller: "form" } do |form| %>
<%= form.hidden_field :outgoing_assignee_id, value: assignee.id %>
<%= form.combobox :incoming_assignee_id, bucket_bubble_users_path(bubble.bucket, bubble),
id: dom_id(assignee, :assignment), required: true, preload: true,
data: { controller: "autofocus", action: "hw-combobox:selection->form#submit" } %>
<% end %>
</details>
</div>
<article class="bubble__bubble bubble__meta bubble__assignee">
<div class="btn btn--plain position-relative fill-transparent">
<span class="assignee__name"><%= assignee.name %></span>
<%= avatar_image_tag assignee, loading: :lazy, class: "avatar flex-item-no-shrink" %>
</div>
</article>
<% end %>
+11 -6
View File
@@ -4,11 +4,17 @@
data-controller="animation upload-preview"
data-animation-play-class="bubble--wobble" data-animation-play-on-load-value="true" data-action="mouseover->animation#play">
<h1 class="bubble__title">
<%= turbo_frame_tag bubble, :edit do %>
<%= link_to bubble.title, edit_bucket_bubble_path(bubble.bucket, bubble), class: "txt-undecorated" %>
<% end %>
</h1>
<div>
<h1 class="bubble__title">
<%= turbo_frame_tag bubble, :edit do %>
<%= link_to bubble.title, edit_bucket_bubble_path(bubble.bucket, bubble), class: "txt-undecorated" %>
<% end %>
</h1>
<div class="bubble__tags flex align-end justify-center gap-half">
<%= render "bubbles/tags", bubble: bubble %>
</div>
</div>
<div class="bubble__shape"></div>
@@ -20,6 +26,5 @@
<%= render "bubbles/boosts", bubble: bubble %>
<%= render "bubbles/date", bubble: bubble %>
<%= render "bubbles/image", bubble: bubble %>
<%= render "bubbles/tags", bubble: bubble %>
</div>
<% end %>
+3 -15
View File
@@ -1,16 +1,4 @@
<% bubble.tags.last(3).each do |tag| %>
<div class="bubble__bubble bubble__meta bubble__tag">
<details name="assignments" class="position-relative" data-controller="expandable" data-action="focusout->expandable#closeOnFocusOutside">
<summary class="btn btn--plain fill-transparent" style="--btn-color: <%= bubble.color %>">
<%= tag.hashtag %>
</summary>
<%= form_with url: bucket_bubble_tagging_swaps_path(bubble.bucket, bubble), data: { controller: "form" } do |form| %>
<%= form.hidden_field :outgoing_tag_id, value: tag.id %>
<%= form.combobox :incoming_tag_id, bucket_bubble_tags_path(bubble.bucket, bubble),
id: dom_id(tag, :tagging), required: true, preload: true, name_when_new: "incoming_tag_title",
data: { controller: "autofocus", action: "hw-combobox:selection->form#submit" } %>
<% end %>
</details>
</div>
<% bubble.tags.each do |tag| %>
<%= link_to tag.hashtag, bubbles_path(@filter.to_params.merge(tag_ids: [ tag.id ])),
class: "btn btn--plain fill-transparent", style: "color: #{bubble.color}" %>
<% end %>
+2 -7
View File
@@ -7,11 +7,8 @@
<strong class="bubble__title-text flex--inline gap-half overflow-ellipsis"><%= bubble.title %></strong>
<% end %>
<div class="flex align-end gap-half">
<% bubble.tags.each do |tag| %>
<%= link_to tag.hashtag, bubbles_path(@filter.to_params.merge(tag_ids: [ tag.id ])),
class: "btn btn--plain txt-small fill-transparent", style: "color: #{bubble.color}" %>
<% end %>
<div class="flex align-end gap-half txt-small">
<%= render "bubbles/tags", bubble: bubble %>
</div>
</div>
@@ -30,6 +27,4 @@
<strong>DUE:</strong> <%= bubble.due_on.strftime("%b %d") %>
</time>
<% end %>
</li>
+52 -7
View File
@@ -1,26 +1,24 @@
<% @page_title = @bubble.title %>
<% @filter ||= Current.user.filters.first || Filter.persist!({}) %>
<% content_for :header do %>
<nav>
<%= link_to "#", class: "btn flex-item-justify-start", data: { controller: "back-navigation", back_navigation_fallback_destination_value: bubbles_path(bucket_id: @bubble.bucket) } do %>
<%= image_tag "arrow-left.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Back</span>
<% end %>
<span class="flex-item-justify-end">
<%= render "bubbles/pop_toggle", bubble: @bubble %>
</span>
</nav>
<% end %>
<aside class="flex align-start justify-end" style="--bubble-color: <%= @bubble.color %>">
<div class="flex flex-column gap-half">
<div class="flex flex-column" style="row-gap: 3px;">
<%= render "bubbles/color", bubble: @bubble %>
<%= form_with model: @bubble, url: bucket_bubble_path(@bubble.bucket, @bubble), data: { controller: "form" } do |form| %>
<label class="btn full-width justify-start borderless">
<%= image_tag "calendar-add.svg", aria: { hidden: true }, size: 24 %>
<span><%= @bubble.due_on.present? ? "Change" : "Add a" %> due date</span>
<span><%= @bubble.due_on.present? ? "Change" : "Add a" %> date</span>
<%= form.date_field :due_on, class: "input input--hidden", data: { action: "change->form#submit click->form#showPicker" } %>
</label>
<% end %>
@@ -28,6 +26,45 @@
<%= render "bubbles/sidebar/assignment", bubble: @bubble %>
<%= render "bubbles/sidebar/tag", bubble: @bubble %>
<%= form_with url: "/", data: { controller: "form" } do |form| %>
<label class="btn full-width justify-start borderless">
<%= image_tag "person.svg", aria: { hidden: true }, size: 24 %>
<span>Assign to…</span>
<%= form.collection_select :assignee_id, @bubble.bucket.users.active, :id, :name, { prompt: "Assign to…", selected: @bubble.assignees.pluck(:id) },
class: "input input--hidden txt-medium",
data: { action: "change->form#submit click->form#showPicker" } %>
</label>
<% end %>
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close">
<button class="btn full-width justify-start borderless" data-action="dialog#toggle">
<%= image_tag "tag.svg", aria: { hidden: true }, size: 24 %>
<span>Tags</span>
</button>
<dialog class="tag-picker panel fill-white shadow gap-half align-center" data-dialog-target="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<%= image_tag "tag.svg", aria: { hidden: true }, size: 24 %>
<%= form_with model: Tag.new, url: bucket_bubble_tags_path(@bubble.bucket, @bubble), class: "min-width flex-item-grow", data: { turbo_frame: "_top" } do |form| %>
<%= form.text_field :title, class: "input", autofocus: "on", list: "tags-list" %>
<%= form.submit "Create Tag", hidden: true %>
<datalist id="tags-list">
<%= Current.account.tags.each do |tag| %>
<option value="<%= tag.title %>"></option>
<% end %>
</datalist>
<% end %>
<form method="dialog">
<button class="btn txt-small" title="Close (esc)">
<%= image_tag "remove.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Close</span>
</button>
</form>
</dialog>
</div>
<% if @bubble.image.attached? %>
<%= button_to bucket_bubble_image_path(@bubble.bucket, @bubble), method: :delete, class: "btn full-width justify-start borderless" do %>
<%= image_tag "picture-add.svg", aria: { hidden: true }, size: 24 %>
@@ -37,7 +74,7 @@
<%= form_with model: @bubble, url: bucket_bubble_path(@bubble.bucket, @bubble), data: { controller: "form" } do |form| %>
<label class="btn full-width justify-start borderless">
<%= image_tag "picture-add.svg", aria: { hidden: true }, size: 24 %>
<span>Add background image</span>
<span>Add an image</span>
<%= form.file_field :image, class: "input",
accept: "image/png, image/jpeg, image/jpg, image/webp",
data: { action: "upload-preview#previewImage form#submit", upload_preview_target: "input" },
@@ -50,6 +87,14 @@
<%= image_tag "thumb-up.svg", aria: { hidden: true }, size: 24 %>
<span>Boost this</span>
<% end %>
<hr class="separator--horizontal full-width" style="--border-color: var(--color-subtle);" />
<%= render "bubbles/pop_toggle", bubble: @bubble %>
<button class="btn full-width justify-start borderless">
<%= image_tag "picture-double.svg", aria: { hidden: true }, size: 24 %>
<span>I've seen this</span>
</button>
</div>
</aside>
+4 -4
View File
@@ -1,9 +1,9 @@
<%= turbo_frame_tag dom_id(@bubble, :stage_picker) do %>
<% if @selected_workflow %>
<aside class="position-relative border pad border-radius" style="--bubble-color: <%= @bubble.color %>"
<aside class="position-relative" style="--bubble-color: <%= @bubble.color %>"
data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<div class="flex align-center justify-start gap-half">
<button class="btn txt-small borderless" data-action="click->dialog#toggle" data-dialog-modal-value="true">
<button class="btn txt-small borderless" style="margin-inline-start: calc((var(--btn-size) + var(--inline-space)) * -0.5);" data-action="click->dialog#toggle" data-dialog-modal-value="true">
<%= image_tag "bolt.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Choose a workflow</span>
</button>
@@ -19,9 +19,9 @@
</menu>
</dialog>
<div class="workflow margin-block-start-half">
<div class="workflow">
<hr class="separator--horizontal" aria-hidden="true" style="--border-color: var(--color-subtle)" />
<div class="flex flex-column gap-half">
<div class="flex flex-column">
<% @selected_workflow.stages.each do |stage| %>
<%= button_to_set_stage @bubble, stage %>
<% end %>
+1 -1
View File
@@ -3,7 +3,7 @@
<%= avatar_tag comment.creator, loading: :lazy %>
</figure>
<div class="comment__content flex flex-column full-width fill-shade border-radius">
<div class="comment__content flex-inline flex-column full-width border border-radius">
<div class="comment__author flex align-center gap-half">
<strong><%= comment.creator.name %></strong>
<%= link_to bucket_bubble_path(comment.bubble.bucket, comment.bubble, anchor: "comment_#{comment.id}"), class: "txt-undecorated" do %>
+2 -2
View File
@@ -1,13 +1,13 @@
<div class="comment flex align-start full-width comment--mine">
<figure class="comment__avatar avatar fill-black txt-reversed flex-item-no-shrink"><strong><%= Current.user.initials %></strong></figure>
<div class="comment__content flex flex-column full-width fill-shade border-radius">
<div class="comment__content flex flex-column full-width">
<div class="comment__author flex align-center gap-half">
<strong><%= Current.user.name %></strong>
</div>
<div class="comment__body txt-align-start margin-block-start-half">
<%= form_with model: Comment.new, url: bucket_bubble_comments_path(bubble.bucket, bubble), class: "flex flex-column gap full-width", data: { controller: "form", action: "keydown.meta+enter->form#submit" } do |form| %>
<%= form.text_area :body, class: "input", required: true, rows: 4, placeholder: new_comment_placeholder(bubble) %>
<%= form.text_area :body, class: "input border border-radius", required: true, rows: 4, placeholder: new_comment_placeholder(bubble) %>
<%= form.button class: "btn btn--reversed center" do %>
<%= image_tag "check.svg", aria: { hidden: "true" }, size: 24 %>
<span class="for-screen-reader">Save</span>
@@ -1,3 +1,3 @@
<div class="event-summary flex-inline flex-wrap align-start fill-white border-radius center position-relative" data-controller="event-summary">
<div class="event-summary flex flex-wrap align-start center" data-controller="event-summary">
<%= event_summary.body %>
</div>