mirror of
https://github.com/we-promise/sure.git
synced 2026-05-09 21:54:58 +00:00
refactor(design-system): migrate fg-* utilities to text-* and remove namespace
The design system carried two parallel namespaces for foreground colors: text-* (canonical, ~2,000 uses) and fg-* (32 uses). Most fg-* tokens were 1:1 duplicates of a text-* counterpart. fg-gray was nearly identical to text-secondary, with a one-step shade difference in dark mode. This PR migrates all 32 usages to their text-* equivalents and removes the fg-* block from the design tokens. Closes #1606. Mapping: - fg-inverse -> text-inverse (20 usages, identical light/dark values) - fg-gray -> text-secondary (7 usages; light values match, dark is one step lighter: gray-300 vs gray-400) - fg-primary -> text-primary (3 usages, identical values) - fg-subdued -> text-subdued (2 usages, identical values) The four other fg-* tokens (fg-contrast, fg-primary-variant, fg-secondary, fg-secondary-variant) had zero usages despite being defined; they are removed without replacement. JSON / build: - design/tokens/sure.tokens.json: $version 1.0.0 -> 2.0.0 (breaking schema change per the policy added in #1620). 8 fg-* token definitions removed. - button-bg-ghost-hover's dark value still references "fg-inverse" internally; rewritten to "bg-gray-800 text-inverse" so the cleanup doesn't break that utility. - _generated.css regenerated. 42 utility blocks now (was 50). Lookbook tokens preview: - The Text & foregrounds section dropped its split between text-* (canonical) and fg-* (legacy). Now a single section listing the five text-* utilities. The "(legacy)" framing is gone since there's no legacy left. README: - design/tokens/README.md's button-bg-ghost-hover edge-case example updated to reflect the new "bg-gray-800 text-inverse" dark value. Visual review needed in dark mode: - Anywhere icons use the application_helper#icon helper with color: "default" (most icons in the app). The default class moved from fg-gray (gray-400 dark) to text-secondary (gray-300 dark), so default-color icons render slightly lighter in dark mode. - DS::Buttonish icons in secondary buttons (same shade shift). - DS::Link icons (same). - Time series chart axes (same). - All tooltips, account add flow, settings hostings buttons, invitations, AI consent, family export, danger-zone buttons -- these used fg-inverse, which is identical to text-inverse, so no visual change expected.
This commit is contained in:
@@ -302,70 +302,6 @@
|
||||
@apply bg-surface-inset animate-pulse;
|
||||
}
|
||||
|
||||
@utility fg-gray {
|
||||
@apply text-gray-500;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-contrast {
|
||||
@apply text-gray-400;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-500;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-inverse {
|
||||
@apply text-white;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-primary {
|
||||
@apply text-gray-900;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-primary-variant {
|
||||
@apply text-gray-800;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-50;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-secondary {
|
||||
@apply text-gray-50;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-secondary-variant {
|
||||
@apply text-gray-100;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-500;
|
||||
}
|
||||
}
|
||||
|
||||
@utility fg-subdued {
|
||||
@apply text-gray-400;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply text-gray-500;
|
||||
}
|
||||
}
|
||||
|
||||
@utility text-primary {
|
||||
@apply text-gray-900;
|
||||
|
||||
@@ -558,7 +494,7 @@
|
||||
@apply bg-gray-50;
|
||||
|
||||
@variant theme-dark {
|
||||
@apply bg-gray-800 fg-inverse;
|
||||
@apply bg-gray-800 text-inverse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ class DS::Buttonish < DesignSystemComponent
|
||||
VARIANTS = {
|
||||
primary: {
|
||||
container_classes: "text-inverse bg-inverse hover:bg-inverse-hover disabled:bg-gray-500 theme-dark:disabled:bg-gray-400",
|
||||
icon_classes: "fg-inverse"
|
||||
icon_classes: "text-inverse"
|
||||
},
|
||||
secondary: {
|
||||
container_classes: "text-primary bg-gray-200 theme-dark:bg-gray-700 hover:bg-gray-300 theme-dark:hover:bg-gray-600 disabled:bg-gray-200 theme-dark:disabled:bg-gray-600",
|
||||
icon_classes: "fg-primary"
|
||||
icon_classes: "text-primary"
|
||||
},
|
||||
destructive: {
|
||||
container_classes: "text-inverse bg-red-500 theme-dark:bg-red-400 hover:bg-red-600 theme-dark:hover:bg-red-500 disabled:bg-red-200 theme-dark:disabled:bg-red-600",
|
||||
@@ -14,23 +14,23 @@ class DS::Buttonish < DesignSystemComponent
|
||||
},
|
||||
outline: {
|
||||
container_classes: "text-primary border border-secondary bg-transparent hover:bg-surface-hover",
|
||||
icon_classes: "fg-gray"
|
||||
icon_classes: "text-secondary"
|
||||
},
|
||||
outline_destructive: {
|
||||
container_classes: "text-destructive border border-secondary bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
icon_classes: "fg-gray"
|
||||
icon_classes: "text-secondary"
|
||||
},
|
||||
ghost: {
|
||||
container_classes: "text-primary bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
icon_classes: "fg-gray"
|
||||
icon_classes: "text-secondary"
|
||||
},
|
||||
icon: {
|
||||
container_classes: "hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
icon_classes: "fg-gray"
|
||||
icon_classes: "text-secondary"
|
||||
},
|
||||
icon_inverse: {
|
||||
container_classes: "bg-inverse hover:bg-inverse-hover",
|
||||
icon_classes: "fg-inverse"
|
||||
icon_classes: "text-inverse"
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class DS::Link < DS::Buttonish
|
||||
VARIANTS = VARIANTS.reverse_merge(
|
||||
default: {
|
||||
container_classes: "",
|
||||
icon_classes: "fg-gray"
|
||||
icon_classes: "text-secondary"
|
||||
}
|
||||
).freeze
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<%= helpers.icon icon_name, size: size, color: color %>
|
||||
|
||||
<div role="tooltip" data-DS--tooltip-target="tooltip" class="hidden absolute z-50 bg-gray-700 text-sm px-1.5 py-1 rounded-md">
|
||||
<div class="fg-inverse font-normal max-w-[200px]">
|
||||
<div class="text-inverse font-normal max-w-[200px]">
|
||||
<%= tooltip_content %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ module ApplicationHelper
|
||||
def icon(key, size: "md", color: "default", custom: false, as_button: false, **opts)
|
||||
extra_classes = opts.delete(:class)
|
||||
sizes = { xs: "w-3 h-3", sm: "w-4 h-4", md: "w-5 h-5", lg: "w-6 h-6", xl: "w-7 h-7", "2xl": "w-8 h-8" }
|
||||
colors = { default: "fg-gray", white: "fg-inverse", success: "text-success", warning: "text-warning", destructive: "text-destructive", current: "text-current" }
|
||||
colors = { default: "text-secondary", white: "text-inverse", success: "text-success", warning: "text-warning", destructive: "text-destructive", current: "text-current" }
|
||||
|
||||
icon_classes = class_names(
|
||||
"shrink-0",
|
||||
|
||||
@@ -110,7 +110,7 @@ export default class extends Controller {
|
||||
.attr("cx", this._d3InitialContainerWidth / 2)
|
||||
.attr("cy", this._d3InitialContainerHeight / 2)
|
||||
.attr("r", 4)
|
||||
.attr("class", "fg-subdued")
|
||||
.attr("class", "text-subdued")
|
||||
.style("fill", "currentColor");
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ export default class extends Controller {
|
||||
// Style ticks
|
||||
this._d3Group
|
||||
.selectAll(".tick text")
|
||||
.attr("class", "fg-gray")
|
||||
.attr("class", "text-secondary")
|
||||
.style("font-size", "12px")
|
||||
.style("font-weight", "500")
|
||||
.attr("text-anchor", "middle")
|
||||
@@ -334,7 +334,7 @@ export default class extends Controller {
|
||||
// Guideline
|
||||
this._d3Group
|
||||
.append("line")
|
||||
.attr("class", "guideline fg-subdued")
|
||||
.attr("class", "guideline text-subdued")
|
||||
.attr("x1", this._d3XScale(d.date))
|
||||
.attr("y1", 0)
|
||||
.attr("x2", this._d3XScale(d.date))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%# locals: (accountable:) %>
|
||||
|
||||
<%= link_to new_polymorphic_path(accountable, step: "method_select", return_to: params[:return_to]),
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover text-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<%= render DS::FilledIcon.new(
|
||||
icon: accountable.icon,
|
||||
hex_color: accountable.color,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<% unless params[:return_to].present? %>
|
||||
<%= button_to imports_path(import: { type: "AccountImport" }),
|
||||
data: { turbo_frame: :_top },
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover text-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<%= render DS::FilledIcon.new(
|
||||
icon: "download",
|
||||
hex_color: "#F79009",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<%= form_with url: user_path(Current.user), method: :patch, class: "w-full", data: { turbo: false } do |form| %>
|
||||
<%= form.hidden_field "user[ai_enabled]", value: true %>
|
||||
<%= form.hidden_field "user[redirect_to]", value: "home" %>
|
||||
<%= form.submit "Enable AI Chats", class: "cursor-pointer hover:bg-inverse-hover w-full py-2 px-4 bg-inverse fg-inverse rounded-lg text-sm font-medium" %>
|
||||
<%= form.submit "Enable AI Chats", class: "cursor-pointer hover:bg-inverse-hover w-full py-2 px-4 bg-inverse text-inverse rounded-lg text-sm font-medium" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<%= form_with url: family_exports_path, method: :post, class: "space-y-4" do |form| %>
|
||||
<div class="flex gap-3">
|
||||
<%= link_to "Cancel", "#", class: "flex-1 text-center px-4 py-2 text-primary bg-surface border border-primary rounded-lg hover:bg-surface-hover", data: { action: "click->modal#close" } %>
|
||||
<%= form.submit "Export data", class: "flex-1 bg-inverse fg-inverse rounded-lg px-4 py-2 cursor-pointer hover:bg-inverse-hover" %>
|
||||
<%= form.submit "Export data", class: "flex-1 bg-inverse text-inverse rounded-lg px-4 py-2 cursor-pointer hover:bg-inverse-hover" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<%= tag.span t(".missing_data"), class: "font-normal text-xs" %>
|
||||
</div>
|
||||
<div role="tooltip" data-tooltip-target="tooltip" class="tooltip bg-gray-700 text-sm p-2 rounded w-64">
|
||||
<div class="fg-inverse">
|
||||
<div class="text-inverse">
|
||||
<%= t(".description") %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
<div data-controller="tooltip" data-tooltip-placement-value="right" data-tooltip-offset-value=10 data-tooltip-cross-axis-value=50>
|
||||
<%= icon("info", size: "sm") %>
|
||||
<div role="tooltip" data-tooltip-target="tooltip" class="tooltip bg-gray-700 text-sm p-2 rounded w-64">
|
||||
<div class="fg-inverse">
|
||||
<div class="text-inverse">
|
||||
<%= t(".total_value_tooltip") %>
|
||||
</div>
|
||||
<div class="flex pt-3">
|
||||
<div class="text-gray-300">
|
||||
<%= t(".cash") %>
|
||||
</div>
|
||||
<div class="fg-inverse ml-auto">
|
||||
<div class="text-inverse ml-auto">
|
||||
<%= tag.p format_money(cash, precision: 0) %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="text-gray-300">
|
||||
<%= t(".holdings") %>
|
||||
</div>
|
||||
<div class="fg-inverse ml-auto">
|
||||
<div class="text-inverse ml-auto">
|
||||
<%= tag.p format_money(holdings, precision: 0) %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="text-gray-300">
|
||||
<%= t(".total") %>
|
||||
</div>
|
||||
<div class="fg-inverse font-bold ml-auto">
|
||||
<div class="text-inverse font-bold ml-auto">
|
||||
<%= tag.p format_money(balance, precision: 0) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{ label: t(".role_label") } %>
|
||||
|
||||
<div class="w-full">
|
||||
<%= form.submit t(".submit"), class: "bg-inverse fg-inverse rounded-lg px-4 py-2 w-full" %>
|
||||
<%= form.submit t(".submit"), class: "bg-inverse text-inverse rounded-lg px-4 py-2 w-full" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="w-full md:w-1/3">
|
||||
<div class="md:px-3 flex items-center gap-3">
|
||||
<% if @release_notes[:avatar].present? %>
|
||||
<div class="fg-inverse shrink-0 w-9 h-9">
|
||||
<div class="text-inverse shrink-0 w-9 h-9">
|
||||
<%= image_tag @release_notes[:avatar], class: "rounded-full w-full h-full object-cover" %>
|
||||
</div>
|
||||
<% else %>
|
||||
|
||||
@@ -54,12 +54,12 @@
|
||||
<%= button_to t(".disconnect_button"),
|
||||
disconnect_external_assistant_settings_hosting_path,
|
||||
method: :delete,
|
||||
class: "bg-red-600 fg-inverse text-sm font-medium rounded-lg px-4 py-2 whitespace-nowrap",
|
||||
class: "bg-red-600 text-inverse text-sm font-medium rounded-lg px-4 py-2 whitespace-nowrap",
|
||||
data: { turbo_confirm: {
|
||||
title: t(".confirm_disconnect.title"),
|
||||
body: t(".confirm_disconnect.body"),
|
||||
accept: t(".disconnect_button"),
|
||||
acceptClass: "w-full bg-red-600 fg-inverse rounded-xl text-center p-[10px] border mb-2"
|
||||
acceptClass: "w-full bg-red-600 text-inverse rounded-xl text-center p-[10px] border mb-2"
|
||||
}} %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
</div>
|
||||
<%=
|
||||
button_to t("settings.hostings.show.clear_cache"), clear_cache_settings_hosting_path, method: :delete,
|
||||
class: "w-full md:w-auto bg-yellow-600 fg-inverse text-sm font-medium rounded-lg px-4 py-2",
|
||||
class: "w-full md:w-auto bg-yellow-600 text-inverse text-sm font-medium rounded-lg px-4 py-2",
|
||||
data: { turbo_confirm: {
|
||||
title: t("settings.hostings.show.confirm_clear_cache.title"),
|
||||
body: t("settings.hostings.show.confirm_clear_cache.body"),
|
||||
accept: t("settings.hostings.show.clear_cache"),
|
||||
acceptClass: "w-full bg-yellow-600 fg-inverse rounded-xl text-center p-[10px] border mb-2"
|
||||
acceptClass: "w-full bg-yellow-600 text-inverse rounded-xl text-center p-[10px] border mb-2"
|
||||
}}
|
||||
%>
|
||||
</div>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<div class="flex gap-2 items-center justify-between bg-container p-4 border border-alpha-black-25 rounded-lg">
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="w-9 h-9 shrink-0">
|
||||
<div class="fg-inverse w-full h-full bg-surface-inset rounded-full flex items-center justify-center text-lg uppercase"><%= invitation.email[0] %></div>
|
||||
<div class="text-inverse w-full h-full bg-surface-inset rounded-full flex items-center justify-center text-lg uppercase"><%= invitation.email[0] %></div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<p class="text-primary font-medium text-sm"><%= invitation.email %></p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div role="tooltip" data-tooltip-target="tooltip" class="tooltip bg-gray-700 text-sm px-1.5 py-1 rounded-md">
|
||||
<div class="fg-inverse font-normal max-w-[200px]">
|
||||
<div class="text-inverse font-normal max-w-[200px]">
|
||||
<%= tooltip_text %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="cta">
|
||||
<%= tag.div class: "relative flex gap-3 rounded-lg bg-container p-4 group w-full md:max-w-80 shadow-border-xs", data: { controller: "element-removal" } do %>
|
||||
<div class="h-5 w-5 shrink-0 p-px text-primary">
|
||||
<div class="flex h-full items-center justify-center rounded-full bg-success fg-inverse">
|
||||
<div class="flex h-full items-center justify-center rounded-full bg-success text-inverse">
|
||||
<%= icon "check", size: "xs", color: "current" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -100,7 +100,7 @@ The same syntax appears inside composite values like `shadow.xs.$value`: `"0px 1
|
||||
- `utility.border-divider`: the value is a plain class string (`border-tertiary`) instead of a `{ref}`. The build treats values without `{}` as raw `@apply` arguments.
|
||||
- `utility.bg-overlay`: uses `sure.utility.raw: "background-color"` because it needs alpha rendering instead of `@apply`.
|
||||
- `utility.bg-loader`: uses `sure.compose` to apply two utilities together (`bg-surface-inset animate-pulse`).
|
||||
- `utility.button-bg-ghost-hover`: its dark value is a multi-class string (`bg-gray-800 fg-inverse`), not a single ref. The build accepts both forms.
|
||||
- `utility.button-bg-ghost-hover`: its dark value is a multi-class string (`bg-gray-800 text-inverse`), not a single ref. The build accepts both forms.
|
||||
|
||||
## Consumers
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://design-tokens.github.io/community-group/format/",
|
||||
"$version": "1.0.0",
|
||||
"$version": "2.0.0",
|
||||
"$description": "Sure design tokens. Single source of truth. Hand-edit; run `npm run tokens:build` to regenerate CSS. Template syntax in $value strings: `{path.to.token}` resolves to `var(--path-to-token)`; `{path|N%}` becomes `--alpha(var(--path) / N%)`. Utility tokens whose value lacks `{}` are treated as raw Tailwind class lists for @apply.",
|
||||
|
||||
"font": {
|
||||
@@ -275,15 +275,6 @@
|
||||
"$extensions": { "sure.compose": ["bg-surface-inset", "animate-pulse"] }
|
||||
},
|
||||
|
||||
"fg-gray": { "$type": "utility", "$value": "{color.gray.500}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.400}" } },
|
||||
"fg-contrast": { "$type": "utility", "$value": "{color.gray.400}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.500}" } },
|
||||
"fg-inverse": { "$type": "utility", "$value": "{color.white}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.900}" } },
|
||||
"fg-primary": { "$type": "utility", "$value": "{color.gray.900}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.white}" } },
|
||||
"fg-primary-variant": { "$type": "utility", "$value": "{color.gray.800}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.50}" } },
|
||||
"fg-secondary": { "$type": "utility", "$value": "{color.gray.50}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.400}" } },
|
||||
"fg-secondary-variant": { "$type": "utility", "$value": "{color.gray.100}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.500}" } },
|
||||
"fg-subdued": { "$type": "utility", "$value": "{color.gray.400}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.500}" } },
|
||||
|
||||
"text-primary": { "$type": "utility", "$value": "{color.gray.900}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.white}" } },
|
||||
"text-inverse": { "$type": "utility", "$value": "{color.white}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.900}" } },
|
||||
"text-secondary": { "$type": "utility", "$value": "{color.gray.500}", "$extensions": { "sure.utility": { "prefix": "text" }, "sure.dark": "{color.gray.300}" } },
|
||||
@@ -346,7 +337,7 @@
|
||||
"button-bg-disabled": { "$type": "utility", "$value": "{color.gray.50}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "{color.gray.700}" } },
|
||||
"button-bg-destructive": { "$type": "utility", "$value": "{color.red.500}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "{color.red.400}" } },
|
||||
"button-bg-destructive-hover": { "$type": "utility", "$value": "{color.red.600}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "{color.red.500}" } },
|
||||
"button-bg-ghost-hover": { "$type": "utility", "$value": "{color.gray.50}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "bg-gray-800 fg-inverse" } },
|
||||
"button-bg-ghost-hover": { "$type": "utility", "$value": "{color.gray.50}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "bg-gray-800 text-inverse" } },
|
||||
"button-bg-outline-hover": { "$type": "utility", "$value": "{color.gray.100}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "{color.gray.700}" } },
|
||||
|
||||
"tab-item-active": { "$type": "utility", "$value": "{color.white}", "$extensions": { "sure.utility": { "prefix": "bg" }, "sure.dark": "{color.gray.700}" } },
|
||||
|
||||
@@ -48,10 +48,7 @@ class DesignTokensPreview < ViewComponent::Preview
|
||||
end
|
||||
|
||||
def text
|
||||
render_with_template(locals: {
|
||||
text_utilities: collect_utilities { |name| name.start_with?("text-") },
|
||||
fg_utilities: collect_utilities { |name| name.start_with?("fg-") }
|
||||
})
|
||||
render_with_template(locals: { utilities: collect_utilities { |name| name.start_with?("text-") } })
|
||||
end
|
||||
|
||||
def borders
|
||||
|
||||
@@ -3,59 +3,34 @@
|
||||
meta = "text-xs text-secondary font-mono"
|
||||
light_ctx = "rounded p-3 bg-surface"
|
||||
dark_ctx = "rounded p-3 bg-gray-900"
|
||||
|
||||
render_group = ->(items) {
|
||||
capture do
|
||||
content_tag(:div, class: "grid gap-3 grid-cols-1 lg:grid-cols-2") do
|
||||
safe_join(items.map do |u|
|
||||
content_tag(:div, class: card) do
|
||||
safe_join([
|
||||
content_tag(:div, class: "grid grid-cols-2 gap-2") do
|
||||
safe_join([
|
||||
content_tag(:div, class: light_ctx) do
|
||||
content_tag(:p, "Quick brown fox", class: "text-sm font-medium #{u[:name]}")
|
||||
end,
|
||||
content_tag(:div, class: dark_ctx) do
|
||||
content_tag(:p, "Quick brown fox", class: "text-sm font-medium #{u[:name]}")
|
||||
end
|
||||
])
|
||||
end,
|
||||
content_tag(:div, class: "space-y-0.5") do
|
||||
safe_join([
|
||||
content_tag(:p, u[:name], class: "text-xs font-medium text-primary"),
|
||||
content_tag(:p, u[:light_resolved] || u[:light_value], class: "#{meta} truncate"),
|
||||
(u[:dark_value] ? content_tag(:p, "dark: #{u[:dark_resolved] || u[:dark_value]}", class: "#{meta} truncate text-subdued") : nil)
|
||||
].compact)
|
||||
end
|
||||
])
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
}
|
||||
%>
|
||||
<div class="bg-surface min-h-screen p-6 space-y-10">
|
||||
<div class="bg-surface min-h-screen p-6 space-y-6">
|
||||
<header>
|
||||
<h2 class="text-2xl font-semibold text-primary">Text & foregrounds</h2>
|
||||
<p class="text-sm text-secondary">
|
||||
Each example renders the literal class on a light <em>and</em> a dark surface so utilities meant for inverse contexts show their intended state.
|
||||
<code class="font-mono">text-*</code> utilities. Each example renders the literal class on a light <em>and</em> a dark surface so utilities meant for inverse contexts show their intended state.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<section class="space-y-3">
|
||||
<header class="space-y-1">
|
||||
<h3 class="text-lg font-medium text-primary"><code class="font-mono">text-*</code> <span class="text-xs text-secondary font-normal">(canonical, ~2,000 uses across the codebase)</span></h3>
|
||||
</header>
|
||||
<%= render_group.call(text_utilities) %>
|
||||
</section>
|
||||
|
||||
<section class="space-y-3">
|
||||
<header class="space-y-1">
|
||||
<h3 class="text-lg font-medium text-primary"><code class="font-mono">fg-*</code> <span class="text-xs text-warning font-normal">(legacy — prefer <code class="font-mono">text-*</code>)</span></h3>
|
||||
<p class="text-sm text-secondary">
|
||||
Older namespace, ~40 uses left in the codebase. Most are 1:1 duplicates of a <code class="font-mono">text-*</code> equivalent. Tracked for migration; no new code should reference these.
|
||||
</p>
|
||||
</header>
|
||||
<%= render_group.call(fg_utilities) %>
|
||||
</section>
|
||||
<div class="grid gap-3 grid-cols-1 lg:grid-cols-2">
|
||||
<% utilities.each do |u| %>
|
||||
<div class="<%= card %>">
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div class="<%= light_ctx %>">
|
||||
<p class="text-sm font-medium <%= u[:name] %>">Quick brown fox</p>
|
||||
</div>
|
||||
<div class="<%= dark_ctx %>">
|
||||
<p class="text-sm font-medium <%= u[:name] %>">Quick brown fox</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-0.5">
|
||||
<p class="text-xs font-medium text-primary"><%= u[:name] %></p>
|
||||
<p class="<%= meta %> truncate"><%= u[:light_resolved] || u[:light_value] %></p>
|
||||
<% if u[:dark_value] %>
|
||||
<p class="<%= meta %> truncate text-subdued">dark: <%= u[:dark_resolved] || u[:dark_value] %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user