Merge branch 'main' into notification-index
* main: Don't round up in time distance expression Tidy Gemfile Banner for draft state Drafts should always use the dashed outline wherever they're displayed Unnecessary parens Use distance to nearest edge Simplify overlap logic Fix divider drag jankiness
This commit is contained in:
@@ -16,6 +16,7 @@ gem "bootsnap", require: false
|
||||
gem "puma", ">= 5.0"
|
||||
gem "solid_cable", ">= 3.0"
|
||||
gem "solid_cache", "~> 1.0"
|
||||
gem "solid_queue", "~> 1.1"
|
||||
gem "sqlite3", ">= 2.0"
|
||||
gem "thruster", require: false
|
||||
|
||||
@@ -44,5 +45,3 @@ group :test do
|
||||
gem "capybara"
|
||||
gem "selenium-webdriver"
|
||||
end
|
||||
|
||||
gem "solid_queue", "~> 1.1"
|
||||
|
||||
@@ -366,18 +366,24 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li {
|
||||
border-radius: 0.6em;
|
||||
list-style: none;
|
||||
padding: 0.5em var(--inline-space);
|
||||
position: relative;
|
||||
transition: background-color 200ms ease-out;
|
||||
ul {
|
||||
li {
|
||||
border-radius: 0.6em;
|
||||
list-style: none;
|
||||
padding: 0.5em var(--inline-space);
|
||||
position: relative;
|
||||
transition: background-color 200ms ease-out;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:hover {
|
||||
background-color: color(from var(--bubble-color) srgb r g b / 0.15);
|
||||
border: 0;
|
||||
border-radius: 0.6em;
|
||||
&:not(.dragging) {
|
||||
li {
|
||||
@media (hover: hover) {
|
||||
&:hover {
|
||||
background-color: color(from var(--bubble-color) srgb r g b / 0.15);
|
||||
border: 0;
|
||||
border-radius: 0.6em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -433,6 +439,10 @@
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
|
||||
.drafted & {
|
||||
color: color(from var(--color-ink) srgb r g b / 0.5);
|
||||
}
|
||||
|
||||
&::after {
|
||||
border-block-end: 1px dotted var(--color-subtle-dark);
|
||||
content: "";
|
||||
@@ -442,9 +452,12 @@
|
||||
}
|
||||
|
||||
.bubble__shape {
|
||||
background-color: var(--bubble-color);
|
||||
background-color: var(--bubble-background-color, var(--bubble-color));
|
||||
block-size: var(--bubble-size, 1.2em);
|
||||
border-color: var(--bubble-border-color, var(--bubble-color));
|
||||
border-radius: var(--bubble-shape);
|
||||
border-style: var(--bubble-border-style, solid);
|
||||
border-width: var(--bubble-border-width, 0);
|
||||
inline-size: var(--bubble-size, 1.2em);
|
||||
pointer-events: none;
|
||||
position: relative;
|
||||
@@ -454,13 +467,17 @@
|
||||
|
||||
.bubble & {
|
||||
--bubble-size: 100%;
|
||||
|
||||
background-color: color(from var(--bubble-color) srgb r g b / 0.15);
|
||||
border: var(--bubble-border-width) solid var(--bubble-color);
|
||||
--bubble-background-color: color(from var(--bubble-color) srgb r g b / 0.15);
|
||||
}
|
||||
|
||||
.bubble.drafted & {
|
||||
border-style: dashed;
|
||||
.drafted & {
|
||||
--bubble-border-style: dashed;
|
||||
|
||||
.bubbles-list & {
|
||||
--bubble-background-color: color(from var(--bubble-color) srgb r g b / 0.15);
|
||||
--bubble-border-color: var(--bubble-color);
|
||||
--bubble-border-width: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble:has(.bubble__link) & {
|
||||
|
||||
@@ -169,7 +169,9 @@
|
||||
|
||||
/* Borders */
|
||||
.border { border: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); }
|
||||
.border-top { border-top: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); }
|
||||
.border-block { border-block: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); }
|
||||
.border-bottom { border-block-end: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); }
|
||||
.border-top { border-block-start: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); }
|
||||
.borderless { border: 0; }
|
||||
|
||||
/* Border radius */
|
||||
|
||||
@@ -2,10 +2,11 @@ import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
const MOVE_ITEM_DATA_TYPE = "x-fizzy/move"
|
||||
const DIVIDER_ITEM_NODE_NAME = "LI"
|
||||
const OVERLAP_THRESHOLD = 0.25
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "divider", "dragImage", "count" ]
|
||||
static classes = [ "installed" ]
|
||||
static classes = [ "installed", "dragging" ]
|
||||
static values = { startCount: Number, maxCount: Number }
|
||||
|
||||
connect() {
|
||||
@@ -22,6 +23,7 @@ export default class extends Controller {
|
||||
event.dataTransfer.dropEffect = "move"
|
||||
event.dataTransfer.setData(MOVE_ITEM_DATA_TYPE, event.target)
|
||||
event.dataTransfer.setDragImage(this.dragImageTarget, 0, 0)
|
||||
this.element.classList.add(this.draggingClass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,14 +33,22 @@ export default class extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
moveDivider({ target }) {
|
||||
if (target.nodeName == DIVIDER_ITEM_NODE_NAME) {
|
||||
this.#moveDividerTo(this.#items.indexOf(target))
|
||||
moveDivider(event) {
|
||||
if (event.target.nodeName == DIVIDER_ITEM_NODE_NAME) {
|
||||
const rect = this.dividerTarget.getBoundingClientRect()
|
||||
const distanceToTop = Math.abs(event.clientY - rect.top)
|
||||
const distanceToBottom = Math.abs(event.clientY - (rect.top + rect.height))
|
||||
const distanceToNearestEdge = Math.min(distanceToTop, distanceToBottom)
|
||||
const overlap = distanceToNearestEdge / rect.height
|
||||
|
||||
if (overlap > OVERLAP_THRESHOLD) {
|
||||
this.#moveDividerTo(this.#items.indexOf(event.target))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
persist() {
|
||||
// TODO
|
||||
drop() {
|
||||
this.element.classList.remove(this.draggingClass)
|
||||
}
|
||||
|
||||
#moveDividerTo(index) {
|
||||
|
||||
@@ -55,7 +55,7 @@ class AgoFormatter {
|
||||
}
|
||||
|
||||
#pluralize(word, quantity) {
|
||||
quantity = Math.round(quantity)
|
||||
quantity = Math.floor(quantity)
|
||||
const suffix = (quantity === 1) ? "" : "s"
|
||||
return `${quantity} ${word}${suffix} ago`
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<%= button_to bucket_bubble_publish_path(bubble.bucket, bubble), class: "btn btn--positive full-width justify-start borderless" do %>
|
||||
<%= image_tag "alert.svg", aria: { hidden: true }, size: 24 %>
|
||||
<%= button_to bucket_bubble_publish_path(bubble.bucket, bubble), class: "btn txt-small btn--link" do %>
|
||||
<span>Publish</span>
|
||||
<% end %>
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
data-divider-start-count-value="10"
|
||||
data-divider-max-count-value="10"
|
||||
data-divider-installed-class="bubbles-list__divider--installed"
|
||||
data-action="turbo:morph@document->divider#install dragstart->divider#configureDrag dragenter->divider#acceptDrop dragover->divider#acceptDrop dragover->divider#moveDivider drop->divider#persist">
|
||||
data-divider-dragging-class="dragging"
|
||||
data-action="turbo:morph@document->divider#install dragstart->divider#configureDrag dragenter->divider#acceptDrop dragover->divider#acceptDrop dragover->divider#moveDivider drop->divider#drop">
|
||||
<%= render partial: "bubbles/list/bubble", collection: @bubbles, cached: true %>
|
||||
<%= render "bubbles/list/divider", filter: @filter %>
|
||||
</ul>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<li class="flex align-center gap-half margin-none" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
|
||||
<li class="<%= class_names("flex align-center gap-half margin-none", drafted: bubble.drafted?) %>" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
|
||||
data-controller="animation" data-animation-play-class="bubble--wobble" data-animation-play-on-load-value="true" data-action="mouseover->animation#play">
|
||||
<div class="bubble__shape flex-item-no-shrink"></div>
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<% @page_title = @bubble.title %>
|
||||
|
||||
<% content_for :header do %>
|
||||
<% if @bubble.drafted? %>
|
||||
<div class="flex align-center gap-half fill-selected justify-center border-block margin-block-end"
|
||||
style="--border-color: var(--color-selected-dark); --border-style: dashed; view-transition-name: draft-banner;">
|
||||
This a draft, it’s only visible to you.
|
||||
<%= render "bubbles/publish", bubble: @bubble %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<nav class="align-start">
|
||||
<%= link_to "#", class: "btn flex-item-justify-start", data: { controller: "hotkey back-navigation", action: "keydown.esc@document->hotkey#click", back_navigation_fallback_destination_value: bubbles_path(bucket_id: @bucket) } do %>
|
||||
<%= image_tag "arrow-left.svg", aria: { hidden: true }, size: 24 %>
|
||||
@@ -56,9 +64,7 @@
|
||||
<% end %>
|
||||
|
||||
<hr class="separator--horizontal full-width" style="--border-color: var(--color-subtle);" />
|
||||
<% if @bubble.drafted? %>
|
||||
<%= render "bubbles/publish", bubble: @bubble %>
|
||||
<% else %>
|
||||
<% unless @bubble.drafted? %>
|
||||
<%= render "bubbles/pop_toggle", bubble: @bubble %>
|
||||
<button class="btn full-width justify-start borderless">
|
||||
<%= image_tag "picture-double.svg", aria: { hidden: true }, size: 24 %>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<%= link_to bubbles_path(bucket_ids: [ bucket ]), class: "border border-radius margin-block-end-half windshield__container flex justify-center align-center position-relative" do %>
|
||||
<div class="windshield bucket__windshield flex flex-wrap gap justify-center align-end" style="view-transition-name: windshield_<%= bucket.id %>">
|
||||
<% bucket.bubbles.ordered_by_activity.limit(10).each do |bubble| %>
|
||||
<div class="bubble" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %> <%= bubble_size(bubble) %>">
|
||||
<div class="<%= class_names("bubble", drafted: bubble.drafted?) %>" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %> <%= bubble_size(bubble) %>">
|
||||
<span class="bubble__shape"></span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
Reference in New Issue
Block a user