Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
b84da94
Add Hotwire Native Bridge wiring.
svara Jan 6, 2026
177afe1
Add bridge page controller and helpers.
svara Jan 6, 2026
ecf0921
Add bridge page targets.
svara Jan 6, 2026
37f0a2c
Add hotwire-native-bridge vendor js.
svara Jan 6, 2026
2d7b76f
Fix bridge viewport safe-area insets.
svara Jan 6, 2026
367a7ab
Use raw page_title in bridge page title attribute
svara Jan 6, 2026
69c17a7
Add bridge insets controller.
svara Jan 7, 2026
cdc4f2c
Wire bridge insets controller into the layout.
svara Jan 7, 2026
367edfc
Add bridge nav-button controller.
svara Jan 7, 2026
c61942d
Add bridge form controller.
svara Jan 7, 2026
4cbc2c6
Hide bridged submit button when native form component is active.
svara Jan 7, 2026
58664f8
Add `bridged_form_with` helper for bridge form controller.
svara Jan 7, 2026
de10717
Use `bridged_form_with` for board creation form.
svara Jan 7, 2026
ce0538d
Move bridge insets controller to bridge/controllers.
svara Jan 7, 2026
75431e0
Hide bridged nav-button elements when native nav component is active.
svara Jan 7, 2026
dc9c544
Use bridge nav-button for board settings action.
svara Jan 7, 2026
76eaf32
Add bridge buttons controller.
svara Jan 7, 2026
9331c37
Remove bridge nav-button controller.
svara Jan 7, 2026
e2f9989
Remove form related events from bridge page controller.
svara Jan 8, 2026
b8bb4cf
Remove option to toggle header visibility from mobile apps in bridge …
svara Jan 8, 2026
37f03fc
Use bridge buttons controller in boards.
svara Jan 8, 2026
0a57e39
Remove redundant url from bridge page change payload.
svara Jan 8, 2026
d38c0c9
Add bridge overflow menu controller.
svara Jan 8, 2026
1a46ed3
Hide bridged overflow-menu elements when native is active.
svara Jan 8, 2026
674509b
Update overflow menu controller to send an array of menu items.
svara Jan 8, 2026
eae17b8
Merge branch 'main' into mobile/bridge-components
Jan 8, 2026
3a43941
Move bridge javascript into existing folder structure
adjogima Jan 8, 2026
45f24d9
Move bridge buttons controller to <body>
adjogima Jan 8, 2026
1028eab
Remove useless shouldLoad
adjogima Jan 8, 2026
0d21efc
Use hidden overflow menu container for board bridge items.
svara Jan 8, 2026
3746774
Remove bridge button metadata from board settings link.
svara Jan 8, 2026
228f65d
Remove change event from bridge page controller.
svara Jan 8, 2026
70853ef
Drop label from bridge button.
svara Jan 8, 2026
e286539
Drop name from bridge icon.
svara Jan 8, 2026
8f07ad6
Explicitly send submit button data in bridge form controller.
svara Jan 8, 2026
33fa3a9
Remove unused BridgeElement extensions.
svara Jan 8, 2026
24e4335
Remove the <summary> distinction
adjogima Jan 8, 2026
c5bd48a
Remove wrapping div in board header
adjogima Jan 8, 2026
f848a49
Use already existing buttons to populate the top nav bar
adjogima Jan 8, 2026
4a798b7
Add bridge overflow menu controller to <body>
adjogima Jan 8, 2026
ff7162c
Fix overflow-menu css scope
jayohms Jan 8, 2026
19d16e6
Cleanup bridge components
jayohms Jan 8, 2026
e35d3c8
Break up excessively long lines with bridge attributes
jayohms Jan 8, 2026
ac45da2
Merge branch 'main' into mobile/bridge-components
jayohms Jan 8, 2026
b6aac0b
Introduce a bridge helper to get icon asset urls
jayohms Jan 8, 2026
b9dcc3c
Update bridged overflow menu items for settings links
jayohms Jan 8, 2026
2b0c4b4
Send icon urls with buttons and resolve duplicate bridge items on the…
jayohms Jan 9, 2026
8cff72e
Hook up the "Create card" button as a bridge form target
jayohms Jan 9, 2026
2e55f67
Extract filtering for enabled targets so that the index of the target…
jayohms Jan 9, 2026
9ac34f8
Only apply the "Don't/Watch this" bridge target for the text variant …
jayohms Jan 9, 2026
b074a11
Update the card perma to support bridge buttonsa and the edit form state
jayohms Jan 9, 2026
cf3efce
Move the rest of the visible card perma buttons to the overflow menu
jayohms Jan 9, 2026
d5fef48
Merge branch 'main' into mobile/bridge-components
jayohms Jan 9, 2026
05c0cbb
Prevent autofocusing the filter input in drop downs
adjogima Jan 12, 2026
caafebb
Extract title to helper
adjogima Jan 12, 2026
43314f7
Move the bridge form controller to the outer container so a cancel ta…
jayohms Jan 12, 2026
bd8feea
Fix the form submit css scope
jayohms Jan 12, 2026
82d4fa5
Tweak card footer on perma
adjogima Jan 12, 2026
3d09258
Move dialog focus handling to a stimulus controller
adjogima Jan 12, 2026
6fab121
Merge branch 'main' into mobile/bridge-components
adjogima Jan 12, 2026
450f57e
Fix missing underline on card closure message button
adjogima Jan 12, 2026
4f7cec3
Rename bride page controller to title controller and remove text size…
svara Jan 13, 2026
68d1966
Add bridge text size controller.
svara Jan 13, 2026
e5c7965
Fix bottom notch in new card form
adjogima Jan 13, 2026
9dc5151
Set footer height
adjogima Jan 13, 2026
8894382
Save a bit of space in "watch" card
adjogima Jan 13, 2026
3b97b2e
Merge branch 'main' into mobile/bridge-components
adjogima Jan 14, 2026
3cada3c
Merge branch 'main' into mobile/bridge-components
jayohms Jan 14, 2026
600ee87
Merge branch 'main' into mobile/bridge-components
jayohms Jan 16, 2026
44732a3
Move dialog focus handling into the dialog controller
adjogima Jan 19, 2026
5113961
Setup proper focus handling for mobile on the card perma's board picker
adjogima Jan 19, 2026
e87dc10
Setup focus handling on touch target's connect callback
adjogima Jan 19, 2026
b5985ef
Use private functions for bridge components
jayohms Jan 19, 2026
e9ebf8e
Fix bad formatting on bridge page title attr
adjogima Jan 19, 2026
a9b873f
Merge branch 'main' into mobile/bridge-components
jayohms Jan 19, 2026
cc4e19b
Remove reference to removed controller
jayohms Jan 19, 2026
1083784
Update `turbo-rails` to get latest Turbo version
rosa Jan 19, 2026
967f76d
Fix notification broadcast test for turbo-rails 2.0.21
rosa Jan 19, 2026
80e0a03
Merge pull request #2399 from basecamp/update-turbo
rosa Jan 19, 2026
fa4e77f
Prevent page scrolling when modal dialog is open
nqst Jan 19, 2026
cd6478d
Merge branch 'main' into mobile/bridge-components
jayohms Jan 19, 2026
3fa850d
Merge pull request #2307 from basecamp/mobile/bridge-components
jayohms Jan 19, 2026
772b378
Merge branch 'main' into modal-scroll-block
nqst Jan 19, 2026
aea90f4
Add viewport padding to dialogs on mobile
nqst Jan 20, 2026
aba88cd
Use CSS variable for panel size in delete dialogs
nqst Jan 20, 2026
bfea02e
Actually make it affect larger screens too
nqst Jan 20, 2026
73cf1de
Use inline spacing variable
nqst Jan 20, 2026
468fe5f
Only index up to 32KB of search content
kevinmcconnell Jan 21, 2026
74aca08
Merge pull request #2406 from basecamp/search-content-limit
kevinmcconnell Jan 21, 2026
72123dc
Merge pull request #2404 from nqst/dialog-viewport-spacing
andyra Jan 21, 2026
783faf3
Make the CLAUDE.md stub less obtrusive
jeremy Jan 21, 2026
9b1dd0b
Merge pull request #2401 from nqst/modal-scroll-block
andyra Jan 21, 2026
eccef3b
Only submit on blur if the input has a value
andyra Jan 21, 2026
6c8d333
Bump card perma z-index when dialog is open
andyra Jan 21, 2026
5b94248
Merge pull request #2409 from basecamp/improve-filter-settings-ux
andyra Jan 21, 2026
f9f638a
Return to Board page when clearing filters
andyra Jan 21, 2026
49f45b6
Merge pull request #2410 from basecamp/handle-single-board-filters
andyra Jan 21, 2026
2299ba4
OAuth 2.1 support
jeremy Jan 5, 2026
403205d
OAuth discovery and dynamic client registration
jeremy Jan 5, 2026
abbf7bb
Connected Apps UI for OAuth grant management
jeremy Jan 5, 2026
08c5d78
Fizzy CLI foundation
jeremy Jan 13, 2026
1312985
Config command for settings management
jeremy Jan 13, 2026
3f71fd2
Query commands for boards, cards, and users
jeremy Jan 13, 2026
3eddbd1
Card action commands
jeremy Jan 13, 2026
94662e6
Name resolution for fuzzy matching
jeremy Jan 13, 2026
c4fac75
Fix OAuth callback SIGPIPE and public client token exchange
jeremy Jan 13, 2026
d7a5b17
--in alias for --board flag
jeremy Jan 13, 2026
a9ba66f
README and tab completion
jeremy Jan 13, 2026
3c6adf2
Multi-origin credential storage and install script
jeremy Jan 13, 2026
ff16900
CSP validation for OAuth redirect_uri
jeremy Jan 13, 2026
0e7b781
Fix API response handling for RESTful patterns
jeremy Jan 13, 2026
6e06c9d
Pagination support for cards command
jeremy Jan 13, 2026
ac4a15f
Fix installer symlink path
jeremy Jan 13, 2026
9a25656
Fix name resolution: tag .title field, pagination, regex safety
jeremy Jan 13, 2026
b36abfc
Fix card create to chain follow-up actions
jeremy Jan 13, 2026
08522fa
Store account_slug per-origin in credentials
jeremy Jan 13, 2026
c96923f
Add --page flag to query commands
jeremy Jan 13, 2026
2792c91
Add pagination fallback + remove Python dependency
jeremy Jan 13, 2026
3e44c05
Fix completions and add postponing_soon status
jeremy Jan 13, 2026
c4d4b7b
Update README for global flags and local dev default
jeremy Jan 13, 2026
fc9b402
Add --all flag for auto-pagination to list commands
jeremy Jan 13, 2026
b29f886
Add card update command
jeremy Jan 13, 2026
76e7745
Add comment edit/delete as subcommands
jeremy Jan 13, 2026
098bf66
Document env var auth path in help and status
jeremy Jan 13, 2026
a0a84af
Add card delete command
jeremy Jan 13, 2026
41bc591
Add card image delete command
jeremy Jan 13, 2026
8f2a56a
Fix API request/response handling
jeremy Jan 13, 2026
ec28c1e
Add steps and reactions parity
jeremy Jan 13, 2026
752b748
Add identity, users, and image upload support
jeremy Jan 14, 2026
6891939
Add JSON responders for webhooks controller
jeremy Jan 14, 2026
0e669f0
Add JSON responders for pins, involvements, publications
jeremy Jan 14, 2026
07b5d75
Add JSON responders for account, board, column, and role endpoints
jeremy Jan 14, 2026
8e02cbf
Update API docs for fidelity with controllers
jeremy Jan 14, 2026
2813500
Add CLI parity matrix
jeremy Jan 14, 2026
0bc7971
Add webhook CLI commands
jeremy Jan 14, 2026
a047efe
Add account CLI commands
jeremy Jan 14, 2026
f69ff6e
Add self-update command and version tracking
jeremy Jan 14, 2026
d65f73c
Add board publish, unpublish, and entropy commands
jeremy Jan 14, 2026
fd2b67a
Add user role command
jeremy Jan 14, 2026
1d8d599
Add card publish and move commands
jeremy Jan 14, 2026
fe48ea2
Update help and API client for new commands
jeremy Jan 14, 2026
04e7999
Update CLI plan with complete command reference
jeremy Jan 14, 2026
e71ea1f
Fix self-update: EXIT_API_ERROR → EXIT_API, add safety guards
jeremy Jan 14, 2026
49aab3f
Switch to commit-hash versioning and add uninstall command
jeremy Jan 14, 2026
7b3195f
Harden install and self-update against edge cases
jeremy Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@../AGENTS.md
1 change: 0 additions & 1 deletion CLAUDE.md

