@@ -39,6 +39,31 @@
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[aria-busy] &:disabled {
|
||||
position: relative;
|
||||
|
||||
> * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&::after {
|
||||
--mask: no-repeat radial-gradient(#000 68%,#0000 71%);
|
||||
--size: 1.25em;
|
||||
|
||||
-webkit-mask: var(--mask), var(--mask), var(--mask);
|
||||
-webkit-mask-size: 28% 45%;
|
||||
animation: submitting 1s infinite linear;
|
||||
aspect-ratio: 8/5;
|
||||
background: currentColor;
|
||||
content: "";
|
||||
inline-size: var(--size);
|
||||
inset: 50%;
|
||||
margin-block: calc((var(--size) / 3) * -1);
|
||||
margin-inline: calc((var(--size) / 2) * -1);
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Variants
|
||||
|
||||
@@ -208,6 +208,10 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.no-transitions &:after {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.cards.is-collapsed & {
|
||||
block-size: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
}
|
||||
|
||||
.comment__body {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -135,6 +136,7 @@
|
||||
var(--color-canvas) 0 1px,
|
||||
var(--color-ink-lightest) 1px 10px
|
||||
);
|
||||
padding-inline: var(--comment-padding-inline);
|
||||
}
|
||||
|
||||
.reactions {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
--popup-item-padding-inline: 0.5rem;
|
||||
|
||||
inset: 0 auto auto 50%;
|
||||
max-block-size: 80vh;
|
||||
min-inline-size: min(25ch, calc(100dvw - var(--block-space-double)));
|
||||
max-inline-size: min(55ch, calc(100dvw - var(--block-space-double)));
|
||||
overflow: auto;
|
||||
@@ -32,6 +31,10 @@
|
||||
|
||||
&.orient-top {
|
||||
inset-block: auto 0;
|
||||
|
||||
&.orient-bottom {
|
||||
inset-block: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&:has(.popup__footer) {
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&.orient-right {
|
||||
inset-inline-start: 0;
|
||||
inset-inline: 0 auto;
|
||||
translate: 0 -100%;
|
||||
}
|
||||
|
||||
&.orient-left {
|
||||
inset-inline-end: 0;
|
||||
inset-inline: auto 0;
|
||||
translate: 0 -100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ module ColumnsHelper
|
||||
tag.span(column.name, class: "overflow-ellipsis"),
|
||||
card_triage_path(card, column_id: column),
|
||||
method: :post,
|
||||
class: [ "card__column-name btn", { "card__column-name--current": column == card.column } ],
|
||||
class: [ "card__column-name btn", { "card__column-name--current": column == card.column && card.open? } ],
|
||||
form_class: "flex align-center gap-half",
|
||||
data: { turbo_frame: "_top" }
|
||||
end
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
const BOTTOM_THRESHOLD = 0
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "menu" ]
|
||||
static classes = [ "orientationTop" ]
|
||||
|
||||
close() {
|
||||
this.menuTarget.close()
|
||||
this.#orient()
|
||||
}
|
||||
|
||||
open() {
|
||||
this.menuTarget.show()
|
||||
this.#orient()
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.menuTarget.open ? this.close() : this.open()
|
||||
}
|
||||
|
||||
closeOnClickOutside({ target }) {
|
||||
if (!this.element.contains(target)) this.close()
|
||||
}
|
||||
|
||||
#orient() {
|
||||
this.element.classList.toggle(this.orientationTopClass, this.#distanceToBottom < BOTTOM_THRESHOLD)
|
||||
this.menuTarget.style.setProperty("--max-width", this.#maxWidth + "px")
|
||||
}
|
||||
|
||||
get #distanceToBottom() {
|
||||
return window.innerHeight - this.#boundingClientRect.bottom
|
||||
}
|
||||
|
||||
get #maxWidth() {
|
||||
return window.innerWidth - this.#boundingClientRect.left
|
||||
}
|
||||
|
||||
get #boundingClientRect() {
|
||||
return this.menuTarget.getBoundingClientRect()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import { orient } from "helpers/orientation_helpers"
|
||||
import { limitHeightToViewport } from "helpers/sizing_helpers"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "dialog" ]
|
||||
@@ -21,6 +22,8 @@ export default class extends Controller {
|
||||
orient(this.dialogTarget)
|
||||
}
|
||||
|
||||
limitHeightToViewport(this.dialogTarget, true)
|
||||
|
||||
this.dialogTarget.setAttribute("aria-hidden", "false")
|
||||
this.dispatch("show")
|
||||
}
|
||||
@@ -38,6 +41,7 @@ export default class extends Controller {
|
||||
this.dialogTarget.setAttribute("aria-hidden", "true")
|
||||
this.dialogTarget.blur()
|
||||
orient(this.dialogTarget, false)
|
||||
limitHeightToViewport(this.dialogTarget, false)
|
||||
}
|
||||
|
||||
closeOnClickOutside({ target }) {
|
||||
|
||||
@@ -24,6 +24,7 @@ export default class extends Controller {
|
||||
|
||||
checkNone() {
|
||||
this.checkboxTargets.forEach(checkbox => {
|
||||
if (checkbox.dataset.collectionsFormTarget === "meCheckbox") return
|
||||
checkbox.checked = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ export function orient(el, orient = true) {
|
||||
const directions = [
|
||||
["orient-left", spaceOnRight],
|
||||
["orient-right", spaceOnLeft],
|
||||
["orient-top", spaceOnBottom]
|
||||
["orient-top", spaceOnBottom],
|
||||
["orient-bottom", spaceOnTop]
|
||||
];
|
||||
|
||||
directions.forEach(([className, fn]) =>
|
||||
@@ -23,3 +24,7 @@ function spaceOnRight(el) {
|
||||
function spaceOnBottom(el) {
|
||||
return window.innerHeight - el.getBoundingClientRect().bottom
|
||||
}
|
||||
|
||||
function spaceOnTop(el) {
|
||||
return el.getBoundingClientRect().top
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export function limitHeightToViewport(el, sizing = true, margin = 64) {
|
||||
if (!el) return
|
||||
|
||||
if (sizing) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
const top = Math.max(rect.top, margin)
|
||||
const max = Math.max(0, window.innerHeight - margin - top)
|
||||
el.style.maxHeight = `${max}px`
|
||||
} else {
|
||||
el.style.maxHeight = ""
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,10 @@
|
||||
<%= render "cards/container/title", card: card %>
|
||||
<%= render "cards/display/perma/steps", card: card %>
|
||||
</div>
|
||||
<%= render "cards/triage/columns", card: card %>
|
||||
|
||||
<% if card.published? %>
|
||||
<%= render "cards/triage/columns", card: card %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<footer class="card__footer full-width flex align-start gap">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<%= form_with model: Comment.new, url: card_comments_path(card), class: "flex flex-column gap full-width",
|
||||
data: { controller: "form local-save",
|
||||
local_save_key_value: "comment-#{card.id}",
|
||||
action: "turbo:submit-end->local-save#submit keydown.ctrl+enter->form#submit:prevent keydown.meta+enter->form#submit:prevent keydown.esc->form#cancel:stop" } do |form| %>
|
||||
action: "turbo:submit-end->local-save#submit keydown.ctrl+enter->form#debouncedSubmit:prevent keydown.meta+enter->form#debouncedSubmit:prevent keydown.esc->form#cancel:stop" } do |form| %>
|
||||
<%= form.rich_textarea :body, required: true, placeholder: new_comment_placeholder(card),
|
||||
data: { local_save_target: "input", action: "lexxy:change->form#disableSubmitWhenInvalid lexxy:change->local-save#save turbo:morph-element->local-save#restoreContent" } do %>
|
||||
<%= general_prompts(@card.collection) %>
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
|
||||
<%= render "filters/menu/hotkeys" %>
|
||||
|
||||
<div class="margin-block-start-half txt-x-small flex-inline align-center gap-half justify-center txt-subtle">
|
||||
<span>BOXCAR is designed, built, and backed by</span>
|
||||
<strong><%= icon_tag "37signals" %> <a href="https://37signals.com" target="_blank" class="txt-subtle">37signals</a>.</strong>
|
||||
<div class="margin-block-start-half txt-x-small txt-align-center txt-subtle">
|
||||
BOXCAR is designed, built, and backed by <strong class="txt-nowrap"><%= icon_tag "37signals" %> <a href="https://37signals.com" target="_blank" class="txt-subtle">37signals</a>.</strong>
|
||||
</div>
|
||||
|
||||
<%= render "filters/menu/custom", filters: @user_filtering.filters %>
|
||||
|
||||
Reference in New Issue
Block a user