From b3cfae352975ddcaf4031cd6cfa4de842e8ca0ec Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 12:29:01 -0600 Subject: [PATCH 01/23] Consolidate UI elements from "the stream" and "Considering" to "Maybe?" --- app/assets/stylesheets/_global.css | 2 +- app/assets/stylesheets/blank-slates.css | 2 +- app/assets/stylesheets/card-columns.css | 16 ++++++++-------- app/assets/stylesheets/print.css | 4 ++-- app/views/boards/show/_columns.html.erb | 2 +- .../show/{_stream.html.erb => _maybe.html.erb} | 4 ++-- app/views/boards/show/_mobile_columns.html.erb | 2 +- .../cards/drops/streams/create.turbo_stream.erb | 2 +- app/views/public/boards/show/_columns.html.erb | 2 +- app/views/public/boards/show/_stream.html.erb | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) rename app/views/boards/show/{_stream.html.erb => _maybe.html.erb} (76%) diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css index dc928b40d4..213d921e4d 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/_global.css @@ -205,7 +205,7 @@ --color-terminal-text: var(--color-ink); --color-terminal-text-light: var(--color-ink-lighter); --color-golden: oklch(89.1% 0.178 95.7); - --color-considering: oklch(var(--lch-blue-medium)); + --color-maybe: oklch(var(--lch-blue-medium)); /* Colors: Cards */ --color-card-default: oklch(var(--lch-blue-dark)); diff --git a/app/assets/stylesheets/blank-slates.css b/app/assets/stylesheets/blank-slates.css index 0725dd3362..3c36b30da5 100644 --- a/app/assets/stylesheets/blank-slates.css +++ b/app/assets/stylesheets/blank-slates.css @@ -11,7 +11,7 @@ white-space: nowrap; } - .cards--considering & { + .cards--maybe & { background-color: var(--card-bg-color) !important; } diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index c239e1b9d1..6d60119063 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -128,7 +128,7 @@ translate: 0; transition: translate var(--column-transition-duration) var(--ease-out-overshoot-subtle); - .is-collapsed:not(.cards--considering) & { + .is-collapsed:not(.cards--maybe) & { translate: 0 var(--column-width-collapsed); } @@ -354,7 +354,7 @@ justify-content: center; } - .cards:is(.cards--considering) &:hover { + .cards:is(.cards--maybe) &:hover { cursor: unset; filter: none; } @@ -382,7 +382,7 @@ writing-mode: vertical-rl; } - .cards:not(.is-collapsed, .cards--considering) & { + .cards:not(.is-collapsed, .cards--maybe) & { align-items: center; display: flex; gap: 0.25ch; @@ -523,11 +523,11 @@ } } - /* Considering + /* Maybe /* ------------------------------------------------------------------------ */ - .cards--considering { - --card-color: oklch(var(--lch-blue-medium)); + .cards--maybe { + --card-color: var(--color-maybe); position: relative; @@ -664,7 +664,7 @@ /* -------------------------------------------------------------------------- */ /* Surface a mini bubble if there are cards with bubbles inside */ - .cards--considering:has(.bubble:not([hidden])) .cards__expander-title, + .cards--maybe:has(.bubble:not([hidden])) .cards__expander-title, .cards--doing.is-collapsed:has(.bubble:not([hidden])) .cards__transition-container { --bubble-color: var(--card-color, oklch(var(--lch-blue-medium))); --bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%; @@ -685,7 +685,7 @@ } /* Maybe column: position bubble relative to the title, not the container */ - .cards--considering & { + .cards--maybe & { overflow: visible; position: relative; diff --git a/app/assets/stylesheets/print.css b/app/assets/stylesheets/print.css index c794934588..f700b9332f 100644 --- a/app/assets/stylesheets/print.css +++ b/app/assets/stylesheets/print.css @@ -125,7 +125,7 @@ .card--new, .cards__decoration, .card-columns:before, - .cards--considering:before { + .cards--maybe:before { display: none; } @@ -140,7 +140,7 @@ padding-inline: 0; } - .cards--considering { + .cards--maybe { background: none; margin: 0; padding-inline: 1ch; diff --git a/app/views/boards/show/_columns.html.erb b/app/views/boards/show/_columns.html.erb index a6001da79a..34f926bfc2 100644 --- a/app/views/boards/show/_columns.html.erb +++ b/app/views/boards/show/_columns.html.erb @@ -23,7 +23,7 @@ <%= render "boards/show/not_now", board: board %> - <%= render "boards/show/stream", board: board, page: page %> + <%= render "boards/show/maybe", board: board, page: page %>
<%= render partial: "boards/show/column", collection: board.columns.sorted, cached: ->(column){ [ column, column.leftmost?, column.rightmost? ] } %> diff --git a/app/views/boards/show/_stream.html.erb b/app/views/boards/show/_maybe.html.erb similarity index 76% rename from app/views/boards/show/_stream.html.erb rename to app/views/boards/show/_maybe.html.erb index d4753eba59..6fb46b7b5c 100644 --- a/app/views/boards/show/_stream.html.erb +++ b/app/views/boards/show/_maybe.html.erb @@ -1,4 +1,4 @@ -<%= column_tag id: "the-stream", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--considering" do %> +<%= column_tag id: "maybe", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--maybe" do %>

Maybe?

@@ -10,7 +10,7 @@
<%= render "columns/show/add_card_button", board: board %> <% if page.used? %> - <%= with_automatic_pagination "the-stream", @page do %> + <%= with_automatic_pagination "maybe", @page do %> <%= render "boards/columns/list", cards: page.records, draggable: true %> <% end %> <% else %> diff --git a/app/views/boards/show/_mobile_columns.html.erb b/app/views/boards/show/_mobile_columns.html.erb index 964d75220a..e8f5938ae9 100644 --- a/app/views/boards/show/_mobile_columns.html.erb +++ b/app/views/boards/show/_mobile_columns.html.erb @@ -12,7 +12,7 @@
<% end %> - <%= link_to board_columns_stream_path(board), class: "cards cards--considering is-collapsed", data: { turbo_frame: "_top" } do %> + <%= link_to board_columns_stream_path(board), class: "cards cards--maybe is-collapsed", data: { turbo_frame: "_top" } do %>
<%= board.cards.awaiting_triage.count %>

diff --git a/app/views/columns/cards/drops/streams/create.turbo_stream.erb b/app/views/columns/cards/drops/streams/create.turbo_stream.erb index 3f62516453..3141b847f0 100644 --- a/app/views/columns/cards/drops/streams/create.turbo_stream.erb +++ b/app/views/columns/cards/drops/streams/create.turbo_stream.erb @@ -1 +1 @@ -<%= turbo_stream.replace("the-stream", partial: "boards/show/stream", method: :morph, locals:{ board: @card.board, page: @page }) %> +<%= turbo_stream.replace("maybe", partial: "boards/show/maybe", method: :morph, locals:{ board: @card.board, page: @page }) %> diff --git a/app/views/public/boards/show/_columns.html.erb b/app/views/public/boards/show/_columns.html.erb index 59f2b5e39d..de0948491a 100644 --- a/app/views/public/boards/show/_columns.html.erb +++ b/app/views/public/boards/show/_columns.html.erb @@ -10,7 +10,7 @@ <%= render "public/boards/show/not_now", board: board %>

- <%= render "public/boards/show/stream", board: board, page: page %> + <%= render "public/boards/show/maybe", board: board, page: page %>
<%= render partial: "public/boards/show/column", collection: board.columns, cached: true %> diff --git a/app/views/public/boards/show/_stream.html.erb b/app/views/public/boards/show/_stream.html.erb index 8fea976b61..9d041c1cdc 100644 --- a/app/views/public/boards/show/_stream.html.erb +++ b/app/views/public/boards/show/_stream.html.erb @@ -1,4 +1,4 @@ -
From 3b08041a3e6e887a512cf3e9b1a8af97adf2ef28 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 13:16:45 -0600 Subject: [PATCH 02/23] Only use grid layout when centering the Maybe column --- app/assets/stylesheets/card-columns.css | 60 +++++++++---------- .../collapsible_columns_controller.js | 4 +- app/views/boards/show/_columns.html.erb | 1 + app/views/boards/show/_maybe.html.erb | 15 +++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 6d60119063..bd1ff3db68 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -19,9 +19,9 @@ --progress-max-height: 50dvh; container-type: inline-size; - display: grid; + display: flex; + justify-content: center; gap: var(--column-gap); - grid-template-columns: 1fr var(--column-width-expanded) 1fr; margin-inline: auto; max-inline-size: var(--main-width); overflow-x: auto; @@ -29,37 +29,39 @@ padding-block-end: var(--column-width-collapsed); position: relative; - /* When it has something expanded */ - &:has(.card-columns__left .cards:not(.is-collapsed), .card-columns__right .cards:not(.is-collapsed)) { - grid-template-columns: auto var(--column-width-expanded) auto; - } - &:has(.cards) { min-block-size: 20lh; } - - body:not(.public) & { - @media (max-width: 519px) { - display: none; - } - } } .card-columns__left, .card-columns__right { - align-items: stretch; - display: flex; - gap: var(--column-gap); + display: contents; } - .card-columns__left { - justify-content: end; - padding-inline-start: var(--column-gap); - } + /* Center the Maybe? column when all the other columns are collapsed */ + @media (min-width: 640px) { + .card-columns:not(:has(.card-columns__left .is-expanded, .card-columns__right .is-expanded)) { + display: grid; + grid-template-columns: 1fr auto 1fr; - .card-columns__right { - justify-content: start; - padding-inline-end: var(--column-gap); + .card-columns__left, + .card-columns__right { + align-items: stretch; + display: flex; + gap: var(--column-gap); + } + + .card-columns__left { + justify-content: end; + padding-inline-start: var(--column-gap); + } + + .card-columns__right { + justify-content: start; + padding-inline-end: var(--column-gap); + } + } } /* Column @@ -128,7 +130,7 @@ translate: 0; transition: translate var(--column-transition-duration) var(--ease-out-overshoot-subtle); - .is-collapsed:not(.cards--maybe) & { + .is-collapsed & { translate: 0 var(--column-width-collapsed); } @@ -353,11 +355,6 @@ inline-size: 100%; justify-content: center; } - - .cards:is(.cards--maybe) &:hover { - cursor: unset; - filter: none; - } } .cards__expander-count { @@ -382,7 +379,7 @@ writing-mode: vertical-rl; } - .cards:not(.is-collapsed, .cards--maybe) & { + .cards:not(.is-collapsed) & { align-items: center; display: flex; gap: 0.25ch; @@ -691,7 +688,8 @@ &:before { inset-block-start: 50%; - translate: 125% -75%; + inset-inline-start: 0; + translate: -125% -75%; z-index: -1; } } diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index 2c97fcd097..5622bb24a6 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus" import { nextFrame, debounce } from "helpers/timing_helpers"; export default class extends Controller { - static classes = [ "collapsed", "noTransitions", "titleNotVisible" ] + static classes = [ "collapsed", "expanded", "noTransitions", "titleNotVisible" ] static targets = [ "column", "button", "title" ] static values = { board: String @@ -89,6 +89,7 @@ export default class extends Controller { const key = this.#localStorageKeyFor(column) this.#buttonFor(column).setAttribute("aria-expanded", "false") + column.classList.remove(this.expandedClass) column.classList.add(this.collapsedClass) localStorage.removeItem(key) } @@ -98,6 +99,7 @@ export default class extends Controller { this.#buttonFor(column).setAttribute("aria-expanded", "true") column.classList.remove(this.collapsedClass) + column.classList.add(this.expandedClass) localStorage.setItem(key, true) } diff --git a/app/views/boards/show/_columns.html.erb b/app/views/boards/show/_columns.html.erb index 34f926bfc2..cb7d4c086e 100644 --- a/app/views/boards/show/_columns.html.erb +++ b/app/views/boards/show/_columns.html.erb @@ -4,6 +4,7 @@ drag_and_drop_hover_container_class: "drag-and-drop__hover-container", collapsible_columns_board_value: board.id, collapsible_columns_collapsed_class: "is-collapsed", + collapsible_columns_expanded_class: "is-expanded", collapsible_columns_no_transitions_class: "no-transitions", collapsible_columns_title_not_visible_class: "is-off-screen", navigable_list_supports_vertical_navigation_value: false, diff --git a/app/views/boards/show/_maybe.html.erb b/app/views/boards/show/_maybe.html.erb index 6fb46b7b5c..4ef7c4a01d 100644 --- a/app/views/boards/show/_maybe.html.erb +++ b/app/views/boards/show/_maybe.html.erb @@ -1,12 +1,11 @@ -<%= column_tag id: "maybe", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--maybe" do %> +<%= column_tag id: "maybe", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--maybe", data: { + drag_and_strum_target: "container", + collapsible_columns_target: "column", + action: "focus->collapsible-columns#focusOnColumn" +} do %>
-
-

Maybe?

-
- <%= link_to board_columns_stream_path(board), class: "cards__maximize-button btn btn--circle txt-x-small borderless", data: { turbo_frame: "_top" } do %> - <%= icon_tag "grid", class: "translucent" %> - Expand column - <% end %> + <%= render "boards/show/expander", title: "Maybe?", count: board.cards.awaiting_triage.count, column_id: "maybe" %> + <%= render "boards/show/menu/maximize", column_path: board_columns_stream_path(board) %>
<%= render "columns/show/add_card_button", board: board %> <% if page.used? %> From c6bfeb6982eb85df26d736d1b8eedc01731e182b Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 13:49:17 -0600 Subject: [PATCH 03/23] Handle Maybe column state at desktop breakpoint --- app/assets/stylesheets/card-columns.css | 10 ++++++- .../collapsible_columns_controller.js | 30 +++++++++++++++++-- app/views/boards/show/_maybe.html.erb | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index bd1ff3db68..59edac1290 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -297,8 +297,16 @@ position: relative; text-transform: uppercase; + &[disabled] { + opacity: 1; + } + @media (any-hover: hover) { - &:hover { + .is-expanded &:hover { + filter: none; + } + + .is-collapsed &:hover { filter: brightness(0.9); } } diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index 5622bb24a6..bf0ff96549 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -3,9 +3,10 @@ import { nextFrame, debounce } from "helpers/timing_helpers"; export default class extends Controller { static classes = [ "collapsed", "expanded", "noTransitions", "titleNotVisible" ] - static targets = [ "column", "button", "title" ] + static targets = [ "column", "button", "title", "maybeColumn" ] static values = { - board: String + board: String, + desktopBreakpoint: { type: String, default: "(min-width: 640px)" } } initialize() { @@ -15,6 +16,11 @@ export default class extends Controller { async connect() { await this.#restoreColumnsDisablingTransitions() this.#setupIntersectionObserver() + + this.mediaQuery = window.matchMedia(this.desktopBreakpointValue) + this.handleDesktop = this.#handleDesktop.bind(this) + this.mediaQuery.addEventListener("change", this.handleDesktop) + this.handleDesktop(this.mediaQuery) } disconnect() { @@ -22,6 +28,7 @@ export default class extends Controller { this._intersectionObserver.disconnect() this._intersectionObserver = null } + this.mediaQuery.removeEventListener("change", this.handleDesktop) } toggle({ target }) { @@ -142,4 +149,23 @@ export default class extends Controller { this.titleTargets.forEach(title => this._intersectionObserver.observe(title)) } + + #handleDesktop(e) { + const matches = e.matches ?? e // handle both Event and MediaQueryList + matches ? this.#disableMaybeToggle() : this.#enableMaybeToggle() + } + + #disableMaybeToggle() { + this.#expand(this.maybeColumnTarget) + this.#maybeButton.setAttribute("disabled", true) + } + + #enableMaybeToggle() { + this.#collapse(this.maybeColumnTarget) + this.#maybeButton.removeAttribute("disabled") + } + + get #maybeButton() { + return this.maybeColumnTarget.querySelector('[data-collapsible-columns-target="button"]') + } } diff --git a/app/views/boards/show/_maybe.html.erb b/app/views/boards/show/_maybe.html.erb index 4ef7c4a01d..b060c357db 100644 --- a/app/views/boards/show/_maybe.html.erb +++ b/app/views/boards/show/_maybe.html.erb @@ -1,6 +1,6 @@ <%= column_tag id: "maybe", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--maybe", data: { drag_and_strum_target: "container", - collapsible_columns_target: "column", + collapsible_columns_target: "column maybeColumn", action: "focus->collapsible-columns#focusOnColumn" } do %>
From b80499e955ca021757bbe55d191e6b8019afbe11 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 14:08:22 -0600 Subject: [PATCH 04/23] Leave Maybe column expanded on Desktop --- .../collapsible_columns_controller.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index bf0ff96549..cd533220ec 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -81,7 +81,9 @@ export default class extends Controller { } #collapseAllExcept(clickedColumn) { - this.columnTargets.forEach(column => { + const columns = this.#isDesktop ? this.columnTargets.filter(c => c !== this.maybeColumnTarget) : this.columnTargets + + columns.forEach(column => { if (column !== clickedColumn) { this.#collapse(column) } @@ -150,18 +152,21 @@ export default class extends Controller { this.titleTargets.forEach(title => this._intersectionObserver.observe(title)) } + #isDesktop(e) { + return e.matches ?? e + } + #handleDesktop(e) { - const matches = e.matches ?? e // handle both Event and MediaQueryList - matches ? this.#disableMaybeToggle() : this.#enableMaybeToggle() + this.#isDesktop(e) ? this.#handleDesktopMode() : this.#handleMobileMode() } - #disableMaybeToggle() { + async #handleDesktopMode() { this.#expand(this.maybeColumnTarget) this.#maybeButton.setAttribute("disabled", true) } - #enableMaybeToggle() { - this.#collapse(this.maybeColumnTarget) + #handleMobileMode() { + this.columnTargets.forEach(column => this.#collapse(column)) this.#maybeButton.removeAttribute("disabled") } From a94f6e8f0d655cc23867856a9c97e9bd25d23504 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 14:40:20 -0600 Subject: [PATCH 05/23] Remove old mobile columns stuff --- app/assets/stylesheets/card-columns.css | 47 ++----------------- app/views/boards/show.html.erb | 5 +- .../boards/show/_mobile_columns.html.erb | 43 ----------------- 3 files changed, 7 insertions(+), 88 deletions(-) delete mode 100644 app/views/boards/show/_mobile_columns.html.erb diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 59edac1290..a3f4f0e36c 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -738,53 +738,12 @@ } } - /* Mobile columns + /* Mobile stuff /* -------------------------------------------------------------------------- */ - .mobile-card-columns { - --column-gap: 8px; - --column-padding-expanded: calc(var(--column-gap) * 2); - --column-width-collapsed: 40px; - --progress-increment: var(--progress-max-width) / var(--progress-max-cards); - --progress-max-cards: 20; - --progress-max-width: 100%; - - padding-inline: 3vw; - - /* Hide on larger devices with cursors */ - @media (min-width: 520px) { + @media (min-width: 640px) { + .hide-on-desktop { display: none; } - - .cards.is-collapsed { - inline-size: auto; - display: block; - padding-block: 0.5ch; - - .cards__expander { - --gradient-direction: to right; - - flex-direction: row; - inline-size: auto; - - &:before { - block-size: 1px; - inline-size: 100%; - inset: 50% 0 auto; - translate: 0 -50%; - } - - &:after { - block-size: var(--column-width-collapsed); - inline-size: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment)); - margin-inline-start: 0; - max-inline-size: var(--progress-max-width); - } - } - - .cards__expander-title { - writing-mode: revert; - } - } } } diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index 9f0c2ebeef..c770a9b00e 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -21,11 +21,14 @@ <%= hidden_field_tag "board_ids[]", @board.id %> <% end %> +
+ <%= render "columns/show/add_card_button", board: @board %> +
+ <%= turbo_frame_tag :cards_container do %> <% if @filter.used?(ignore_boards: true) %> <%= render "boards/show/filtered_cards", page: @page %> <% else %> <%= render "boards/show/columns", page: @page, board: @board %> - <%= render "boards/show/mobile_columns", page: @page, board: @board %> <% end %> <% end %> diff --git a/app/views/boards/show/_mobile_columns.html.erb b/app/views/boards/show/_mobile_columns.html.erb deleted file mode 100644 index e8f5938ae9..0000000000 --- a/app/views/boards/show/_mobile_columns.html.erb +++ /dev/null @@ -1,43 +0,0 @@ -
-
- <%= render "columns/show/add_card_button", board: board %> -
- - <%= link_to board_columns_not_now_path(board), class: "cards cards--on-deck is-collapsed", style: "--card-color: var(--color-card-complete);", data: { turbo_frame: "_top" } do %> -
- <%= board.cards.postponed.count %> -

- Not Now -

-
- <% end %> - - <%= link_to board_columns_stream_path(board), class: "cards cards--maybe is-collapsed", data: { turbo_frame: "_top" } do %> -
- <%= board.cards.awaiting_triage.count %> -

- Maybe? -

-
- <% end %> - - <% board.columns.sorted.each do |column| %> - <%= link_to board_column_path(column.board, column), class: "cards cards--doing is-collapsed", style: "--card-color: #{column.color}", data: { turbo_frame: "_top" } do %> -
- <%= column.cards.active.count %> -

- <%= column.name %> -

-
- <% end %> - <% end %> - - <%= link_to board_columns_closed_path(board), class: "cards cards--closed is-collapsed", style: "--card-color: var(--color-card-complete);", data: { turbo_frame: "_top" } do %> -
- <%= board.cards.closed.count %> -

- Done -

-
- <% end %> -
From c97973149196356f7d1014539a134ac8be89042c Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 14:46:04 -0600 Subject: [PATCH 06/23] Use getter for isDesktop --- .../controllers/collapsible_columns_controller.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index cd533220ec..26950f36a2 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -152,12 +152,12 @@ export default class extends Controller { this.titleTargets.forEach(title => this._intersectionObserver.observe(title)) } - #isDesktop(e) { - return e.matches ?? e + get #isDesktop() { + return this.mediaQuery?.matches } - #handleDesktop(e) { - this.#isDesktop(e) ? this.#handleDesktopMode() : this.#handleMobileMode() + #handleDesktop() { + this.#isDesktop ? this.#handleDesktopMode() : this.#handleMobileMode() } async #handleDesktopMode() { From 0d370a04a2ad1c59e0f52d6f6a777e3fc568afde Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 14:49:13 -0600 Subject: [PATCH 07/23] Fix .closest selector to be more fuzzy --- app/javascript/controllers/collapsible_columns_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index 26950f36a2..e9974b0ce3 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -32,7 +32,7 @@ export default class extends Controller { } toggle({ target }) { - const column = target.closest('[data-collapsible-columns-target="column"]') + const column = target.closest('[data-collapsible-columns-target~="column"]') this.#toggleColumn(column); } From 44e7e662a8d2903ee9f70ee12bae6c0e146f2539 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 14:54:03 -0600 Subject: [PATCH 08/23] Adjust padding on new card element --- app/assets/stylesheets/card-columns.css | 6 ++++-- app/views/boards/show.html.erb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index a3f4f0e36c..165208e0f3 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -741,8 +741,10 @@ /* Mobile stuff /* -------------------------------------------------------------------------- */ - @media (min-width: 640px) { - .hide-on-desktop { + .mobile-add-card-container { + padding-inline: 1rem; + + @media (min-width: 640px) { display: none; } } diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index c770a9b00e..e9d3bbe513 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -21,7 +21,7 @@ <%= hidden_field_tag "board_ids[]", @board.id %> <% end %> -
+
<%= render "columns/show/add_card_button", board: @board %>
From bf62c97c25f811011468a0a8aabce73f05b89160 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 16:18:47 -0600 Subject: [PATCH 09/23] Fix horizontal scrolling --- app/assets/stylesheets/card-columns.css | 109 +++++++++++++++--------- app/views/boards/show.html.erb | 4 - 2 files changed, 71 insertions(+), 42 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 165208e0f3..691284c8cd 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -19,49 +19,48 @@ --progress-max-height: 50dvh; container-type: inline-size; - display: flex; - justify-content: center; + display: grid; gap: var(--column-gap); + grid-template-columns: 1fr auto 1fr; margin-inline: auto; max-inline-size: var(--main-width); + outline: none; overflow-x: auto; overflow-y: hidden; padding-block-end: var(--column-width-collapsed); position: relative; + /* When it has something expanded */ + &:has(.card-columns__left .cards:not(.is-collapsed), .card-columns__right .cards:not(.is-collapsed)) { + grid-template-columns: auto var(--column-width-expanded) auto; + } + &:has(.cards) { min-block-size: 20lh; } + + body:not(.public) & { + @media (max-width: 519px) { + display: none; + } + } } .card-columns__left, .card-columns__right { - display: contents; + align-items: stretch; + display: flex; + gap: var(--column-gap); } - /* Center the Maybe? column when all the other columns are collapsed */ - @media (min-width: 640px) { - .card-columns:not(:has(.card-columns__left .is-expanded, .card-columns__right .is-expanded)) { - display: grid; - grid-template-columns: 1fr auto 1fr; - - .card-columns__left, - .card-columns__right { - align-items: stretch; - display: flex; - gap: var(--column-gap); - } - - .card-columns__left { - justify-content: end; - padding-inline-start: var(--column-gap); - } + .card-columns__left { + justify-content: end; + padding-inline-start: var(--column-gap); + } - .card-columns__right { - justify-content: start; - padding-inline-end: var(--column-gap); - } - } + .card-columns__right { + justify-content: start; + padding-inline-end: var(--column-gap); } /* Column @@ -302,11 +301,7 @@ } @media (any-hover: hover) { - .is-expanded &:hover { - filter: none; - } - - .is-collapsed &:hover { + .is-collapsed:hover { filter: brightness(0.9); } } @@ -528,11 +523,11 @@ } } - /* Maybe + /* Considering /* ------------------------------------------------------------------------ */ .cards--maybe { - --card-color: var(--color-maybe); + --card-color: oklch(var(--lch-blue-medium)); position: relative; @@ -696,8 +691,7 @@ &:before { inset-block-start: 50%; - inset-inline-start: 0; - translate: -125% -75%; + translate: 125% -75%; z-index: -1; } } @@ -738,14 +732,53 @@ } } - /* Mobile stuff + /* Mobile columns /* -------------------------------------------------------------------------- */ - .mobile-add-card-container { - padding-inline: 1rem; + .mobile-card-columns { + --column-gap: 8px; + --column-padding-expanded: calc(var(--column-gap) * 2); + --column-width-collapsed: 40px; + --progress-increment: var(--progress-max-width) / var(--progress-max-cards); + --progress-max-cards: 20; + --progress-max-width: 100%; + + padding-inline: 3vw; - @media (min-width: 640px) { + /* Hide on larger devices with cursors */ + @media (min-width: 520px) { display: none; } + + .cards.is-collapsed { + inline-size: auto; + display: block; + padding-block: 0.5ch; + + .cards__expander { + --gradient-direction: to right; + + flex-direction: row; + inline-size: auto; + + &:before { + block-size: 1px; + inline-size: 100%; + inset: 50% 0 auto; + translate: 0 -50%; + } + + &:after { + block-size: var(--column-width-collapsed); + inline-size: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment)); + margin-inline-start: 0; + max-inline-size: var(--progress-max-width); + } + } + + .cards__expander-title { + writing-mode: revert; + } + } } } diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index e9d3bbe513..bd3266ac34 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -21,10 +21,6 @@ <%= hidden_field_tag "board_ids[]", @board.id %> <% end %> -
- <%= render "columns/show/add_card_button", board: @board %> -
- <%= turbo_frame_tag :cards_container do %> <% if @filter.used?(ignore_boards: true) %> <%= render "boards/show/filtered_cards", page: @page %> From 98b47ede6b1db7a9dc87171cac9b58200fa2ec99 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 16:27:06 -0600 Subject: [PATCH 10/23] Center and scroll snap columns on mobile --- app/assets/stylesheets/card-columns.css | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 691284c8cd..1225497a0e 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -31,18 +31,19 @@ position: relative; /* When it has something expanded */ - &:has(.card-columns__left .cards:not(.is-collapsed), .card-columns__right .cards:not(.is-collapsed)) { - grid-template-columns: auto var(--column-width-expanded) auto; + &:has(.card-columns__left .is-expanded, .card-columns__right .is-expanded) { + grid-template-columns: auto auto auto; } &:has(.cards) { min-block-size: 20lh; } - body:not(.public) & { - @media (max-width: 519px) { - display: none; - } + @media (max-width: 639px) { + --column-padding-expanded: 0px; + --column-width-expanded: calc(100vw - var(--column-gap) * 4); + + scroll-snap-type: inline mandatory; } } @@ -74,6 +75,10 @@ position: relative; scroll-snap-align: start; + @media (max-width: 639px) { + scroll-snap-align: center; + } + &.is-collapsed { inline-size: var(--column-width-collapsed); @@ -691,7 +696,8 @@ &:before { inset-block-start: 50%; - translate: 125% -75%; + inset-inline-start: 0; + translate: -125% -75%; z-index: -1; } } From 5d9b2b8663062198c38ff8a5c557feac8f981049 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 12 Dec 2025 16:30:45 -0600 Subject: [PATCH 11/23] Center all columns when collapsed on mobile --- app/assets/stylesheets/card-columns.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 1225497a0e..4ec7668820 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -44,6 +44,10 @@ --column-width-expanded: calc(100vw - var(--column-gap) * 4); scroll-snap-type: inline mandatory; + + &:not(:has(.is-expanded)) { + grid-template-columns: auto var(--column-width-collapsed) auto; + } } } From ffb5474a79a51efe0ad67dbc7c9b1cb6d5a4a66c Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 14:40:28 -0600 Subject: [PATCH 12/23] Equal padding on left mobile columns --- app/assets/stylesheets/card-columns.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 4ec7668820..e67d4d97d3 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -33,6 +33,10 @@ /* When it has something expanded */ &:has(.card-columns__left .is-expanded, .card-columns__right .is-expanded) { grid-template-columns: auto auto auto; + + @media (min-width: 640px) { + grid-template-columns: auto var(--column-width-expanded) auto; + } } &:has(.cards) { @@ -61,6 +65,10 @@ .card-columns__left { justify-content: end; padding-inline-start: var(--column-gap); + + @media (max-width: 639px) { + padding-inline-start: calc(var(--column-gap) * 2); + } } .card-columns__right { From f2591e7da6211002c2df7833899a47af544ecfdd Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 14:56:27 -0600 Subject: [PATCH 13/23] Basic scrolling setup --- app/assets/stylesheets/base.css | 3 ++- app/assets/stylesheets/card-columns.css | 25 +++++++++++++++++++++++++ app/assets/stylesheets/layout.css | 15 ++++++++++----- app/assets/stylesheets/utilities.css | 6 ------ app/views/boards/show.html.erb | 1 + app/views/layouts/application.html.erb | 24 +++++++++++++----------- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/base.css index 05d2b016eb..689b802153 100644 --- a/app/assets/stylesheets/base.css +++ b/app/assets/stylesheets/base.css @@ -102,7 +102,8 @@ } /* Turbo */ - turbo-frame { + turbo-frame, + turbo-cable-stream-source { display: contents; } diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index e67d4d97d3..dabdd69e53 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -1,4 +1,27 @@ @layer components { + /* Layout adjustments for contained scrolling + /* ------------------------------------------------------------------------ */ + + body.contained-scrolling { + block-size: 100dvh; + grid-template-rows: 1fr var(--footer-height); + + #global-container, + #main { + display: grid; + grid-template-rows: auto 1fr; + } + + #global-container { + overflow: hidden; + } + + #main { + overflow: auto; + padding: 0; + } + } + /* Column container /* ------------------------------------------------------------------------ */ @@ -22,6 +45,7 @@ display: grid; gap: var(--column-gap); grid-template-columns: 1fr auto 1fr; + inline-size: 100%; margin-inline: auto; max-inline-size: var(--main-width); outline: none; @@ -88,6 +112,7 @@ scroll-snap-align: start; @media (max-width: 639px) { + overflow-y: auto; scroll-snap-align: center; } diff --git a/app/assets/stylesheets/layout.css b/app/assets/stylesheets/layout.css index e82992dfcc..6ea479eb64 100644 --- a/app/assets/stylesheets/layout.css +++ b/app/assets/stylesheets/layout.css @@ -8,6 +8,16 @@ } } + /* Required for the card column page on mobile, but not needed otherwise */ + :where(#global-container) { + display: contents; + } + + :where(#header) { + position: relative; + z-index: var(--z-nav); + } + :where(#main) { inline-size: 100dvw; margin-inline: auto; @@ -22,11 +32,6 @@ max-inline-size: 100dvw; } - :where(#header) { - position: relative; - z-index: var(--z-nav); - } - :is(#header, #footer) { @media print { display: none; diff --git a/app/assets/stylesheets/utilities.css b/app/assets/stylesheets/utilities.css index 0f487e1f9a..80cbfcdca6 100644 --- a/app/assets/stylesheets/utilities.css +++ b/app/assets/stylesheets/utilities.css @@ -95,12 +95,6 @@ .overflow-clip { text-overflow: clip; white-space: nowrap; overflow: hidden; } .overflow-ellipsis { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } - .overflow-hide-scrollbar::-webkit-scrollbar { - @media (pointer: course) { - display: none; - } - } - .overflow-line-clamp { -webkit-line-clamp: var(--lines, 2); -webkit-box-orient: vertical; diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index bd3266ac34..e1b0a3e960 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -1,4 +1,5 @@ <% @page_title = @board.name %> +<% @body_class = "contained-scrolling" %> <% turbo_exempts_page_from_cache %> <%= turbo_stream_from @board %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6aef1f1bcb..ffc7f271f4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -2,19 +2,21 @@ <%= render "layouts/shared/head" %> - - + +
+ - <%= render "layouts/shared/flash" %> - <%= render "layouts/shared/time_zone" if Current.user %> + <%= render "layouts/shared/flash" %> + <%= render "layouts/shared/time_zone" if Current.user %> -
- <%= yield %> -
+
+ <%= yield %> +
+
<%= yield :footer %> From adceae2e7154e5d9d856e0dc5d8645285fd1ef86 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:13:14 -0600 Subject: [PATCH 14/23] Scrolling in place (borked padding) --- app/assets/stylesheets/card-columns.css | 41 +++++++++++++++---------- app/views/boards/columns/_list.html.erb | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index dabdd69e53..48ce031c0b 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -2,23 +2,26 @@ /* Layout adjustments for contained scrolling /* ------------------------------------------------------------------------ */ - body.contained-scrolling { - block-size: 100dvh; - grid-template-rows: 1fr var(--footer-height); - - #global-container, - #main { - display: grid; - grid-template-rows: auto 1fr; - } + /* Scroll columns individually on mobile */ + @media (max-width: 639px) { + body.contained-scrolling { + block-size: 100dvh; + grid-template-rows: 1fr var(--footer-height); + + #global-container, + #main { + display: grid; + grid-template-rows: auto 1fr; + } - #global-container { - overflow: hidden; - } + #global-container { + overflow: hidden; + } - #main { - overflow: auto; - padding: 0; + #main { + overflow: auto; + padding: 0; + } } } @@ -51,7 +54,6 @@ outline: none; overflow-x: auto; overflow-y: hidden; - padding-block-end: var(--column-width-collapsed); position: relative; /* When it has something expanded */ @@ -77,6 +79,10 @@ grid-template-columns: auto var(--column-width-collapsed) auto; } } + + @media (min-width: 640px) { + padding-block-end: var(--column-width-collapsed); + } } .card-columns__left, @@ -112,6 +118,7 @@ scroll-snap-align: start; @media (max-width: 639px) { + overflow-x: hidden; overflow-y: auto; scroll-snap-align: center; } @@ -198,13 +205,13 @@ /* The wrapper around the cards used to clip overflow while transitioning. * Also, don't resize cards while transitioning to avoid reflow. */ .cards__list { - align-items: flex-end; /* use flex-start to wipe from left */ display: flex; flex-direction: column; gap: var(--cards-gap); margin-block-start: -1ch; margin-inline: -1ch; overflow: hidden; + overflow-y: auto; .cards:not(.is-collapsed) & { padding: 1ch; diff --git a/app/views/boards/columns/_list.html.erb b/app/views/boards/columns/_list.html.erb index 7adedf3223..47b33413d6 100644 --- a/app/views/boards/columns/_list.html.erb +++ b/app/views/boards/columns/_list.html.erb @@ -1,3 +1,3 @@ -
+
<%= render "cards/display/previews", cards: cards, draggable: draggable %>
From 463b99dd7ec5044e3585965ff215a5db2dbae047 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:40:58 -0600 Subject: [PATCH 15/23] Correct padding --- app/assets/stylesheets/card-columns.css | 127 ++++------------------- app/assets/stylesheets/drag_and_drop.css | 4 - 2 files changed, 21 insertions(+), 110 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 48ce031c0b..a07f34346a 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -36,7 +36,7 @@ --bubble-size: 3.5rem; --cards-gap: min(1.2cqi, 1.7rem); --column-gap: 8px; - --column-padding-expanded: calc(var(--column-gap) * 2); + --column-padding: calc(var(--column-gap) * 2); --column-transition-duration: 300ms; --column-width-collapsed: 40px; --column-width-expanded: 450px; @@ -70,7 +70,6 @@ } @media (max-width: 639px) { - --column-padding-expanded: 0px; --column-width-expanded: calc(100vw - var(--column-gap) * 4); scroll-snap-type: inline mandatory; @@ -118,8 +117,7 @@ scroll-snap-align: start; @media (max-width: 639px) { - overflow-x: hidden; - overflow-y: auto; + overflow: hidden; scroll-snap-align: center; } @@ -182,10 +180,6 @@ translate: 0 var(--column-width-collapsed); } - .cards:not(.is-collapsed) & { - padding-inline: var(--column-padding-expanded); - } - .drag-and-drop__hover-container & { --dnd-bg-color: var(--column-color); --dnd-border-color: var(--card-color); @@ -200,6 +194,14 @@ .no-transitions & { transition: none; } + + /* Use flex so the __list container can take up the remaining space for scrolling */ + @media (max-width: 639px) { + .is-expanded & { + display: flex; + flex-direction: column; + } + } } /* The wrapper around the cards used to clip overflow while transitioning. @@ -208,17 +210,16 @@ display: flex; flex-direction: column; gap: var(--cards-gap); - margin-block-start: -1ch; - margin-inline: -1ch; - overflow: hidden; + overflow-x: hidden; overflow-y: auto; - .cards:not(.is-collapsed) & { - padding: 1ch; - } + .is-expanded & { + padding: var(--column-padding); - .card { - inline-size: calc(var(--column-width-expanded) - var(--column-padding-expanded) * 2); + /* Use the rest of the column height for scrolling */ + @media (max-width: 639px) { + flex: 1; + } } .cards--grid & { @@ -294,11 +295,12 @@ block-size: 100%; } - .cards:not(.is-collapsed) & { + .cards.is-expanded & { display: grid; grid-template-areas: "menu expander maximize"; grid-template-columns: var(--column-width-collapsed) 1fr var(--column-width-collapsed); margin-block-end: calc(0.5 * var(--cards-gap)); + padding-inline: var(--column-padding); } } @@ -457,44 +459,6 @@ } } - /* TODO: I think this is legacy now? */ - .cards__heading { - display: flex; - font-size: var(--text-medium); - inset-block-start: 0; - justify-content: center; - margin-block-start: 1px; - margin-inline: -8px; /* enough to cover card shadows, but avoid overlapping bubbles */ - padding-block: var(--cards-gap) 0; - position: sticky; - z-index: 3; - - /* Cover bubbles and cards on small viewports */ - @media (max-width: 639px) { - margin-inline: calc(-1 * var(--cards-gap) - var(--main-padding)); - } - - &, .cards__filter { - font-weight: bold; - text-transform: uppercase; - } - - .cards__filter { - --filter-block-padding: 0.5rem; - - background-color: var(--color-canvas); - border-radius: 99rem; - inline-size: auto; - margin-block: calc(-1 * var(--filter-block-padding)); - padding-block: var(--filter-block-padding); - } - - dialog { - font-weight: normal; - text-transform: none; - } - } - /* Override card styles within columns /* ------------------------------------------------------------------------ */ @@ -629,7 +593,8 @@ --card-padding-block: var(--block-space); border: 1px solid var(--border-color); - margin-block-end: var(--cards-gap); + inline-size: auto; + margin-inline: var(--column-padding); text-align: center; &:has(dialog[open]) { @@ -781,54 +746,4 @@ } } } - - /* Mobile columns - /* -------------------------------------------------------------------------- */ - - .mobile-card-columns { - --column-gap: 8px; - --column-padding-expanded: calc(var(--column-gap) * 2); - --column-width-collapsed: 40px; - --progress-increment: var(--progress-max-width) / var(--progress-max-cards); - --progress-max-cards: 20; - --progress-max-width: 100%; - - padding-inline: 3vw; - - /* Hide on larger devices with cursors */ - @media (min-width: 520px) { - display: none; - } - - .cards.is-collapsed { - inline-size: auto; - display: block; - padding-block: 0.5ch; - - .cards__expander { - --gradient-direction: to right; - - flex-direction: row; - inline-size: auto; - - &:before { - block-size: 1px; - inline-size: 100%; - inset: 50% 0 auto; - translate: 0 -50%; - } - - &:after { - block-size: var(--column-width-collapsed); - inline-size: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment)); - margin-inline-start: 0; - max-inline-size: var(--progress-max-width); - } - } - - .cards__expander-title { - writing-mode: revert; - } - } - } } diff --git a/app/assets/stylesheets/drag_and_drop.css b/app/assets/stylesheets/drag_and_drop.css index 2ada036b4d..03943be14a 100644 --- a/app/assets/stylesheets/drag_and_drop.css +++ b/app/assets/stylesheets/drag_and_drop.css @@ -15,9 +15,5 @@ outline-offset: -2px; transition: background-color 200ms; z-index: 1; - - .cards__heading { - background-color: transparent; - } } } From ea4520575ab9e5fec83daf26d52cde115697fc8f Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:48:40 -0600 Subject: [PATCH 16/23] Hide scrollbars on lists --- app/views/boards/columns/_empty_placeholder.html.erb | 2 +- app/views/boards/columns/_list.html.erb | 2 +- app/views/boards/show/_maybe.html.erb | 2 +- app/views/public/boards/columns/_list.html.erb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/boards/columns/_empty_placeholder.html.erb b/app/views/boards/columns/_empty_placeholder.html.erb index 36507c1ff4..51a5b79e62 100644 --- a/app/views/boards/columns/_empty_placeholder.html.erb +++ b/app/views/boards/columns/_empty_placeholder.html.erb @@ -1,4 +1,4 @@ -
+