This file was deleted.

2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ GEM
timeout (0.6.0)
trilogy (2.9.0)
tsort (0.2.0)
turbo-rails (2.0.20)
turbo-rails (2.0.21)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6)
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.saas.lock
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ GEM
timeout (0.6.0)
trilogy (2.9.0)
tsort (0.2.0)
turbo-rails (2.0.20)
turbo-rails (2.0.21)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6)
Expand Down
33 changes: 19 additions & 14 deletions app/assets/stylesheets/card-perma.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
position: relative;

&:has(dialog[open]) {
z-index: 2;
z-index: 3;
}

&:has(.card-perma__star-input:checked) {
Expand Down Expand Up @@ -281,10 +281,7 @@

/* Overlap the card BG by half the button height */
&:has(.btn) {
&,
~ .card-perma__closure-message {
translate: 0 calc(-1 * var(--half-btn-height));
}
translate: 0 calc(-1 * var(--half-btn-height));
}

form {
Expand All @@ -297,12 +294,6 @@
--btn-color: var(--color-ink-inverted);
}

.btn--plain {
--btn-color: var(--card-color);

text-decoration: underline;
}

.btn--reversed {
--btn-background: var(--color-canvas);
--btn-color: var(--card-color);
Expand Down Expand Up @@ -330,11 +321,25 @@
.card-perma__closure-message {
color: var(--card-color);
grid-area: closure-message;
margin-block-start: 0.5ch;
margin-block: var(--block-space) var(--block-space-double);
padding-inline: 1ch;

form {
display: inline;
.btn--plain {
--btn-color: var(--card-color);

text-decoration: underline;
}

@media (max-width: 799px) {
margin-block: var(--block-space-half);
translate: 0 calc(-0.5 * var(--half-btn-height));
}

@media (min-width: 800px) {
.card-perma__notch--bottom:has(.btn) ~ & {
margin-block: var(--block-space-half) var(--block-space);
translate: 0 calc(-0.5 * var(--half-btn-height));
}
}
}
}
10 changes: 10 additions & 0 deletions app/assets/stylesheets/dialog.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
@layer components {
/* Prevent page scrolling when modal dialog is open */
html:has(dialog:modal) {
overflow: hidden;
}

:is(.dialog) {
border: 0;
opacity: 0;
Expand Down Expand Up @@ -35,4 +40,9 @@
}
}
}

/* Ensure padding from viewport edges */
.dialog.panel {
max-inline-size: calc(100vw - var(--inline-space-double) * 2);
}
}
40 changes: 40 additions & 0 deletions app/assets/stylesheets/native.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
--custom-safe-inset-bottom: var(--injected-safe-inset-bottom, env(safe-area-inset-bottom, 0px));
--custom-safe-inset-left: var(--injected-safe-inset-left, env(safe-area-inset-left, 0px));

