Previews

No matching results.

x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<div class="flex flex-col gap-6">
<div class="flex items-center gap-3">
<div data-controller="ui--theme" class="contents">
<div class="relative inline-block" data-controller="ui--menu"><button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:text-muted-foreground! hover:bg-accent hover:text-accent-foreground disabled:bg-transparent! h-7 w-7 disabled:cursor-not-allowed size-7!" aria-label="Change theme" id="ui-menu-trigger-ui-menu-c47a4605" aria-haspopup="true" aria-expanded="false" aria-controls="ui-menu-content-ui-menu-c47a4605" data-ui--menu-target="trigger" data-action="click->ui--menu#toggle keydown->ui--menu#triggerKeydown"><i data-lucide="sun" class="shrink-0 w-4 h-4 block in-data-[theme=dark]:hidden in-data-[theme=system]:hidden" aria-hidden="true"></i>
<i data-lucide="moon" class="shrink-0 w-4 h-4 hidden in-data-[theme=dark]:block" aria-hidden="true"></i>
<i data-lucide="monitor" class="shrink-0 w-4 h-4 hidden in-data-[theme=system]:block" aria-hidden="true"></i>
</button>
<div id="ui-menu-content-ui-menu-c47a4605" class="z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md flex flex-col gap-[5px] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-40" role="menu" aria-orientation="vertical" data-ui--menu-target="content" hidden="hidden" data-side="bottom" data-align="end" tabindex="-1">
<div class="px-2 py-1.5 text-sm font-semibold text-muted-foreground">Theme</div>
<button role="menuitemradio" data-theme="light" data-action="ui--theme#select" data-ui--theme-target="option" aria-checked="false" class="relative flex cursor-default select-none items-center gap-2 rounded w-full px-2 py-1 text-sm whitespace-nowrap border-0 bg-transparent outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:ring-2 focus:ring-ring focus:ring-offset-1 aria-checked:bg-accent aria-checked:text-accent-foreground aria-checked:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50 transition-all group" tabindex="-1" data-ui--menu-target="item"><i data-lucide="sun" class="inline-block shrink-0 w-4 h-4" aria-hidden="true"></i>
<span>Light</span><i data-lucide="check" class="shrink-0 w-4 h-4 ml-auto hidden group-aria-checked:block" aria-hidden="true"></i>
</button>
<button role="menuitemradio" data-theme="dark" data-action="ui--theme#select" data-ui--theme-target="option" aria-checked="false" class="relative flex cursor-default select-none items-center gap-2 rounded w-full px-2 py-1 text-sm whitespace-nowrap border-0 bg-transparent outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:ring-2 focus:ring-ring focus:ring-offset-1 aria-checked:bg-accent aria-checked:text-accent-foreground aria-checked:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50 transition-all group" tabindex="-1" data-ui--menu-target="item"><i data-lucide="moon" class="inline-block shrink-0 w-4 h-4" aria-hidden="true"></i>
<span>Dark</span><i data-lucide="check" class="shrink-0 w-4 h-4 ml-auto hidden group-aria-checked:block" aria-hidden="true"></i>
</button>
<button role="menuitemradio" data-theme="system" data-action="ui--theme#select" data-ui--theme-target="option" aria-checked="false" class="relative flex cursor-default select-none items-center gap-2 rounded w-full px-2 py-1 text-sm whitespace-nowrap border-0 bg-transparent outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:ring-2 focus:ring-ring focus:ring-offset-1 aria-checked:bg-accent aria-checked:text-accent-foreground aria-checked:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50 transition-all group" tabindex="-1" data-ui--menu-target="item"><i data-lucide="monitor" class="inline-block shrink-0 w-4 h-4" aria-hidden="true"></i>
<span>System</span><i data-lucide="check" class="shrink-0 w-4 h-4 ml-auto hidden group-aria-checked:block" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<p class="text-sm font-normal text-muted-foreground">Flip the theme, then scan for anything unreadable.</p>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
<div class="rounded-md border p-4" style="background: var(--background); color: var(--foreground);">
<div class="text-sm font-medium">--background</div>
<div class="text-xs opacity-80">--foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--card); color: var(--card-foreground);">
<div class="text-sm font-medium">--card</div>
<div class="text-xs opacity-80">--card-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--popover); color: var(--popover-foreground);">
<div class="text-sm font-medium">--popover</div>
<div class="text-xs opacity-80">--popover-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--primary); color: var(--primary-foreground);">
<div class="text-sm font-medium">--primary</div>
<div class="text-xs opacity-80">--primary-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--secondary); color: var(--secondary-foreground);">
<div class="text-sm font-medium">--secondary</div>
<div class="text-xs opacity-80">--secondary-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--muted); color: var(--muted-foreground);">
<div class="text-sm font-medium">--muted</div>
<div class="text-xs opacity-80">--muted-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--accent); color: var(--accent-foreground);">
<div class="text-sm font-medium">--accent</div>
<div class="text-xs opacity-80">--accent-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--sidebar); color: var(--sidebar-foreground);">
<div class="text-sm font-medium">--sidebar</div>
<div class="text-xs opacity-80">--sidebar-foreground</div>
</div>
<div class="rounded-md border p-4" style="background: var(--sidebar-accent); color: var(--sidebar-accent-foreground);">
<div class="text-sm font-medium">--sidebar-accent</div>
<div class="text-xs opacity-80">--sidebar-accent-foreground</div>
</div>
</div>
<div class="flex flex-wrap items-center gap-3">
<button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:bg-muted! disabled:text-muted-foreground! bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-2 disabled:cursor-not-allowed" aria-busy="false">Primary</button>
<button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:bg-muted! disabled:text-muted-foreground! bg-secondary text-secondary-foreground hover:bg-secondary/80 h-9 px-4 py-2 disabled:cursor-not-allowed" aria-busy="false">Secondary</button>
<button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:bg-muted! disabled:text-muted-foreground! border border-input bg-background hover:bg-accent hover:text-accent-foreground disabled:border-input! h-9 px-4 py-2 disabled:cursor-not-allowed" aria-busy="false">Outline</button>
<button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:text-muted-foreground! hover:bg-accent hover:text-accent-foreground disabled:bg-transparent! h-9 px-4 py-2 disabled:cursor-not-allowed" aria-busy="false">Ghost</button>
<button type="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-offset-1 ring-offset-background disabled:pointer-events-none disabled:bg-muted! disabled:text-muted-foreground! bg-destructive text-white hover:bg-destructive/90 focus:ring-destructive h-9 px-4 py-2 disabled:cursor-not-allowed" aria-busy="false">Destructive</button>
</div>
<div class="flex flex-wrap items-center gap-3">
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 bg-primary text-primary-foreground hover:bg-primary/80 h-6 px-2 text-xs leading-none">Default</span>
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 bg-secondary text-secondary-foreground hover:bg-secondary/80 h-6 px-2 text-xs leading-none">Secondary</span>
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 bg-destructive text-white hover:bg-destructive/80 h-6 px-2 text-xs leading-none">Destructive</span>
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 text-foreground border-input h-6 px-2 text-xs leading-none">Outline</span>
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 bg-emerald-500 dark:bg-emerald-600 text-white hover:bg-emerald-500/80 dark:hover:bg-emerald-600/80 h-6 px-2 text-xs leading-none">Success</span>
<span class="inline-flex items-center justify-center gap-1 rounded-full font-medium whitespace-nowrap border border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 bg-amber-500 dark:bg-amber-600 text-white hover:bg-amber-500/80 dark:hover:bg-amber-600/80 h-6 px-2 text-xs leading-none">Warning</span>
</div>
<div class="flex flex-col gap-3 max-w-md">
<div role="alert" aria-live="assertive" aria-atomic="true" class="relative w-full rounded-md border p-4 flex items-start gap-3 [&>i]:translate-y-0.5 [&>i]:shrink-0 bg-background text-foreground border-input">
<i data-lucide="info" class="inline-block w-4 h-4 shrink-0" aria-hidden="true"></i>
<div class="flex flex-col gap-1 min-w-0 flex-1">
<h5 class="font-medium leading-none tracking-tight">Default</h5>
<div class="text-sm leading-relaxed [&_p]:leading-relaxed">How the default alert reads in this theme.</div>
</div>
</div>
<div role="alert" aria-live="assertive" aria-atomic="true" class="relative w-full rounded-md border p-4 flex items-start gap-3 [&>i]:translate-y-0.5 [&>i]:shrink-0 bg-destructive/10 text-destructive border-destructive/30">
<i data-lucide="circle-alert" class="inline-block w-4 h-4 shrink-0" aria-hidden="true"></i>
<div class="flex flex-col gap-1 min-w-0 flex-1">
<h5 class="font-medium leading-none tracking-tight">Destructive</h5>
<div class="text-sm leading-relaxed [&_p]:leading-relaxed">How the destructive alert reads in this theme.</div>
</div>
</div>
<div role="alert" aria-live="assertive" aria-atomic="true" class="relative w-full rounded-md border p-4 flex items-start gap-3 [&>i]:translate-y-0.5 [&>i]:shrink-0 bg-amber-50 text-amber-800 border-amber-300 dark:bg-amber-950/30 dark:text-amber-200 dark:border-amber-800">
<i data-lucide="circle-alert" class="inline-block w-4 h-4 shrink-0" aria-hidden="true"></i>
<div class="flex flex-col gap-1 min-w-0 flex-1">
<h5 class="font-medium leading-none tracking-tight">Warning</h5>
<div class="text-sm leading-relaxed [&_p]:leading-relaxed">How the warning alert reads in this theme.</div>
</div>
</div>
<div role="alert" aria-live="assertive" aria-atomic="true" class="relative w-full rounded-md border p-4 flex items-start gap-3 [&>i]:translate-y-0.5 [&>i]:shrink-0 bg-emerald-50 text-emerald-800 border-emerald-300 dark:bg-emerald-950/30 dark:text-emerald-200 dark:border-emerald-800">
<i data-lucide="circle-check" class="inline-block w-4 h-4 shrink-0" aria-hidden="true"></i>
<div class="flex flex-col gap-1 min-w-0 flex-1">
<h5 class="font-medium leading-none tracking-tight">Success</h5>
<div class="text-sm leading-relaxed [&_p]:leading-relaxed">How the success alert reads in this theme.</div>
</div>
</div>
<div role="alert" aria-live="assertive" aria-atomic="true" class="relative w-full rounded-md border p-4 flex items-start gap-3 [&>i]:translate-y-0.5 [&>i]:shrink-0 bg-sky-50 text-sky-800 border-sky-300 dark:bg-sky-950/30 dark:text-sky-200 dark:border-sky-800">
<i data-lucide="info" class="inline-block w-4 h-4 shrink-0" aria-hidden="true"></i>
<div class="flex flex-col gap-1 min-w-0 flex-1">
<h5 class="font-medium leading-none tracking-tight">Info</h5>
<div class="text-sm leading-relaxed [&_p]:leading-relaxed">How the info alert reads in this theme.</div>
</div>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<%# Every semantic token side by side. The fastest way to review both themes:
flip the toggle and check nothing goes muddy or illegible. %>
<% pairs = [
["background", "foreground"], ["card", "card-foreground"],
["popover", "popover-foreground"], ["primary", "primary-foreground"],
["secondary", "secondary-foreground"], ["muted", "muted-foreground"],
["accent", "accent-foreground"], ["sidebar", "sidebar-foreground"],
["sidebar-accent", "sidebar-accent-foreground"]
] %>
<div class="flex flex-col gap-6">
<div class="flex items-center gap-3">
<%= render(UI::ThemeToggle.new) %>
<%= render(UI::Typography::Muted.new) { "Flip the theme, then scan for anything unreadable." } %>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
<% pairs.each do |bg, fg| %>
<div class="rounded-md border p-4" style="background: var(--<%= bg %>); color: var(--<%= fg %>);">
<div class="text-sm font-medium">--<%= bg %></div>
<div class="text-xs opacity-80">--<%= fg %></div>
</div>
<% end %>
</div>
<div class="flex flex-wrap items-center gap-3">
<%= render(UI::Button.new) { "Primary" } %>
<%= render(UI::Button.new(variant: :secondary)) { "Secondary" } %>
<%= render(UI::Button.new(variant: :outline)) { "Outline" } %>
<%= render(UI::Button.new(variant: :ghost)) { "Ghost" } %>
<%= render(UI::Button.new(variant: :destructive)) { "Destructive" } %>
</div>
<div class="flex flex-wrap items-center gap-3">
<% %i[default secondary destructive outline success warning].each do |v| %>
<%= render(UI::Badge.new(variant: v)) { v.to_s.capitalize } %>
<% end %>
</div>
<div class="flex flex-col gap-3 max-w-md">
<% %i[default destructive warning success info].each do |v| %>
<%= render(UI::Alert.new(variant: v)) do |alert| %>
<% alert.with_title { v.to_s.capitalize } %>
<% alert.with_description { "How the #{v} alert reads in this theme." } %>
<% end %>
<% end %>
</div>
</div>