Drag bubble divider
This commit is contained in:
@@ -397,13 +397,29 @@
|
||||
--divider-color: var(--color-subtle-dark);
|
||||
|
||||
font-size: 1rem;
|
||||
cursor: grab;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.bubbles-list__divider--positioned {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.divider-drag-image {
|
||||
background-color: var(--color-link);
|
||||
border-radius: 1rem;
|
||||
color: var(--color-ink-reversed);
|
||||
inset: auto 100% 100% auto;
|
||||
line-height: 2rem;
|
||||
padding: 0 1rem;
|
||||
position: fixed;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
.btn--reversed.bubbles-list__handle {
|
||||
--btn-background: var(--divider-color);
|
||||
|
||||
font-size: 0.9rem;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.bubbles-list__count {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import { get, patch } from "@rails/request.js"
|
||||
|
||||
const MOVE_ITEM_DATA_TYPE = "x-fizzy/move"
|
||||
const DIVIDER_ITEM_NODE_NAME = "LI"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "divider", "dragImage", "count" ]
|
||||
static classes = [ "positioned" ]
|
||||
static values = { startCount: Number, maxCount: Number }
|
||||
|
||||
connect() {
|
||||
this.install()
|
||||
}
|
||||
|
||||
install() {
|
||||
this.#positionDividerElement(this.startCountValue)
|
||||
}
|
||||
|
||||
configureDrag(event) {
|
||||
if (event.target == this.dividerTarget) {
|
||||
event.dataTransfer.dropEffect = "move"
|
||||
event.dataTransfer.setData(MOVE_ITEM_DATA_TYPE, event.target)
|
||||
event.dataTransfer.setDragImage(this.dragImageTarget, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
moveDivider(event) {
|
||||
if (event.target.nodeName != DIVIDER_ITEM_NODE_NAME) return
|
||||
|
||||
const targetIndex = this.#items.indexOf(event.target)
|
||||
|
||||
if (targetIndex > this.maxCountValue) return
|
||||
|
||||
if (this.#dividerIndex < targetIndex) {
|
||||
event.target.after(this.dividerTarget)
|
||||
} else {
|
||||
event.target.before(this.dividerTarget)
|
||||
}
|
||||
|
||||
this.countTarget.textContent = targetIndex
|
||||
}
|
||||
|
||||
persist() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
acceptDrop(event) {
|
||||
const isDroppable = event.dataTransfer.types.includes(MOVE_ITEM_DATA_TYPE)
|
||||
if (isDroppable) event.preventDefault()
|
||||
}
|
||||
|
||||
#positionDividerElement(index) {
|
||||
if (index == 0) {
|
||||
this.#items[0].before(this.dividerTarget)
|
||||
} else if (index <= this.#items.length - 1) {
|
||||
this.#items[index - 1].after(this.dividerTarget)
|
||||
} else {
|
||||
this.#items[this.#items.length - 1].after(this.dividerTarget)
|
||||
}
|
||||
|
||||
this.dividerTarget.classList.add(this.positionedClass)
|
||||
}
|
||||
|
||||
get #items() {
|
||||
return Array.from(this.element.children)
|
||||
}
|
||||
|
||||
get #dividerIndex() {
|
||||
return this.#items.indexOf(this.dividerTarget)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
// FIXME: Can we do this without a controller? https://github.com/basecamp/fizzy/pull/130#discussion_r1833094616
|
||||
export default class extends Controller {
|
||||
merge({ params: { key, value } }) {
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.set(key, value)
|
||||
Turbo.visit(url)
|
||||
}
|
||||
}
|
||||
@@ -34,20 +34,14 @@
|
||||
</section>
|
||||
|
||||
<section class="bubbles-list unpad-inline center margin-block-start">
|
||||
<ul class="unpad margin-none flex flex-column txt-align-start center">
|
||||
<li class="bubbles-list__divider flex align-center gap-half full-width">
|
||||
<button class="bubbles-list__handle btn btn--reversed">
|
||||
<%= image_tag "drag.svg", aria: { hidden: true }, size: 16 %>
|
||||
<span class="for-screen-reader">Drag to change number of bubbles shown above</span>
|
||||
</button>
|
||||
<hr class="separator--horizontal flex-item-grow">
|
||||
<strong class="bubbles-list__count border-radius">
|
||||
Top 10
|
||||
</strong>
|
||||
<hr class="separator--horizontal flex-item-grow">
|
||||
<span></span>
|
||||
</li>
|
||||
<ul class="unpad margin-none flex flex-column txt-align-start center"
|
||||
data-controller="divider"
|
||||
data-divider-start-count-value="10"
|
||||
data-divider-max-count-value="10"
|
||||
data-divider-positioned-class="bubbles-list__divider--positioned"
|
||||
data-action="turbo:morph@document->divider#install dragstart->divider#configureDrag dragenter->divider#acceptDrop dragover->divider#acceptDrop dragover->divider#moveDivider drop->divider#persist">
|
||||
<%= render partial: "bubbles/list/bubble", collection: @bubbles, cached: true %>
|
||||
<%= render "bubbles/list/divider", filter: @filter %>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<li class="bubbles-list__divider flex align-center gap-half full-width" draggable="true" data-divider-target="divider">
|
||||
<div class="divider-drag-image" data-divider-target="dragImage">Drag up or down</div>
|
||||
<button class="bubbles-list__handle btn btn--reversed">
|
||||
<%= image_tag "drag.svg", aria: { hidden: true }, size: 16 %>
|
||||
<span class="for-screen-reader">Drag to change number of bubbles shown above</span>
|
||||
</button>
|
||||
<hr class="separator--horizontal flex-item-grow">
|
||||
<strong class="bubbles-list__count border-radius">
|
||||
Top <span data-divider-target="count">10</span>
|
||||
</strong>
|
||||
<hr class="separator--horizontal flex-item-grow">
|
||||
<span></span>
|
||||
</li>
|
||||
@@ -1,4 +1,4 @@
|
||||
<div name="assignments" class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn full-width justify-start borderless" data-action="click->dialog#open:stop">
|
||||
<%= image_tag "person.svg", aria: { hidden: true }, size: 24 %>
|
||||
<span>Assign to someone</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div name="assignments" class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<div class="position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn full-width justify-start borderless" data-action="click->dialog#open:stop">
|
||||
<%= image_tag "tag.svg", aria: { hidden: true }, size: 24 %>
|
||||
<span>Tag this</span>
|
||||
|
||||
Reference in New Issue
Block a user