--footer-height: 0;

-webkit-tap-highlight-color: transparent;

.hide-on-native {
Expand All @@ -28,11 +30,27 @@
}
}

/* Card columns
/* ------------------------------------------------------------------------ */

.board-tools.card {
padding-block-start: 0;
}

/* Card perma
/* ------------------------------------------------------------------------ */

.card-perma {
margin-block-start: 0;

&:not(:has(.card-perma__notch-new-card-buttons)) .card-perma__bg {
padding-block: clamp(0.25rem, 2vw, var(--padding-block));
}
}

.card-perma__closure-message {
margin-block: var(--block-space);
translate: unset;
}

/* Search
Expand All @@ -43,3 +61,25 @@
}
}
}

[data-bridge-components~=form] {
[data-controller~=bridge--form] {
[data-bridge--form-target~=submit] {
display: none;
}
}
}

[data-bridge-components~=overflow-menu] {
[data-controller~=bridge--overflow-menu] {
[data-bridge--overflow-menu-target~=item] {
display: none;
}
}
}

[data-bridge-components~=buttons] {
[data-bridge--buttons-target~=button] {
display: none;
}
}
4 changes: 4 additions & 0 deletions app/assets/stylesheets/popup.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
.popup__title {
font-weight: 800;
white-space: nowrap;

&[tabindex="-1"]:focus-visible {
outline: unset;
}
}

/* Hide lists when all the items within are hidden */
Expand Down
5 changes: 4 additions & 1 deletion app/controllers/account/entropies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ class Account::EntropiesController < ApplicationController

