x
1
2
3
<form action="/slow_action" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="UeiCcoduetyhBUA8pxy5pt_MN5BhQOQfKSnBaKKtRU-J_95HEIwe3QFbCkBy3Lui9VjNtLnIvl_3CiPkYqkFXA" autocomplete="off" />
<button name="button" type="submit" class="btn btn--loading"><span>Click and wait</span></button>
</form>
1
2
3
<%= form_with(url: main_app.slow_action_path) do |form| %>
<%= button_tag tag.span("Click and wait"), class: "btn btn--loading" %>
<% end %>
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
:root {
--btn-background: var(--color-bg);
}
.btn {
align-items: center;
background-color: var(--btn-background);
border-radius: var(--btn-radius, var(--rounded-md));
border: 1px solid var(--btn-border-color, var(--color-border));
color: var(--btn-color, var(--color-text));
cursor: pointer;
display: inline-flex;
font-size: var(--btn-font-size, var(--text-sm));
font-weight: var(--btn-font-weight, var(--font-medium));
gap: var(--size-2);
inline-size: var(--btn-inline-size, auto);
justify-content: var(--btn-justify-content, center);
padding: var(--btn-padding, 0.5rem 1rem);
text-align: center;
white-space: nowrap;
img:not([class]) {
filter: var(--btn-icon-color, var(--color-filter-text));
}
&:hover {
background-color: var(--btn-hover-color, oklch(from var(--btn-background) calc(l * .95) c h));
}
&:focus-visible {
outline: var(--btn-outline-size, 2px) solid var(--color-selected-dark);
outline-offset: var(--border-2);
}
&:is(:disabled, [aria-disabled]) {
opacity: var(--opacity-50);
pointer-events: none;
}
}
.btn--primary {
--btn-background: var(--color-primary);
--btn-border-color: transparent;
--btn-color: var(--color-text-reversed);
--btn-icon-color: var(--color-filter-text-reversed);
}
.btn--secondary {
--btn-background: var(--color-secondary);
--btn-border-color: transparent;
}
.btn--borderless {
--btn-border-color: transparent;
}
.btn--positive {
--btn-background: var(--color-positive);
--btn-border-color: transparent;
--btn-color: white;
--btn-icon-color: invert(1);
}
.btn--negative {
--btn-background: var(--color-negative);
--btn-border-color: transparent;
--btn-color: white;
--btn-icon-color: invert(1);
}
.btn--plain {
--btn-background: transparent;
--btn-border-color: transparent;
--btn-hover-color: transparent;
--btn-padding: 0;
}
.btn--icon {
--btn-padding: var(--size-2);
--btn-radius: var(--rounded-full);
}
[aria-busy] .btn--loading:disabled {
> * {
visibility: hidden;
}
&::after {
filter: var(--btn-icon-color, var(--color-filter-text));
}
&::after {
animation: spin 1s linear infinite;
background-image: url("loader-circle.svg");
background-size: cover;
block-size: var(--size-4);
content: "";
inline-size: var(--size-4);
position: absolute;
}
}
Java Script is not required or multiple files are needed, check the notes.