Skip to content

fix: replace contrast buttons with primary style#23753

Merged
TirmanSidhu merged 1 commit into
mainfrom
tirmansidhu/remove-contrast-buttons
Apr 6, 2026
Merged

fix: replace contrast buttons with primary style#23753
TirmanSidhu merged 1 commit into
mainfrom
tirmansidhu/remove-contrast-buttons

Conversation

@TirmanSidhu
Copy link
Copy Markdown
Contributor

@TirmanSidhu TirmanSidhu commented Apr 6, 2026

Summary

  • Replace all .contrast button usages with .primary in ComposerView (macOS) and InputBarView (iOS)
  • Remove contrast from gallery demos
  • Fixes white-on-white button visibility issue in chat composer

Test plan

  • Stop generation button in composer uses primary style
  • Voice mode mute button uses primary style
  • No white-on-white buttons visible in chat

🤖 Generated with Claude Code


Open with Devin

Remove all production usages of .contrast button style in favor of .primary.
Fixes white-on-white button visibility issues in chat composer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@TirmanSidhu TirmanSidhu merged commit f3a38d9 into main Apr 6, 2026
@TirmanSidhu TirmanSidhu deleted the tirmansidhu/remove-contrast-buttons branch April 6, 2026 14:55
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c7e2cdb19

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

label: manager.state == .listening ? "Mute" : "Unmute",
iconOnly: manager.state == .listening ? VIcon.mic.rawValue : VIcon.micOff.rawValue,
style: .contrast,
style: .primary,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use contrasting style for voice mute button