def update
Current.account.entropy.update!(entropy_params)
redirect_to account_settings_path, notice: "Account updated"
respond_to do |format|
format.html { redirect_to account_settings_path, notice: "Account updated" }
format.json { head :no_content }
end
end

private
Expand Down
18 changes: 16 additions & 2 deletions app/controllers/account/exports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@ class Account::ExportsController < ApplicationController
CURRENT_EXPORT_LIMIT = 10

def show
respond_to do |format|
format.html
format.json do
if @export
render json: @export.as_json(only: %i[id status created_at])
else
head :not_found
end
end
end
end

def create
Current.account.exports.create!(user: Current.user).build_later
redirect_to account_settings_path, notice: "Export started. You'll receive an email when it's ready."
export = Current.account.exports.create!(user: Current.user)
export.build_later
respond_to do |format|
format.html { redirect_to account_settings_path, notice: "Export started. You'll receive an email when it's ready." }
format.json { render json: export.as_json(only: %i[id status created_at]), status: :accepted }
end
end

private
Expand Down
19 changes: 16 additions & 3 deletions app/controllers/account/join_codes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@ class Account::JoinCodesController < ApplicationController
before_action :ensure_admin, only: %i[ update destroy ]

def show
respond_to do |format|
format.html
format.json { render json: @join_code.as_json(only: %i[code usage_limit usage_count]) }
end
end