Drag cards here

diff --git a/app/views/boards/columns/_list.html.erb b/app/views/boards/columns/_list.html.erb index 47b33413d6..5fda3012df 100644 --- a/app/views/boards/columns/_list.html.erb +++ b/app/views/boards/columns/_list.html.erb @@ -1,3 +1,3 @@ -
+
<%= render "cards/display/previews", cards: cards, draggable: draggable %>
diff --git a/app/views/boards/show/_maybe.html.erb b/app/views/boards/show/_maybe.html.erb index b060c357db..36145faaa0 100644 --- a/app/views/boards/show/_maybe.html.erb +++ b/app/views/boards/show/_maybe.html.erb @@ -13,7 +13,7 @@ <%= render "boards/columns/list", cards: page.records, draggable: true %> <% end %> <% else %> -
+
<% end %> <% end %> diff --git a/app/views/public/boards/columns/_list.html.erb b/app/views/public/boards/columns/_list.html.erb index c733902574..b12af21850 100644 --- a/app/views/public/boards/columns/_list.html.erb +++ b/app/views/public/boards/columns/_list.html.erb @@ -1,3 +1,3 @@ -
+
<%= render "cards/display/public_previews", cards: cards %>
From e24569584d827ac1cf6f065c75ccbe74029748de Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:51:53 -0600 Subject: [PATCH 17/23] Move board-tools inside list --- app/assets/stylesheets/card-columns.css | 1 - app/views/boards/columns/_list.html.erb | 1 + app/views/boards/show/_maybe.html.erb | 5 +++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index a07f34346a..c5b3c3486e 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -594,7 +594,6 @@ border: 1px solid var(--border-color); inline-size: auto; - margin-inline: var(--column-padding); text-align: center; &:has(dialog[open]) { diff --git a/app/views/boards/columns/_list.html.erb b/app/views/boards/columns/_list.html.erb index 5fda3012df..3c7ed50683 100644 --- a/app/views/boards/columns/_list.html.erb +++ b/app/views/boards/columns/_list.html.erb @@ -1,3 +1,4 @@
+ <%= yield %> <%= render "cards/display/previews", cards: cards, draggable: draggable %>
diff --git a/app/views/boards/show/_maybe.html.erb b/app/views/boards/show/_maybe.html.erb index 36145faaa0..552cef52c7 100644 --- a/app/views/boards/show/_maybe.html.erb +++ b/app/views/boards/show/_maybe.html.erb @@ -7,10 +7,11 @@ <%= render "boards/show/expander", title: "Maybe?", count: board.cards.awaiting_triage.count, column_id: "maybe" %> <%= render "boards/show/menu/maximize", column_path: board_columns_stream_path(board) %>
- <%= render "columns/show/add_card_button", board: board %> <% if page.used? %> <%= with_automatic_pagination "maybe", @page do %> - <%= render "boards/columns/list", cards: page.records, draggable: true %> + <%= render "boards/columns/list", cards: page.records, draggable: true do %> + <%= render "columns/show/add_card_button", board: board %> + <% end %> <% end %> <% else %>
From c7ee0ad040338e1fa4d378cee9df48deaf503536 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:53:40 -0600 Subject: [PATCH 18/23] Mini bubble on Maybe column --- app/assets/stylesheets/card-columns.css | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index c5b3c3486e..c4ca41c963 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -116,9 +116,11 @@ position: relative; scroll-snap-align: start; - @media (max-width: 639px) { - overflow: hidden; - scroll-snap-align: center; + &.is-expanded { + @media (max-width: 639px) { + overflow: hidden; + scroll-snap-align: center; + } } &.is-collapsed { @@ -678,6 +680,7 @@ /* Surface a mini bubble if there are cards with bubbles inside */ .cards--maybe:has(.bubble:not([hidden])) .cards__expander-title, + .cards--maybe.is-collapsed:has(.bubble:not([hidden])) .cards__transition-container, .cards--doing.is-collapsed:has(.bubble:not([hidden])) .cards__transition-container { --bubble-color: var(--card-color, oklch(var(--lch-blue-medium))); --bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%; @@ -698,7 +701,7 @@ } /* Maybe column: position bubble relative to the title, not the container */ - .cards--maybe & { + .cards--maybe.is-expanded & { overflow: visible; position: relative; From 0f1ee03edbd297f18680ffd823bd887bd7ded24d Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 15:55:19 -0600 Subject: [PATCH 19/23] Remove vertical offset on mobile --- app/assets/stylesheets/card-columns.css | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index c4ca41c963..f540f3d8eb 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -178,8 +178,10 @@ translate: 0; transition: translate var(--column-transition-duration) var(--ease-out-overshoot-subtle); - .is-collapsed & { - translate: 0 var(--column-width-collapsed); + @media (min-width: 640px) { + .is-collapsed & { + translate: 0 var(--column-width-collapsed); + } } .drag-and-drop__hover-container & { @@ -245,7 +247,9 @@ } .cards__new-column { - margin-block-start: var(--column-width-collapsed); + @media (min-width: 640px) { + margin-block-start: var(--column-width-collapsed); + } } /* Cards grid; used when filtering From a3723ef0d2312b3c9b246d39b48605770f1a4ad1 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 16:03:16 -0600 Subject: [PATCH 20/23] Cleanup and scroll into view when expanding --- app/assets/stylesheets/card-columns.css | 8 ++++---- .../controllers/collapsible_columns_controller.js | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index f540f3d8eb..53257fae11 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -411,7 +411,7 @@ } } - .cards:not(.is-collapsed) & { + .cards.is-expanded & { inline-size: 100%; justify-content: center; } @@ -421,7 +421,7 @@ line-height: var(--column-width-collapsed); inline-size: var(--column-width-collapsed); - .cards:not(.is-collapsed) & { + .cards.is-expanded & { display: none; } } @@ -439,7 +439,7 @@ writing-mode: vertical-rl; } - .cards:not(.is-collapsed) & { + .cards.is-expanded & { align-items: center; display: flex; gap: 0.25ch; @@ -458,7 +458,7 @@ display: none; } - .cards:not(.is-collapsed) .cards__expander:hover & { + .cards.is-expanded .cards__expander:hover & { opacity: 0.66; scale: 1; } diff --git a/app/javascript/controllers/collapsible_columns_controller.js b/app/javascript/controllers/collapsible_columns_controller.js index e9974b0ce3..806e70c760 100644 --- a/app/javascript/controllers/collapsible_columns_controller.js +++ b/app/javascript/controllers/collapsible_columns_controller.js @@ -110,6 +110,10 @@ export default class extends Controller { column.classList.remove(this.collapsedClass) column.classList.add(this.expandedClass) localStorage.setItem(key, true) + + if (window.matchMedia('(max-width: 639px)').matches) { + column.scrollIntoView({ behavior: "smooth", inline: "nearest" }) + } } #buttonFor(column) { From 9504b986ab8c2d305bdf55c3ba2c8f9b3c1e22cf Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 16:07:51 -0600 Subject: [PATCH 21/23] Tighten up column padding on mobile --- app/assets/stylesheets/card-columns.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 53257fae11..0cf8e655a4 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -223,6 +223,7 @@ /* Use the rest of the column height for scrolling */ @media (max-width: 639px) { flex: 1; + padding-inline: calc(var(--column-padding) / 4); } } From 623dd90c66f2fb2f72dcda01dc9b62f457911b2b Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 15 Dec 2025 16:12:07 -0600 Subject: [PATCH 22/23] Looser scroll snap --- app/assets/stylesheets/card-columns.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 0cf8e655a4..e08b5748dc 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -72,7 +72,7 @@ @media (max-width: 639px) { --column-width-expanded: calc(100vw - var(--column-gap) * 4); - scroll-snap-type: inline mandatory; + scroll-snap-type: inline; &:not(:has(.is-expanded)) { grid-template-columns: auto var(--column-width-collapsed) auto; From b7951718f3e88eca79886df384a3265e9f039647 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 19 Dec 2025 15:27:18 -0600 Subject: [PATCH 23/23] Position New Column absolutely to center collapsed columns --- app/assets/stylesheets/card-columns.css | 20 ++++++++++++-------- app/views/boards/show/menu/_columns.html.erb | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index 38f5674444..b0710a81f5 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -72,7 +72,7 @@ @media (max-width: 639px) { --column-width-expanded: calc(100vw - var(--column-gap) * 4); - scroll-snap-type: inline; + scroll-snap-type: inline mandatory; &:not(:has(.is-expanded)) { grid-template-columns: auto var(--column-width-collapsed) auto; @@ -89,10 +89,12 @@ align-items: stretch; display: flex; gap: var(--column-gap); + position: relative; } .card-columns__left { justify-content: end; + margin-inline-start: auto; padding-inline-start: var(--column-gap); @media (max-width: 639px) { @@ -103,6 +105,7 @@ .card-columns__right { justify-content: start; padding-inline-end: var(--column-gap); + margin-inline-end: auto; } /* Column @@ -248,6 +251,14 @@ } .cards__new-column { + position: relative; + + @media (max-width: 639px) { + inset-inline-end: 0; + position: absolute; + translate: 100%; + } + @media (min-width: 640px) { margin-block-start: var(--column-width-collapsed); } @@ -689,13 +700,6 @@ } } - /* Closed (Done) - /* ------------------------------------------------------------------------ */ - - .cards--closed { - - } - /* Doing /* -------------------------------------------------------------------------- */ diff --git a/app/views/boards/show/menu/_columns.html.erb b/app/views/boards/show/menu/_columns.html.erb index 70aac7c902..017527a43c 100644 --- a/app/views/boards/show/menu/_columns.html.erb +++ b/app/views/boards/show/menu/_columns.html.erb @@ -1,4 +1,4 @@ -
+