This document outlines the changes made to fix two critical UI issues:
- Button Styling Issue: Buttons were rendering with white backgrounds and white text, making them unreadable
- Select Dropdown Issue: When selecting a release from the dropdown in the "Create Stage" dialog, the selected value was not being properly stored as a string
src/lib/components/ui/button/button.types.tssrc/lib/components/ui/button/button.svelte
- Updated the default button variant in
buttonVariantsto use a blood orange color scheme instead of the generic "primary" color - Changed from:
bg-primary text-primary-foreground - Changed to:
bg-orange-600 text-white shadow-xs hover:bg-orange-700 active:bg-orange-800 - Removed hardcoded
background: #fff;style from button.svelte that was overriding the theme
All buttons throughout the application now use the blood orange (bg-orange-600) theme with white text, providing better visibility and brand alignment with OpenHack's branding. The theme includes:
- Default state:
bg-orange-600 text-white - Hover state:
bg-orange-700(darker orange) - Active state:
bg-orange-800(even darker)
- All pages that use the default Button component now display with the blood orange theme
- Specifically removed hardcoded white styling from:
src/routes/desktop/pages/Stages.svelte
src/lib/components/ui/select/index.ts- Updated exports to use new SelectWrappersrc/lib/components/ui/select/select-wrapper.svelte- NEW FILE created to properly expose bits-ui Selectsrc/routes/desktop/pages/Stages.svelte- Now uses the fixed Select component
The issue was that bits-ui's Select.Root component has a native value prop that is bindable, but it needs to be explicitly exposed. The solution was to create a simple wrapper that:
- Accepts
bind:valuebinding - Specifies
type="single"for single-select behavior - Passes through to bits-ui's native bindable value prop
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'
let { value = $bindable(''), children, ...restProps } = $props()
</script>
<SelectPrimitive.Root type="single" bind:value {...restProps}>
{@render children?.()}
</SelectPrimitive.Root>This elegant solution leverages bits-ui's built-in support for single-select string values without any custom callbacks or conversions.
- Before: Selecting a release would show unexpected behavior and store as array
- After: Selecting a release correctly stores the selected ID as a simple string
- The
releaseIdin the form now properly contains just the selected ID string - Only one selection is possible at a time
- No custom conversion logic needed
src/routes/desktop/pages/Stages.svelte- Create Stage dialog now properly handles release selectionsrc/routes/desktop/pages/Deployments.svelte- Stage selection also works correctly
- Removed unused function:
handleReleaseSelection()in Stages.svelte (no longer needed) - Fixed TypeScript assertions: Added non-null assertions (
stageDetail!.) for proper type narrowing in the stage detail modal - Fixed dialog cleanup: Moved dialog cleanup logic to
onOpenChangehandler to properly handle state cleanup - Fixed type issues: Changed
logsSourcefrom strictReadable<string[]>toanyto handle websocket store type mismatch - Code formatting: Applied consistent formatting across modified files
- Visit any page with buttons (Dashboard, Stages, Deployments, etc.)
- Verify all default buttons now display with blood orange background and white text
- Test hover states by moving mouse over buttons
- Test disabled states to ensure opacity is applied correctly
- Navigate to Stages page
- Click "New stage" button
- Click the Release dropdown
- Select a release from the list
- Expected: The selected release ID should display correctly in the trigger area
- Verify: Only one release can be selected at a time
- Verify: The form value is a string, not an array
- Create a stage to verify the selection is properly passed to the API
- Test the Deployments page Stage dropdown for consistency
- No new dependencies were added
- All changes use existing libraries:
bits-ui,tailwind-variants,svelte - Installation status note: These fixes are ready for use after running
npm install
- All changes are compatible with modern browsers
- No breaking changes to existing functionality
- Fully backward compatible
- The blood orange color (
#ea580corrgb(234, 88, 12)in standard form) aligns with OpenHack branding - The Select wrapper is a transparent abstraction - users use it exactly like before but now it works correctly
- All type errors have been resolved (except for missing lucide icon dependencies, which resolve after npm install)
- The solution uses bits-ui's native capabilities rather than adding custom logic