Skip to content

Commit

Permalink
Add turbo: true as an option for ToggleSwitch (#2964)
Browse files Browse the repository at this point in the history
  • Loading branch information
klaustopher authored Jul 26, 2024
1 parent 9b675a7 commit 91f5a57
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changeset/hip-glasses-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@primer/view-components": minor
---

Add `turbo: true` as an parameter for the `ToggleSwitch` component and treat the respoonse (when it has the correct MIME type) as a [Turbo Stream](https://turbo.hotwired.dev/handbook/streams). The new `turbo` paramater defaults to false
and with that the HTTP response is simply ignored as is the current behavior.
6 changes: 4 additions & 2 deletions app/components/primer/alpha/toggle_switch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ class ToggleSwitch < Primer::Component
# @param enabled [Boolean] Whether or not the toggle switch responds to user input.
# @param size [Symbol] What size toggle switch to render. <%= one_of(Primer::Alpha::ToggleSwitch::SIZE_OPTIONS) %>
# @param status_label_position [Symbol] Which side of the toggle switch to render the status label. <%= one_of(Primer::Alpha::ToggleSwitch::STATUS_LABEL_POSITION_OPTIONS) %>
# @param turbo [Boolean] Whether or not to request a turbo stream and render the response as such.
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
def initialize(src: nil, csrf_token: nil, checked: false, enabled: true, size: SIZE_DEFAULT, status_label_position: STATUS_LABEL_POSITION_DEFAULT, **system_arguments)
def initialize(src: nil, csrf_token: nil, checked: false, enabled: true, size: SIZE_DEFAULT, status_label_position: STATUS_LABEL_POSITION_DEFAULT, turbo: false, **system_arguments)
@src = src
@csrf_token = csrf_token
@checked = checked
@enabled = enabled
@turbo = turbo
@system_arguments = system_arguments

@size = fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)
Expand Down Expand Up @@ -82,7 +84,7 @@ def before_render

@system_arguments[:data] = merge_data(
@system_arguments,
{ data: { csrf: @csrf_token } }
{ data: { csrf: @csrf_token, turbo: @turbo } }
)
end
end
Expand Down
23 changes: 19 additions & 4 deletions app/components/primer/alpha/toggle_switch.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {controller, target} from '@github/catalyst'
import {controller, target, attr} from '@github/catalyst'

@controller
class ToggleSwitchElement extends HTMLElement {
@target switch: HTMLElement
@target loadingSpinner: HTMLElement
@target errorIcon: HTMLElement
@attr turbo = false

private toggling = false

Expand Down Expand Up @@ -158,13 +159,19 @@ class ToggleSwitchElement extends HTMLElement {

let response

const requestHeaders: {[key: string]: string} = {
'Requested-With': 'XMLHttpRequest',
}

if (this.turbo) {
requestHeaders['Accept'] = 'text/vnd.turbo-stream.html'
}

try {
response = await fetch(this.src, {
credentials: 'same-origin',
method: 'POST',
headers: {
'Requested-With': 'XMLHttpRequest',
},
headers: requestHeaders,
body,
})
} catch (error) {
Expand All @@ -174,12 +181,20 @@ class ToggleSwitchElement extends HTMLElement {
if (!response.ok) {
throw new Error(await response.text())
}

const contentType = response.headers.get('Content-Type')
if (window.Turbo && this.turbo && contentType?.startsWith('text/vnd.turbo-stream.html')) {
window.Turbo.renderStreamMessage(await response.text())
}
}
}

declare global {
interface Window {
ToggleSwitchElement: typeof ToggleSwitchElement
Turbo: {
renderStreamMessage: (message: string) => void
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions previews/primer/alpha/toggle_switch_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def with_csrf_token
def with_bad_csrf_token
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.toggle_switch_index_path, csrf_token: "i_am_a_criminal"))
end

def with_turbo
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.toggle_switch_index_path, turbo: true))
end
end
end
end
6 changes: 6 additions & 0 deletions test/components/alpha/toggle_switch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ def test_csrf_token

assert_selector("[data-csrf]")
end

def test_turbo
render_inline(Primer::Alpha::ToggleSwitch.new(src: "/foo", turbo: true))

assert_selector("[data-turbo]")
end
end
end
end
14 changes: 14 additions & 0 deletions test/system/alpha/toggle_switch_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ def test_fetch_made_with_correct_headers
assert_equal "XMLHttpRequest", ToggleSwitchController.last_request.headers["HTTP_REQUESTED_WITH"]
end

def test_fetch_made_with_turbo
visit_preview(:with_turbo)

refute_selector(".ToggleSwitch--checked")
find("toggle-switch").click
assert_selector(".ToggleSwitch--checked")

wait_for_request

assert_equal "text/vnd.turbo-stream.html", ToggleSwitchController.last_request.headers["HTTP_ACCEPT"]
end



private

def wait_for_spinner
Expand Down

0 comments on commit 91f5a57

Please sign in to comment.