OS switcher tabs updates (#1002)

* Add OS switcher tabs to WakatimeSetup page

- Add segmented control with macOS/Linux/Codespaces, Windows, and Advanced tabs
- Default tab is auto-detected from user agent (server-side)
- Show WSL option in mac/linux tab label only when user is on Windows
- Use modal-matching cubic-bezier easing for tab transitions

* Add system test for WakatimeSetup OS switcher tabs

* Extract repeated tab classes into tabClass helper

* Remove Xcode reference from setup subtitle

* Show Xcode in subtitle only on macOS/Linux tab

* pf

* Update test/system/wakatime_setup_test.rb

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Mahad Kalam 2026-02-25 10:43:52 +00:00 committed by GitHub
parent 36816f59b3
commit 66f928ca24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 16 deletions

View file

@ -16,6 +16,15 @@
let activeSection = $state(setup_os === "windows" ? "windows" : "mac-linux");
let isWindows = setup_os === "windows";
const tabBase =
"flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)]";
const tabActive = "bg-darkless text-surface-content shadow-sm";
const tabInactive = "text-secondary hover:text-surface-content";
function tabClass(section: string) {
return `${tabBase} ${activeSection === section ? tabActive : tabInactive}`;
}
let hasHeartbeat = $state(false);
let heartbeatTimeAgo = $state("");
let checkCount = $state(0);
@ -33,8 +42,11 @@
];
const sharedTitle = "Configure Hackatime";
const sharedSubtitle =
const macLinuxSubtitle =
"This creates your config file and validates your API key. And if you're using VS Code, a JetBrains IDE, Zed, or Xcode, we'll even set up the plugins for you!";
const windowsSubtitle =
"This creates your config file and validates your API key. And if you're using VS Code, a JetBrains IDE, or Zed, we'll even set up the plugins for you!";
const advancedSubtitle = macLinuxSubtitle;
function showSuccess(timeAgo: string) {
hasHeartbeat = true;
@ -123,28 +135,19 @@
<div class="flex gap-1 p-1 bg-darker border border-darkless rounded-xl">
<button
class="flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] {activeSection ===
'mac-linux'
? 'bg-darkless text-surface-content shadow-sm'
: 'text-secondary hover:text-surface-content'}"
class={tabClass("mac-linux")}
onclick={() => (activeSection = "mac-linux")}
>
macOS / Linux{isWindows ? " / WSL" : ""} / Codespaces
</button>
<button
class="flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] {activeSection ===
'windows'
? 'bg-darkless text-surface-content shadow-sm'
: 'text-secondary hover:text-surface-content'}"
class={tabClass("windows")}
onclick={() => (activeSection = "windows")}
>
Windows
</button>
<button
class="flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] {activeSection ===
'advanced'
? 'bg-darkless text-surface-content shadow-sm'
: 'text-secondary hover:text-surface-content'}"
class={tabClass("advanced")}
onclick={() => (activeSection = "advanced")}
>
Advanced
@ -155,7 +158,7 @@
<div class="bg-dark border border-darkless rounded-xl p-8 shadow-sm">
<div class="mb-6">
<h3 class="text-xl font-semibold mb-2">{sharedTitle}</h3>
<p class="text-secondary text-sm">{sharedSubtitle}</p>
<p class="text-secondary text-sm">{macLinuxSubtitle}</p>
</div>
<div
@ -267,7 +270,7 @@
<div class="bg-dark border border-darkless rounded-xl p-8 shadow-sm">
<div class="mb-6">
<h3 class="text-xl font-semibold mb-2">{sharedTitle}</h3>
<p class="text-secondary text-sm">{sharedSubtitle}</p>
<p class="text-secondary text-sm">{windowsSubtitle}</p>
</div>
<div class="space-y-4">
@ -355,7 +358,7 @@
<div class="bg-dark border border-darkless rounded-xl p-8 shadow-sm">
<div class="mb-6">
<h3 class="text-xl font-semibold mb-2">{sharedTitle}</h3>
<p class="text-secondary text-sm">{sharedSubtitle}</p>
<p class="text-secondary text-sm">{advancedSubtitle}</p>
</div>
<div class="bg-purple/10 border border-purple/20 rounded-lg p-4 mb-4">

View file

@ -0,0 +1,30 @@
require "application_system_test_case"
class WakatimeSetupTest < ApplicationSystemTestCase
setup do
@user = User.create!(timezone: "UTC")
sign_in_as(@user)
end
test "shows OS switcher tabs and can switch between them" do
visit my_wakatime_setup_path
# Default tab should be macOS / Linux / Codespaces (non-Windows user agent)
assert_text "Configure Hackatime"
assert_text "curl -fsSL"
# Switch to Windows tab
click_on "Windows"
assert_text "Open PowerShell"
assert_text "install.ps1"
# Switch to Advanced tab
click_on "Advanced"
assert_text "~/.wakatime.cfg"
assert_text "api_url"
# Switch back to macOS / Linux tab
click_on "macOS / Linux / Codespaces"
assert_text "curl -fsSL"
end
end