Files
sure/app/views/settings/ai_prompts/show.html.erb
Guillem Arias Fauste 83cb287294 chore(design-system): swap raw gray classes for semantic tokens in settings/ (#1652)
* chore(design-system): swap raw gray classes for semantic tokens in settings/

Pilot for the broader raw-color sweep. Maps 21 occurrences across 11
files to design-system equivalents:

- text-white bg-gray-900 hover:bg-gray-800 (CTA buttons)
  -> text-inverse button-bg-primary hover:button-bg-primary-hover
- bg-gray-25 / bg-gray-50 / bg-gray-100 (subtle surface backgrounds)
  -> bg-surface-inset
- bg-gray-800 (tooltip pills) -> bg-inverse
- text-white inside tooltips -> text-inverse
- text-gray-300 (muted tooltip labels) -> text-inverse opacity-70
- text-gray-600 (muted body text) -> text-secondary
- hover:text-gray-700 -> hover:text-primary
- focus:ring-gray-900 -> focus:ring-button-bg-primary

The 7 status-indicator dots (`bg-gray-400`) are intentionally left
as raw classes. Gray-400 against both light and dark container bgs
gives reasonable contrast either way, and there's no semantic token
that fits a "neutral inactive indicator" use case yet. Worth a
follow-up if a `bg-subdued` token would benefit other places.

* fix(design-system): use theme-aware focus ring on provider submit buttons

Two issues caught in code review:

1. focus:ring-button-bg-primary silently emits no CSS (CodeRabbit, Codex).
   button-bg-primary is a custom @utility, not a theme color, so Tailwind's
   ring-{name} resolution finds no --color-button-bg-primary and falls
   back to the default. Replaces with focus:ring-gray-900
   theme-dark:focus:ring-white — same color flip as the button bg, but
   resolved through theme colors so ring-{name} actually generates CSS.

2. _enable_banking_panel.html.erb dropped focus-ring + transition entirely
   in the original sweep (CodeRabbit). Restores parity with the other
   provider panels using the corrected ring classes.

Long-term cleanup: tracked under issue #1653 (modifier-aware utilities)
to make button-bg-primary also a theme color so ring-button-bg-primary
becomes valid.
2026-05-04 21:42:44 +02:00

109 lines
5.0 KiB
Plaintext

<%= content_for :page_title, t(".page_title") %>
<% if Current.user.ai_enabled? %>
<div class="mb-4 flex justify-end">
<%= render DS::Button.new(
text: t(".disable_ai"),
href: user_path(Current.user),
method: :patch,
params: { user: { ai_enabled: false, redirect_to: "ai_prompts" } },
data: { turbo: false },
variant: :destructive
) %>
</div>
<% end %>
<div class="bg-container rounded-xl shadow-border-xs p-4">
<div class="rounded-xl bg-container-inset space-y-1 p-1">
<div class="flex items-center gap-1.5 px-4 py-2 text-xs font-medium text-secondary">
<p><%= t(".openai_label") %></p>
</div>
<div class="bg-container rounded-lg shadow-border-xs">
<div class="space-y-4 p-4">
<!-- Main System Prompt Section -->
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-full bg-surface-inset flex justify-center items-center">
<%= icon "message-circle" %>
</div>
<div>
<p class="text-sm font-medium text-primary"><%= t(".main_system_prompt.title") %></p>
<p class="text-xs text-secondary"><%= t(".main_system_prompt.subtitle") %></p>
</div>
</div>
<div class="pl-12 space-y-2">
<details class="group">
<summary class="flex items-center gap-2 cursor-pointer">
<span class="text-xs font-medium text-primary uppercase"><%= t(".prompt_instructions") %></span>
<%= icon "chevron-right", class: "group-open:transform group-open:rotate-90" %>
</summary>
<pre class="whitespace-pre-wrap text-xs font-mono text-primary">[<%= Provider::Openai::DEFAULT_MODEL %>]</pre>
<div class="mt-2 px-3 py-2 bg-surface-default border border-primary rounded-lg">
<pre class="whitespace-pre-wrap text-xs font-mono text-primary"><%= @assistant_config[:instructions] %></pre>
</div>
</details>
</div>
</div>
<div class="border-t border-primary"></div>
<!-- Auto-Categorization Section -->
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-full bg-surface-inset flex justify-center items-center">
<%= icon "brain" %>
</div>
<div>
<p class="text-sm font-medium text-primary"><%= t(".transaction_categorizer.title") %></p>
<p class="text-xs text-secondary"><%= t(".transaction_categorizer.subtitle") %></p>
</div>
</div>
<div class="pl-12 space-y-2">
<details class="group">
<summary class="flex items-center gap-2 cursor-pointer">
<span class="text-xs font-medium text-primary uppercase"><%= t(".prompt_instructions") %></span>
<%= icon "chevron-right", class: "group-open:transform group-open:rotate-90" %>
</summary>
<pre class="whitespace-pre-wrap text-xs font-mono text-primary">[<%= Provider::Openai::DEFAULT_MODEL %>]</pre>
<div class="mt-2 px-3 py-2 bg-surface-default border border-primary rounded-lg">
<pre class="whitespace-pre-wrap text-xs font-mono text-primary"><%= @assistant_config[:auto_categorizer]&.instructions || Provider::Openai::AutoCategorizer.new(nil).instructions %></pre>
</div>
</details>
</div>
</div>
<div class="border-t border-primary"></div>
<!-- Merchant Detection Section -->
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-full bg-surface-inset flex justify-center items-center">
<%= icon "store" %>
</div>
<div>
<p class="text-sm font-medium text-primary"><%= t(".merchant_detector.title") %></p>
<p class="text-xs text-secondary"><%= t(".merchant_detector.subtitle") %></p>
</div>
</div>
<div class="pl-12 space-y-2">
<details class="group">
<summary class="flex items-center gap-2 cursor-pointer">
<span class="text-xs font-medium text-primary uppercase"><%= t(".prompt_instructions") %></span>
<%= icon "chevron-right", class: "group-open:transform group-open:rotate-90" %>
</summary>
<pre class="whitespace-pre-wrap text-xs font-mono text-primary">[<%= Provider::Openai::DEFAULT_MODEL %>]</pre>
<div class="mt-2 px-3 py-2 bg-surface-default border border-primary rounded-lg">
<pre class="whitespace-pre-wrap text-xs font-mono text-primary"><%= @assistant_config[:auto_merchant]&.instructions || Provider::Openai::AutoMerchantDetector.new(nil, model: "", transactions: [], user_merchants: []).instructions %></pre>
</div>
</details>
</div>
</div>
</div>
</div>
</div>
</div>