def edit
end

def update
if @join_code.update(join_code_params)
redirect_to account_join_code_path
respond_to do |format|
format.html { redirect_to account_join_code_path }
format.json { head :no_content }
end
else
render :edit, status: :unprocessable_entity
respond_to do |format|
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: { errors: @join_code.errors }, status: :unprocessable_entity }
end
end
end

def destroy
@join_code.reset
redirect_to account_join_code_path
respond_to do |format|
format.html { redirect_to account_join_code_path }
format.json { render json: @join_code.as_json(only: %i[code usage_limit usage_count]) }
end
end

private
Expand Down
9 changes: 8 additions & 1 deletion app/controllers/account/settings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ class Account::SettingsController < ApplicationController

def show
@users = @account.users.active.alphabetically.includes(:identity)
respond_to do |format|
format.html
format.json { render json: @account.as_json(only: %i[id name]) }
end
end

def update
@account.update!(account_params)
redirect_to account_settings_path
respond_to do |format|
format.html { redirect_to account_settings_path }
format.json { head :no_content }
end
end

private
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/boards/entropies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ class Boards::EntropiesController < ApplicationController

def update
@board.update!(entropy_params)
respond_to do |format|
format.html
format.turbo_stream
format.json { head :no_content }
end
end

private
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/boards/involvements_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@ class Boards::InvolvementsController < ApplicationController

def update
@board.access_for(Current.user).update!(involvement: params[:involvement])
respond_to do |format|
format.html
format.turbo_stream
format.json { head :no_content }
end
end
end
10 changes: 10 additions & 0 deletions app/controllers/boards/publications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ class Boards::PublicationsController < ApplicationController

def create
@board.publish
respond_to do |format|
format.html
format.turbo_stream
format.json { render json: { key: @board.publication.key, url: published_board_url(@board) } }
end
end

def destroy
@board.unpublish
@board.reload
respond_to do |format|
format.html
format.turbo_stream
format.json { head :no_content }
end
end
end
18 changes: 14 additions & 4 deletions app/controllers/cards/pins_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ def show
def create
@pin = @card.pin_by Current.user

broadcast_add_pin_to_tray
render_pin_button_replacement
respond_to do |format|
format.html do
broadcast_add_pin_to_tray
render_pin_button_replacement
end
format.json { head :no_content }
end
end

def destroy
@pin = @card.unpin_by Current.user

broadcast_remove_pin_from_tray
render_pin_button_replacement
respond_to do |format|
format.html do
broadcast_remove_pin_from_tray
render_pin_button_replacement
end
format.json { head :no_content }
end
end

private
Expand Down
15 changes: 10 additions & 5 deletions app/controllers/cards/publishes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ class Cards::PublishesController < ApplicationController
def create
@card.publish

if add_another_param?
card = @board.cards.create!(status: :drafted)
redirect_to card_draft_path(card), notice: "Card added"
else
redirect_to @card.board
respond_to do |format|
format.html do
if add_another_param?
card = @board.cards.create!(status: :drafted)
redirect_to card_draft_path(card), notice: "Card added"
else
redirect_to @card.board
end
end
format.json { head :no_content }
end
end

Expand Down
5 changes: 5 additions & 0 deletions app/controllers/columns/left_positions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ class Columns::LeftPositionsController < ApplicationController
def create
@left_column = @column.left_column
@column.move_left
respond_to do |format|
format.html
format.turbo_stream
format.json { head :no_content }
end
end
end
5 changes: 5 additions & 0 deletions app/controllers/columns/right_positions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ class Columns::RightPositionsController < ApplicationController
def create
@right_column = @column.right_column
@column.move_right
respond_to do |format|
format.html
format.turbo_stream
format.json { head :no_content }
end
end
end
Loading