UI/UX redesign: unified refined-glass design system
Deploy / lint (push) Failing after 10m26s
Deploy / test (push) Has been skipped
Deploy / deploy (push) Has been skipped

- Add shared UI primitives: Button, Field/Input/Select, PageHeader,
  Section, Callout, Tabs, Disclosure
- Replace gradient buttons with single blue-accent btn-primary
- Reserve gradient text for the brand wordmark only
- Rework Scanner page onto the glass system; collapse explainer and
  glossary into a disclosure, move filters into a glass toolbar
- Restructure Ticker Detail into tabs (Analysis / Indicators / S/R)
  with chart and recommendation always visible
- Align Watchlist, Rankings, Admin, Login/Register to shared primitives
- Unify stray indigo/violet/gray accents into the blue family

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 14:52:56 +02:00
parent 79ca19f45f
commit d69df5df27
27 changed files with 405 additions and 275 deletions
@@ -188,7 +188,7 @@ export function JobControls() {
type="button"
onClick={() => triggerJob.mutate(job.name)}
disabled={triggerJob.isPending || !job.enabled || anyJobRunning}
className="btn-gradient px-3 py-1.5 text-xs disabled:opacity-50 disabled:cursor-not-allowed"
className="btn-primary px-3 py-1.5 text-xs disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>
{job.running
@@ -89,7 +89,7 @@ export function RecommendationSettings() {
</div>
<div className="flex items-center gap-2">
<button className="btn-gradient px-4 py-2 text-sm" onClick={onSave} disabled={update.isPending}>
<button className="btn-primary px-4 py-2 text-sm" onClick={onSave} disabled={update.isPending}>
{update.isPending ? 'Saving…' : 'Save Configuration'}
</button>
<button className="px-4 py-2 text-sm rounded border border-white/[0.1] text-gray-300 hover:text-white" onClick={onReset} disabled={update.isPending}>
@@ -43,8 +43,8 @@ export function SettingsForm() {
type="button"
onClick={() => handleToggleRegistration(setting.value)}
disabled={updateSetting.isPending}
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-[#0a0e1a] disabled:opacity-50 ${
setting.value === 'true' ? 'bg-gradient-to-r from-blue-600 to-indigo-600' : 'bg-white/[0.1]'
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-[#0a0e1a] disabled:opacity-50 ${
setting.value === 'true' ? 'bg-gradient-to-r from-blue-600 to-sky-500' : 'bg-white/[0.1]'
}`}
role="switch"
aria-checked={setting.value === 'true'}
@@ -64,7 +64,7 @@ export function SettingsForm() {
<button
onClick={() => handleSave(setting.key)}
disabled={updateSetting.isPending}
className="btn-gradient px-3 py-2 text-xs disabled:opacity-50 disabled:cursor-not-allowed"
className="btn-primary px-3 py-2 text-xs disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>{updateSetting.isPending ? 'Saving…' : 'Save'}</span>
</button>
@@ -36,7 +36,7 @@ export function TickerManagement() {
<button
type="submit"
disabled={addTicker.isPending || !newSymbol.trim()}
className="btn-gradient px-4 py-2.5 text-sm disabled:opacity-50 disabled:cursor-not-allowed"
className="btn-primary px-4 py-2.5 text-sm disabled:opacity-50 disabled:cursor-not-allowed"
>
<span>{addTicker.isPending ? 'Adding…' : 'Add Ticker'}</span>
</button>
@@ -78,7 +78,7 @@ export function TickerUniverseBootstrap() {
<div className="flex flex-wrap gap-2">
<button
className="btn-gradient px-4 py-2 text-sm disabled:opacity-50"
className="btn-primary px-4 py-2 text-sm disabled:opacity-50"
onClick={onSaveDefault}
disabled={isLoading || updateDefault.isPending || bootstrap.isPending}
>
+2 -2
View File
@@ -64,7 +64,7 @@ export function UserTable() {
Access
</label>
<button type="submit" disabled={createUser.isPending || !newUsername.trim() || !newPassword.trim()}
className="btn-gradient px-4 py-2 text-sm disabled:opacity-50 disabled:cursor-not-allowed">
className="btn-primary px-4 py-2 text-sm disabled:opacity-50 disabled:cursor-not-allowed">
<span>{createUser.isPending ? 'Creating…' : 'Create User'}</span>
</button>
</form>
@@ -103,7 +103,7 @@ export function UserTable() {
placeholder="new password" className="w-32 input-glass px-2 py-1 text-xs" />
<button onClick={() => handleResetPassword(user.id)}
disabled={resetPassword.isPending || !resetPw.trim()}
className="btn-gradient px-2 py-1 text-xs disabled:opacity-50">
className="btn-primary px-2 py-1 text-xs disabled:opacity-50">
<span>Save</span>
</button>
<button onClick={() => { setResetTarget(null); setResetPw(''); }}