Switching the voice-mode mute/unmute control to .primary makes it visually blend into the voice composer container in dark appearance: voiceConversationComposer uses VColor.contentEmphasized as its background, and VButton.Style.primary resolves to the same dark-mode token value (#FDFDFC) in ColorTokens.swift, so the button fill disappears and the control loses affordance. This regression is specific to voice mode and dark appearance, and the previous .contrast style at least preserved separation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

VCard {
HStack(spacing: VSpacing.xl) {
ForEach([VButton.Style.primary, .outlined, .danger, .dangerOutline, .ghost, .contrast], id: \.self) { style in
ForEach([VButton.Style.primary, .outlined, .danger, .dangerOutline, .ghost], id: \.self) { style in
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Dead .contrast style enum case and handling code not removed per AGENTS.md dead code rule

After this PR removes all consumer usages of VButton.Style.contrast, the .contrast enum case (clients/shared/DesignSystem/Core/Buttons/VButton.swift:4) and all its handling code in VButton.swift (lines 110, 230-234, 245) and VSplitButton.swift (lines 138-141, 158, 174-175, 182) become dead code with zero callers. The root AGENTS.md requires: "Proactively remove unused code during every change. Remove code your change makes unused." The gallery's styleName helper at clients/shared/DesignSystem/Gallery/Sections/ButtonsGallerySection.swift:321 and the component description at clients/shared/DesignSystem/Gallery/ComponentGalleryView.swift:55 (which still lists "contrast" as a style) should also be cleaned up.

Prompt for agents
The PR removes all consumer usages of VButton.Style.contrast but leaves the enum case and all its handling code in the design system. Per AGENTS.md dead code removal rule, the following should be cleaned up:

1. Remove `contrast` from the `Style` enum in clients/shared/DesignSystem/Core/Buttons/VButton.swift:4
2. Remove the `.contrast` cases from switch statements in VButton.swift (lines 110, 230-234, 245)
3. Remove the `.contrast` cases from switch statements in VSplitButton.swift (lines 138-141, 158, 174-175, 182)
4. Remove the `.contrast` case from the `styleName` function in ButtonsGallerySection.swift:321
5. Update the description string in ComponentGalleryView.swift:55 to remove mention of "contrast" from the style list
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

label: manager.state == .listening ? "Mute" : "Unmute",
iconOnly: manager.state == .listening ? VIcon.mic.rawValue : VIcon.micOff.rawValue,
style: .contrast,
style: .primary,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Visual behavior change for voice conversation mute/unmute button

The mute/unmute button in the voice conversation composer (ComposerView.swift:615) sits inside a container with a VColor.contentEmphasized background (line 637). The old .contrast style used VColor.contentDefault as the button background — a neutral dark color designed to stand out against dark surfaces. The new .primary style uses VColor.primaryBase (the brand accent color). While this is an intentional design change, reviewers should verify the visual contrast is sufficient on the dark voice-conversation bar, especially in both light and dark modes.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

noanflaherty pushed a commit that referenced this pull request Apr 6, 2026
Remove all production usages of .contrast button style in favor of .primary.
Fixes white-on-white button visibility issues in chat composer.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
noanflaherty added a commit that referenced this pull request Apr 6, 2026
* Increase teleport import timeout from 2 to 5 minutes (#23749)

* increase teleport import timeout from 2 to 5 minutes

* fix: update platform import timeout error message to say 5 minutes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Update billing tab copy: referral subtitle, remove earning cap note, move credit info to card subtitle (#23751)

* fix(macos): always collapse thinking blocks by default (#23750)

Thinking blocks were auto-expanding during streaming, showing a wall of
text. Remove the auto-expand logic so blocks always start collapsed.
Users can still manually expand them. The header already shows
"Thinking..." vs "Thought process" as a streaming indicator.

Closes LUM-729

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>

* [LUM-684/LUM-726] Fix dictation crash: pass nil format to installTap (#23754)

* Fix dictation crash: pass nil format to installTap, consolidate audio engine calls

Pass nil for the format parameter in AVAudioNode.installTap(onBus:bufferSize:format:block:)
so AVAudioEngine uses its own internal hardware format, which is always self-consistent.
This prevents NSInternalInconsistencyException crashes caused by format.sampleRate != hwFormat.sampleRate
when the cached format from outputFormat(forBus:) diverges from the engine's internal hardware
format after audio route changes (Bluetooth, USB mic, AirPods mode switch).

AudioEngineController.swift:
- installTapAndStart() now passes nil instead of explicit format to installTap
- Removed 6 now-unused methods: inputNodeFormat(), installTap(bufferSize:format:block:),
  removeTap(), prepare(), start(), prepareAndStart()

OpenAIVoiceService.swift:
- startRecording(): replaced separate inputNodeFormat/installTap/prepare/start chain
  with single installTapAndStart() call
- startBargeInMonitor(): same migration to installTapAndStart()
- Removed error-path removeTap() call (handled internally by installTapAndStart)

Resolves: LUM-684, LUM-726
Co-Authored-By: tkheyfets <timur@vellum.ai>

* fix: use explicit block: parameter in guard statements for installTapAndStart

Swift doesn't support trailing closure syntax with guard statements,
causing compilation errors. Use explicit block: parameter label instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace contrast buttons with primary style (#23753)

Remove all production usages of .contrast button style in favor of .primary.
Fixes white-on-white button visibility issues in chat composer.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Inject host environment via transport hints (#23779)

* refactor: discriminated union for transport metadata, remove iOS proxy setup (#23776)

* feat: inject interface ID and macOS host environment into transport hints (#23777)

* feat: send hostHomeDir and hostUsername from macOS client (#23778)

* fix: remove iOS from proxy restoration in conversation-process.ts (#23782)

---------

Co-authored-by: Carson Shaar <carson.s.shaar@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Tirman Sidhu <tirmansidhu@gmail.com>
dvargasfuertes pushed a commit that referenced this pull request Apr 6, 2026
* Increase teleport import timeout from 2 to 5 minutes (#23749)

* increase teleport import timeout from 2 to 5 minutes

* fix: update platform import timeout error message to say 5 minutes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Update billing tab copy: referral subtitle, remove earning cap note, move credit info to card subtitle (#23751)

* fix(macos): always collapse thinking blocks by default (#23750)

Thinking blocks were auto-expanding during streaming, showing a wall of
text. Remove the auto-expand logic so blocks always start collapsed.
Users can still manually expand them. The header already shows
"Thinking..." vs "Thought process" as a streaming indicator.

Closes LUM-729

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>

* [LUM-684/LUM-726] Fix dictation crash: pass nil format to installTap (#23754)

* Fix dictation crash: pass nil format to installTap, consolidate audio engine calls

Pass nil for the format parameter in AVAudioNode.installTap(onBus:bufferSize:format:block:)
so AVAudioEngine uses its own internal hardware format, which is always self-consistent.
This prevents NSInternalInconsistencyException crashes caused by format.sampleRate != hwFormat.sampleRate
when the cached format from outputFormat(forBus:) diverges from the engine's internal hardware
format after audio route changes (Bluetooth, USB mic, AirPods mode switch).

AudioEngineController.swift:
- installTapAndStart() now passes nil instead of explicit format to installTap
- Removed 6 now-unused methods: inputNodeFormat(), installTap(bufferSize:format:block:),
  removeTap(), prepare(), start(), prepareAndStart()

OpenAIVoiceService.swift:
- startRecording(): replaced separate inputNodeFormat/installTap/prepare/start chain
  with single installTapAndStart() call
- startBargeInMonitor(): same migration to installTapAndStart()
- Removed error-path removeTap() call (handled internally by installTapAndStart)

Resolves: LUM-684, LUM-726
Co-Authored-By: tkheyfets <timur@vellum.ai>

* fix: use explicit block: parameter in guard statements for installTapAndStart

Swift doesn't support trailing closure syntax with guard statements,
causing compilation errors. Use explicit block: parameter label instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace contrast buttons with primary style (#23753)

Remove all production usages of .contrast button style in favor of .primary.
Fixes white-on-white button visibility issues in chat composer.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Inject host environment via transport hints (#23779)

* refactor: discriminated union for transport metadata, remove iOS proxy setup (#23776)

* feat: inject interface ID and macOS host environment into transport hints (#23777)

* feat: send hostHomeDir and hostUsername from macOS client (#23778)

* fix: remove iOS from proxy restoration in conversation-process.ts (#23782)

---------

Co-authored-by: Carson Shaar <carson.s.shaar@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Tirman Sidhu <tirmansidhu@gmail.com>
dvargasfuertes pushed a commit that referenced this pull request Apr 6, 2026
* Release v0.6.1

* Cherry-pick fixes for v0.6.1 (#23785)

* Increase teleport import timeout from 2 to 5 minutes (#23749)

* increase teleport import timeout from 2 to 5 minutes

* fix: update platform import timeout error message to say 5 minutes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Update billing tab copy: referral subtitle, remove earning cap note, move credit info to card subtitle (#23751)

* fix(macos): always collapse thinking blocks by default (#23750)

Thinking blocks were auto-expanding during streaming, showing a wall of
text. Remove the auto-expand logic so blocks always start collapsed.
Users can still manually expand them. The header already shows
"Thinking..." vs "Thought process" as a streaming indicator.

Closes LUM-729

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>

* [LUM-684/LUM-726] Fix dictation crash: pass nil format to installTap (#23754)

* Fix dictation crash: pass nil format to installTap, consolidate audio engine calls

Pass nil for the format parameter in AVAudioNode.installTap(onBus:bufferSize:format:block:)
so AVAudioEngine uses its own internal hardware format, which is always self-consistent.
This prevents NSInternalInconsistencyException crashes caused by format.sampleRate != hwFormat.sampleRate
when the cached format from outputFormat(forBus:) diverges from the engine's internal hardware
format after audio route changes (Bluetooth, USB mic, AirPods mode switch).

AudioEngineController.swift:
- installTapAndStart() now passes nil instead of explicit format to installTap
- Removed 6 now-unused methods: inputNodeFormat(), installTap(bufferSize:format:block:),
  removeTap(), prepare(), start(), prepareAndStart()

OpenAIVoiceService.swift:
- startRecording(): replaced separate inputNodeFormat/installTap/prepare/start chain
  with single installTapAndStart() call
- startBargeInMonitor(): same migration to installTapAndStart()
- Removed error-path removeTap() call (handled internally by installTapAndStart)

Resolves: LUM-684, LUM-726
Co-Authored-By: tkheyfets <timur@vellum.ai>

* fix: use explicit block: parameter in guard statements for installTapAndStart

Swift doesn't support trailing closure syntax with guard statements,
causing compilation errors. Use explicit block: parameter label instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace contrast buttons with primary style (#23753)

Remove all production usages of .contrast button style in favor of .primary.
Fixes white-on-white button visibility issues in chat composer.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Inject host environment via transport hints (#23779)

* refactor: discriminated union for transport metadata, remove iOS proxy setup (#23776)

* feat: inject interface ID and macOS host environment into transport hints (#23777)

* feat: send hostHomeDir and hostUsername from macOS client (#23778)

* fix: remove iOS from proxy restoration in conversation-process.ts (#23782)

---------

Co-authored-by: Carson Shaar <carson.s.shaar@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Tirman Sidhu <tirmansidhu@gmail.com>

* [skip ci] Cherry-pick fixes for v0.6.1 (#23820)

* revert: disable Teleport feature flag by default (#23744) (#23815)

* fix: replace auxWhite-on-primaryBase with VButton across the app (#23802)

* fix: use VButton for inline surface action buttons

Replace raw Button with manual color functions in InlineSurfaceRouter
with the design system VButton component. The manual buttonForeground
used VColor.auxWhite (always #FFFFFF) against VColor.primaryBase which
resolves to #FDFDFC in dark mode, producing invisible white-on-white
text.

Closes LUM-730

Co-Authored-By: ashlee@vellum.ai <ashlee@vellum.ai>

* fix: replace auxWhite-on-primaryBase with VButton in additional locations

FileUploadSurfaceView: Upload/Cancel buttons used raw Button with
VColor.auxWhite on VColor.primaryBase — white-on-white in dark mode.
Replaced with VButton(.primary) and VButton(.outlined).

JITPermissionView: Permission buttons used the same auxWhite pattern.
Replaced with VButton(.primary/.outlined, isFullWidth: true).

ImproveExperienceStepView: ToS checkbox checkmark used auxWhite on
primaryBase fill. Changed to VColor.contentInset which adapts per
color scheme.

ChatGallerySection: Gallery demo of surface action pills mirrored
the old buggy pattern. Updated to use VButton so the gallery
accurately represents production rendering.

Co-Authored-By: ashlee@vellum.ai <ashlee@vellum.ai>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>

* Make dictation engine start non-blocking with audio route resilience (#23811)

* Make dictation engine start non-blocking and improve audio resilience

- Add installTapAndStartAsync to AudioEngineController for non-blocking
  engine start using Swift concurrency (withCheckedContinuation)
- Extract installTapAndStartImpl to share logic between sync/async paths
- Listen for AVAudioEngineConfigurationChange to re-prewarm inputNode
  after Bluetooth device connect/disconnect and AirPods mode switches
- Restructure VoiceInputManager.beginRecording() to show recording UI
  and play activation chime immediately, then start engine async via Task
- Move DictationContextCapture off the critical path: engine starts
  concurrently on its audio queue while context capture runs on main
- Add SFSpeechRecognizer transient unavailability retry (recreate if
  isAvailable returns false after sleep/wake or heavy use)
- Handle edge case where PTT is released before async engine start
  completes (stopRecordingForDictation cleans up directly)

Co-Authored-By: tkheyfets <timur@vellum.ai>

* Tear down engine when async startup outlives recording session

When PTT is released before installTapAndStartAsync completes, the
isRecording guard now stops and removes the tap if the engine started
successfully, preventing the mic path from staying alive with no
active recording session.

Co-Authored-By: tkheyfets <timur@vellum.ai>

* Add recording generation token and gate context capture on start success

Co-Authored-By: tkheyfets <timur@vellum.ai>

* Guard stale teardown against active sessions and gate rewarm on mic auth

Co-Authored-By: tkheyfets <timur@vellum.ai>

* Move context capture to Task.detached to avoid blocking main actor

Co-Authored-By: tkheyfets <timur@vellum.ai>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: tkheyfets <timur@vellum.ai>

* [LUM-681] Fix audio tap format mismatch by resetting engine before installTap (#23766)

After audio-route changes (Bluetooth, USB mic, AirPods mode switch), the
format cached inside AVAudioInputNode diverges from the engine's actual
hardware format. Both outputFormat(forBus:) and a nil format argument to
installTap resolve to this stale value, causing:

  'Failed to create tap due to format mismatch,
   <AVAudioFormat: 2 ch, 44100 Hz, Float32, deinterleaved>'

Fix: call audioEngine.reset() before re-querying the format, then pass it
explicitly to installTap. This forces the engine to discard its cached graph
state and re-read the hardware, so the tap, node, and engine all agree.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: tkheyfets <timur@vellum.ai>

* fix: pass transport hints through HTTP message endpoint for managed-mode conversations (#23824)

* fix: pass transport metadata through POST /v1/messages to enable host environment hints

The HTTP message handler auto-creates conversations without transport
metadata, so applyTransportMetadata() returns early and host environment
hints (hostHomeDir, hostUsername) are never injected into the LLM context.
This causes the assistant to hallucinate the user's home directory path
from their display name instead of using the actual macOS username.

Thread transport metadata from the message request body through
SendMessageDeps.getOrCreateConversation() to the daemon, and send
hostHomeDir/hostUsername from the macOS client in every message request.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: replace dynamic imports with static type imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: reset non-version-bump files to match main

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Noa Flaherty <noa@vellum.ai>
Co-authored-by: Carson Shaar <carson.s.shaar@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ashlee@vellum.ai <ashlee@vellum.ai>
Co-authored-by: tkheyfets <timur@vellum.ai>
Co-authored-by: Tirman Sidhu <tirmansidhu@gmail.com>
Co-authored-by: David Vargas Fuertes <vargasvellum@Davids-MacBook-Pro.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant