Skip to content

Commit b5f3654

Browse files
authored
Merge pull request #242 from ocsigen/forms2
Adding reactive forms (from Be Sport, extracted by Claude)
2 parents 6ef5a15 + fd38f0d commit b5f3654

File tree

5 files changed

+1493
-39
lines changed

5 files changed

+1493
-39
lines changed

css/ot_form.css

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/* ================================================================ */
2+
/* Toggle button */
3+
/* ================================================================ */
4+
5+
.ot-toggle-button {
6+
display: inline-flex;
7+
align-items: center;
8+
padding: 0.4em 1em;
9+
border: 1px solid #ccc;
10+
border-radius: 4px;
11+
cursor: pointer;
12+
transition: background-color 0.15s, border-color 0.15s, color 0.15s;
13+
}
14+
15+
.ot-toggle-off {
16+
background-color: #4a90d9;
17+
border-color: #4a90d9;
18+
color: white;
19+
}
20+
21+
.ot-toggle-off:hover {
22+
background-color: #3a7bc8;
23+
border-color: #3a7bc8;
24+
}
25+
26+
.ot-toggle-on {
27+
background-color: #3570a8;
28+
border-color: #2d6090;
29+
color: white;
30+
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
31+
}
32+
33+
.ot-toggle-on:hover {
34+
background-color: #2d6090;
35+
border-color: #265580;
36+
}
37+
38+
/* ================================================================ */
39+
/* Password input */
40+
/* ================================================================ */
41+
42+
.ot-password-container {
43+
display: flex;
44+
align-items: center;
45+
}
46+
47+
.ot-password-container > .ot-password-input {
48+
flex: 1;
49+
}
50+
51+
.ot-password-toggle {
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
padding: 0.4em 0.6em;
56+
border: 1px solid #ccc;
57+
border-left: none;
58+
background: #f5f5f5;
59+
cursor: pointer;
60+
line-height: 1;
61+
}
62+
63+
.ot-password-toggle:hover {
64+
background: #e8e8e8;
65+
}
66+
67+
/* Pressed look when password is visible (toggle shows the "hide" icon) */
68+
.ot-password-toggle:has(.ot-password-toggle-hide) {
69+
background: #e0e0e0;
70+
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
71+
}
72+
73+
/* The toggle contains a span that gets class ot-password-toggle-show
74+
or ot-password-toggle-hide via R.a_class. We use background-image
75+
SVGs so the icon is visible even though the span has no text. */
76+
.ot-password-toggle-show,
77+
.ot-password-toggle-hide {
78+
display: inline-block;
79+
width: 1.4em;
80+
height: 1.4em;
81+
background-size: contain;
82+
background-repeat: no-repeat;
83+
background-position: center;
84+
}
85+
86+
/* Eye open (Feather icon) */
87+
.ot-password-toggle-show {
88+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
89+
}
90+
91+
/* Eye off / barred (Feather icon) */
92+
.ot-password-toggle-hide {
93+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'/%3E%3Cline x1='1' y1='1' x2='23' y2='23'/%3E%3C/svg%3E");
94+
}
95+
96+
/* ================================================================ */
97+
/* Checkbox */
98+
/* ================================================================ */
99+
100+
/* The label element has both a desktop and a mobile style class,
101+
e.g. ot-checkbox-box-desktop + ot-checkbox-toggle-mobile.
102+
We only style desktop classes here; apps should add media queries
103+
to switch to mobile styles at their chosen breakpoint.
104+
105+
DOM structure:
106+
label.ot-checkbox.ot-checkbox-{style}-desktop
107+
input.ot-checkbox-input[type=checkbox] (hidden)
108+
span.ot-checkbox-label
109+
span.ot-checkbox-decoration
110+
span.ot-checkbox-sub-decoration
111+
span (text content)
112+
*/
113+
114+
.ot-checkbox {
115+
display: inline-flex;
116+
align-items: center;
117+
cursor: pointer;
118+
gap: 0.5em;
119+
}
120+
121+
.ot-checkbox-label {
122+
display: inline-flex;
123+
align-items: center;
124+
gap: 0.4em;
125+
}
126+
127+
.ot-checkbox > .ot-checkbox-input {
128+
position: absolute;
129+
opacity: 0;
130+
width: 0;
131+
height: 0;
132+
}
133+
134+
/* --- Box style -------------------------------------------------- */
135+
136+
.ot-checkbox-box-desktop .ot-checkbox-decoration {
137+
display: inline-flex;
138+
align-items: center;
139+
justify-content: center;
140+
width: 1.2em;
141+
height: 1.2em;
142+
border: 2px solid #888;
143+
border-radius: 3px;
144+
background: white;
145+
transition: background-color 0.15s, border-color 0.15s;
146+
}
147+
148+
.ot-checkbox-box-desktop .ot-checkbox-sub-decoration {
149+
width: 0.35em;
150+
height: 0.65em;
151+
border: solid transparent;
152+
border-width: 0 2px 2px 0;
153+
transform: rotate(45deg);
154+
margin-bottom: 0.1em;
155+
}
156+
157+
.ot-checkbox-box-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-decoration {
158+
background-color: #4a90d9;
159+
border-color: #4a90d9;
160+
}
161+
162+
.ot-checkbox-box-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-sub-decoration {
163+
border-color: white;
164+
}
165+
166+
/* --- Toggle style ----------------------------------------------- */
167+
168+
.ot-checkbox-toggle-desktop .ot-checkbox-decoration {
169+
display: inline-block;
170+
width: 2.4em;
171+
height: 1.3em;
172+
border-radius: 0.65em;
173+
background-color: #ccc;
174+
position: relative;
175+
transition: background-color 0.2s;
176+
}
177+
178+
.ot-checkbox-toggle-desktop .ot-checkbox-sub-decoration {
179+
display: block;
180+
position: absolute;
181+
width: 1.05em;
182+
height: 1.05em;
183+
border-radius: 50%;
184+
background: white;
185+
top: 0.125em;
186+
left: 0.125em;
187+
transition: transform 0.2s;
188+
}
189+
190+
.ot-checkbox-toggle-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-decoration {
191+
background-color: #4a90d9;
192+
}
193+
194+
.ot-checkbox-toggle-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-sub-decoration {
195+
transform: translateX(1.1em);
196+
}
197+
198+
/* --- Bullet style ----------------------------------------------- */
199+
200+
.ot-checkbox-bullet-desktop .ot-checkbox-decoration {
201+
display: inline-flex;
202+
align-items: center;
203+
justify-content: center;
204+
width: 1.2em;
205+
height: 1.2em;
206+
border: 2px solid #888;
207+
border-radius: 50%;
208+
background: white;
209+
transition: border-color 0.15s;
210+
}
211+
212+
.ot-checkbox-bullet-desktop .ot-checkbox-sub-decoration {
213+
width: 0.6em;
214+
height: 0.6em;
215+
border-radius: 50%;
216+
background-color: transparent;
217+
transition: background-color 0.15s;
218+
}
219+
220+
.ot-checkbox-bullet-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-decoration {
221+
border-color: #4a90d9;
222+
}
223+
224+
.ot-checkbox-bullet-desktop > .ot-checkbox-input:checked + .ot-checkbox-label .ot-checkbox-sub-decoration {
225+
background-color: #4a90d9;
226+
}

ocsigen-toolkit.install

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ share: [
1212
"css/ot_color_picker.css" {"css/ot_color_picker.css"}
1313
"css/ot_pull_to_refresh.css" {"css/ot_pull_to_refresh.css"}
1414
"css/ot_tongue.css" {"css/ot_tongue.css"}
15+
"css/ot_form.css" {"css/ot_form.css"}
1516
]

opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
opam-version: "2.0"
22
name: "ocsigen-toolkit"
3-
version: "4.1.0"
3+
version: "4.2.0"
44
maintainer: "dev@ocsigen.org"
55
synopsis: "Reusable UI components for Eliom applications (client only, or client-server)"
66
description: "The Ocsigen Toolkit is a set of user interface widgets that facilitate the development of Eliom applications."

0 commit comments

Comments
 (0)