feat: alternative styling for single choice questions

This commit is contained in:
Adriano Caloiaro 2025-02-18 18:00:58 -07:00
parent 2f0d7c99f6
commit 563a1c1eff
No known key found for this signature in database
GPG key ID: C2BC56DE73CE3F75
16 changed files with 540 additions and 251 deletions

3
.ignore Normal file
View file

@ -0,0 +1,3 @@
**/**_templ.{go,txt}
static/**
**_enumer*.go

View file

@ -1806,11 +1806,11 @@
"systems": "systems_6"
},
"locked": {
"lastModified": 1730850516,
"narHash": "sha256-V79L9JZLhn78B11DN/ZrQ9beZiUgaOb0EYeQFtW78W8=",
"lastModified": 1739908740,
"narHash": "sha256-j9glgLcq36MWG/EUFJKC9r4cu8/GbVzJNt8zgniRPfo=",
"owner": "acaloiaro",
"repo": "tailwind-cli-extra",
"rev": "2ee50b55ea468ebbe39a98be3b221780aa32d3ee",
"rev": "f4a392401e3f85a82693b50177944ae0b44ec155",
"type": "github"
},
"original": {

View file

@ -205,7 +205,7 @@
-r '.*tailwind\.css$|.*\.templ$' \
--inverse-regex='\.devenv' \
--inverse-regex='\.direnv' \
-- tailwindcss -i ./css/tailwind.css -o ./static/css/styles.css
-- tailwindcss -i ./ui/css/tailwind.css -o ./static/css/styles.css -c ./ui/tailwind.config.js
'';
};

View file

@ -336,6 +336,8 @@ func NewField(w http.ResponseWriter, r *http.Request) {
newField.Placeholder = "Choose items"
case types.FormFieldTypeSingleChoice:
newField.Label = "New single choice field"
case types.FormFieldTypeSingleChoiceSpaced:
newField.Label = "New single choice field (spaced)"
}
fields[fieldID.String()] = *newField

View file

@ -1,5 +1,113 @@
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
/*
! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com
! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com
*/
/*
@ -442,11 +550,11 @@ video {
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
[hidden]:where(:not([hidden="until-found"])) {
display: none;
}
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@ -463,7 +571,7 @@ video {
--tw-shadow: 0 0 #0000;
}
[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
outline: 2px solid transparent;
outline-offset: 2px;
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
@ -492,6 +600,11 @@ input::placeholder,textarea::placeholder {
::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
@ -509,7 +622,7 @@ select {
print-color-adjust: exact;
}
[multiple] {
[multiple],[size]:where(select:not([size="1"])) {
background-image: initial;
background-position: initial;
background-repeat: unset;
@ -574,10 +687,26 @@ select {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='checkbox']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='radio']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
}
@media (forced-colors: active) {
[type='radio']:checked {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
border-color: transparent;
background-color: currentColor;
@ -592,6 +721,14 @@ select {
background-repeat: no-repeat;
}
@media (forced-colors: active) {
[type='checkbox']:indeterminate {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
}
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
border-color: transparent;
background-color: currentColor;
@ -816,114 +953,6 @@ html {
--bc: 74.6477% 0.0216 264.435964;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
--tw-contain-size: ;
--tw-contain-layout: ;
--tw-contain-paint: ;
--tw-contain-style: ;
}
.container {
width: 100%;
}
@ -1004,6 +1033,11 @@ html {
.form-input::-webkit-date-and-time-value {
min-height: 1.5em;
text-align: inherit;
}
.form-input::-webkit-datetime-edit {
display: inline-flex;
}
.form-input::-webkit-datetime-edit,.form-input::-webkit-datetime-edit-year-field,.form-input::-webkit-datetime-edit-month-field,.form-input::-webkit-datetime-edit-day-field,.form-input::-webkit-datetime-edit-hour-field,.form-input::-webkit-datetime-edit-minute-field,.form-input::-webkit-datetime-edit-second-field,.form-input::-webkit-datetime-edit-millisecond-field,.form-input::-webkit-datetime-edit-meridiem-field {
@ -2458,6 +2492,11 @@ input.tab:checked + .tab-content,
.join.join-horizontal > :where(*:not(:first-child)):is(.btn) {
margin-inline-start: calc(var(--border-btn) * -1);
margin-top: 0px;
}
.invisible {
visibility: hidden;
}
.fixed {
@ -2481,20 +2520,11 @@ input.tab:checked + .tab-content,
margin-right: auto;
}
.my-1 {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
}
.my-1\.5 {
margin-top: 0.375rem;
margin-bottom: 0.375rem;
}
.-mt-0 {
margin-top: -0px;
}
.-mt-0\.5 {
margin-top: -0.125rem;
}
@ -2544,6 +2574,15 @@ input.tab:checked + .tab-content,
height: 1.5rem;
}
.size-7 {
width: 1.75rem;
height: 1.75rem;
}
.h-0 {
height: 0px;
}
.h-12 {
height: 3rem;
}
@ -2580,6 +2619,10 @@ input.tab:checked + .tab-content,
min-height: 1.5rem;
}
.w-0 {
width: 0px;
}
.w-1\/2 {
width: 50%;
}
@ -2600,6 +2643,10 @@ input.tab:checked + .tab-content,
width: 1.25rem;
}
.w-auto {
width: auto;
}
.w-full {
width: 100%;
}
@ -2625,6 +2672,10 @@ input.tab:checked + .tab-content,
flex-shrink: 0;
}
.shrink {
flex-shrink: 1;
}
.flex-grow {
flex-grow: 1;
}
@ -2647,6 +2698,10 @@ input.tab:checked + .tab-content,
appearance: none;
}
.grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@ -2683,9 +2738,8 @@ input.tab:checked + .tab-content,
gap: 1.25rem;
}
.gap-x-0 {
-moz-column-gap: 0px;
column-gap: 0px;
.gap-8 {
gap: 2rem;
}
.gap-x-0\.5 {
@ -2693,11 +2747,6 @@ input.tab:checked + .tab-content,
column-gap: 0.125rem;
}
.gap-x-1 {
-moz-column-gap: 0.25rem;
column-gap: 0.25rem;
}
.gap-x-1\.5 {
-moz-column-gap: 0.375rem;
column-gap: 0.375rem;
@ -2718,6 +2767,10 @@ input.tab:checked + .tab-content,
place-self: center;
}
.justify-self-end {
justify-self: end;
}
.overflow-visible {
overflow: visible;
}
@ -2740,6 +2793,10 @@ input.tab:checked + .tab-content,
border-radius: 0.25rem;
}
.rounded-full {
border-radius: 9999px;
}
.rounded-lg {
border-radius: 0.5rem;
}
@ -2771,66 +2828,62 @@ input.tab:checked + .tab-content,
.border-base-300 {
--tw-border-opacity: 1;
border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));
border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity, 1)));
}
.border-black {
--tw-border-opacity: 1;
border-color: rgb(0 0 0 / var(--tw-border-opacity));
border-color: rgb(0 0 0 / var(--tw-border-opacity, 1));
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(176 176 176 / var(--tw-border-opacity));
border-color: rgb(176 176 176 / var(--tw-border-opacity, 1));
}
.bg-base-200 {
--tw-bg-opacity: 1;
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity, 1)));
}
.bg-blue-100 {
--tw-bg-opacity: 1;
background-color: rgb(219 234 254 / var(--tw-bg-opacity));
background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgb(231 231 231 / var(--tw-bg-opacity));
background-color: rgb(231 231 231 / var(--tw-bg-opacity, 1));
}
.bg-gray-50 {
--tw-bg-opacity: 1;
background-color: rgb(246 246 246 / var(--tw-bg-opacity));
background-color: rgb(246 246 246 / var(--tw-bg-opacity, 1));
}
.bg-primary-500 {
--tw-bg-opacity: 1;
background-color: rgb(0 159 255 / var(--tw-bg-opacity));
background-color: rgb(0 159 255 / var(--tw-bg-opacity, 1));
}
.bg-sky-100 {
--tw-bg-opacity: 1;
background-color: rgb(224 242 254 / var(--tw-bg-opacity));
background-color: rgb(224 242 254 / var(--tw-bg-opacity, 1));
}
.bg-sky-200 {
--tw-bg-opacity: 1;
background-color: rgb(186 230 253 / var(--tw-bg-opacity));
background-color: rgb(186 230 253 / var(--tw-bg-opacity, 1));
}
.bg-sky-50 {
--tw-bg-opacity: 1;
background-color: rgb(240 249 255 / var(--tw-bg-opacity));
background-color: rgb(240 249 255 / var(--tw-bg-opacity, 1));
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.p-0 {
padding: 0px;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.p-0\.5 {
@ -3006,32 +3059,32 @@ input.tab:checked + .tab-content,
.text-black {
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity));
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
}
.text-blue-900 {
--tw-text-opacity: 1;
color: rgb(30 58 138 / var(--tw-text-opacity));
color: rgb(30 58 138 / var(--tw-text-opacity, 1));
}
.text-gray-400 {
--tw-text-opacity: 1;
color: rgb(136 136 136 / var(--tw-text-opacity));
color: rgb(136 136 136 / var(--tw-text-opacity, 1));
}
.text-gray-500 {
--tw-text-opacity: 1;
color: rgb(109 109 109 / var(--tw-text-opacity));
color: rgb(109 109 109 / var(--tw-text-opacity, 1));
}
.text-gray-700 {
--tw-text-opacity: 1;
color: rgb(76 76 76 / var(--tw-text-opacity));
color: rgb(76 76 76 / var(--tw-text-opacity, 1));
}
.text-gray-800 {
--tw-text-opacity: 1;
color: rgb(69 69 69 / var(--tw-text-opacity));
color: rgb(69 69 69 / var(--tw-text-opacity, 1));
}
.text-inherit {
@ -3040,22 +3093,22 @@ input.tab:checked + .tab-content,
.text-red-400 {
--tw-text-opacity: 1;
color: rgb(255 153 153 / var(--tw-text-opacity));
color: rgb(255 153 153 / var(--tw-text-opacity, 1));
}
.text-red-500 {
--tw-text-opacity: 1;
color: rgb(255 119 119 / var(--tw-text-opacity));
color: rgb(255 119 119 / var(--tw-text-opacity, 1));
}
.text-slate-700 {
--tw-text-opacity: 1;
color: rgb(51 65 85 / var(--tw-text-opacity));
color: rgb(51 65 85 / var(--tw-text-opacity, 1));
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.underline {
@ -3064,12 +3117,16 @@ input.tab:checked + .tab-content,
.placeholder-gray-400::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(136 136 136 / var(--tw-placeholder-opacity));
color: rgb(136 136 136 / var(--tw-placeholder-opacity, 1));
}
.placeholder-gray-400::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(136 136 136 / var(--tw-placeholder-opacity));
color: rgb(136 136 136 / var(--tw-placeholder-opacity, 1));
}
.opacity-0 {
opacity: 0;
}
.shadow-sm {
@ -3148,38 +3205,34 @@ https://github.com/Choices-js/Choices/issues/449
text-align: right;
}
.checked\:bg-none:checked {
background-image: none;
}
.hover\:bg-gray-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(231 231 231 / var(--tw-bg-opacity));
background-color: rgb(231 231 231 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(209 209 209 / var(--tw-bg-opacity));
background-color: rgb(209 209 209 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(246 246 246 / var(--tw-bg-opacity));
background-color: rgb(246 246 246 / var(--tw-bg-opacity, 1));
}
.hover\:bg-primary-400:hover {
--tw-bg-opacity: 1;
background-color: rgb(38 198 255 / var(--tw-bg-opacity));
background-color: rgb(38 198 255 / var(--tw-bg-opacity, 1));
}
.hover\:bg-primary-600:hover {
--tw-bg-opacity: 1;
background-color: rgb(0 117 255 / var(--tw-bg-opacity));
background-color: rgb(0 117 255 / var(--tw-bg-opacity, 1));
}
.hover\:text-gray-800:hover {
--tw-text-opacity: 1;
color: rgb(69 69 69 / var(--tw-text-opacity));
color: rgb(69 69 69 / var(--tw-text-opacity, 1));
}
.focus\:border-2:focus {
@ -3225,27 +3278,41 @@ https://github.com/Choices-js/Choices/issues/449
cursor: not-allowed;
}
.disabled\:bg-gray-500:disabled {
.disabled\:bg-gray-200:disabled {
--tw-bg-opacity: 1;
background-color: rgb(109 109 109 / var(--tw-bg-opacity));
background-color: rgb(209 209 209 / var(--tw-bg-opacity, 1));
}
.disabled\:bg-primary-500:disabled {
--tw-bg-opacity: 1;
background-color: rgb(0 159 255 / var(--tw-bg-opacity));
background-color: rgb(0 159 255 / var(--tw-bg-opacity, 1));
}
.disabled\:opacity-75:disabled {
opacity: 0.75;
}
.peer:checked ~ .peer-checked\:visible {
visibility: visible;
}
.has-\[\:checked\]\:border-sky-500:has(:checked) {
--tw-border-opacity: 1;
border-color: rgb(14 165 233 / var(--tw-border-opacity, 1));
}
.has-\[\:checked\]\:bg-sky-400:has(:checked) {
--tw-bg-opacity: 1;
background-color: rgb(56 189 248 / var(--tw-bg-opacity, 1));
}
.aria-disabled\:cursor-not-allowed[aria-disabled="true"] {
cursor: not-allowed;
}
.aria-disabled\:bg-primary-500[aria-disabled="true"] {
--tw-bg-opacity: 1;
background-color: rgb(0 159 255 / var(--tw-bg-opacity));
background-color: rgb(0 159 255 / var(--tw-bg-opacity, 1));
}
.aria-disabled\:opacity-75[aria-disabled="true"] {
@ -3254,47 +3321,47 @@ https://github.com/Choices-js/Choices/issues/449
.dark\:border-gray-600:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(93 93 93 / var(--tw-border-opacity));
border-color: rgb(93 93 93 / var(--tw-border-opacity, 1));
}
.dark\:bg-gray-800:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(69 69 69 / var(--tw-bg-opacity));
background-color: rgb(69 69 69 / var(--tw-bg-opacity, 1));
}
.dark\:bg-primary-400:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(38 198 255 / var(--tw-bg-opacity));
background-color: rgb(38 198 255 / var(--tw-bg-opacity, 1));
}
.dark\:text-gray-300:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(176 176 176 / var(--tw-text-opacity));
color: rgb(176 176 176 / var(--tw-text-opacity, 1));
}
.dark\:text-gray-900:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(61 61 61 / var(--tw-text-opacity));
color: rgb(61 61 61 / var(--tw-text-opacity, 1));
}
.dark\:placeholder-gray-500:is(.dark *)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(109 109 109 / var(--tw-placeholder-opacity));
color: rgb(109 109 109 / var(--tw-placeholder-opacity, 1));
}
.dark\:placeholder-gray-500:is(.dark *)::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(109 109 109 / var(--tw-placeholder-opacity));
color: rgb(109 109 109 / var(--tw-placeholder-opacity, 1));
}
.dark\:hover\:bg-gray-800:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(69 69 69 / var(--tw-bg-opacity));
background-color: rgb(69 69 69 / var(--tw-bg-opacity, 1));
}
.dark\:hover\:bg-primary-500:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 159 255 / var(--tw-bg-opacity));
background-color: rgb(0 159 255 / var(--tw-bg-opacity, 1));
}
.dark\:focus-visible\:outline-primary-400:focus-visible:is(.dark *) {
@ -3303,12 +3370,12 @@ https://github.com/Choices-js/Choices/issues/449
.dark\:disabled\:bg-primary-400:disabled:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(38 198 255 / var(--tw-bg-opacity));
background-color: rgb(38 198 255 / var(--tw-bg-opacity, 1));
}
.dark\:aria-disabled\:bg-primary-400[aria-disabled="true"]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(38 198 255 / var(--tw-bg-opacity));
background-color: rgb(38 198 255 / var(--tw-bg-opacity, 1));
}
@media (min-width: 768px) {
@ -3352,6 +3419,12 @@ https://github.com/Choices-js/Choices/issues/449
}
}
@media (min-width: 1280px) {
.xl\:grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media print {
.print\:hidden {
display: none;

View file

@ -8,11 +8,11 @@ import (
"strings"
)
const _FormFieldTypeName = "text_singletext_multiplesingle_selectmulti_selectsingle_choice"
const _FormFieldTypeName = "text_singletext_multiplesingle_selectmulti_selectsingle_choicesingle_choice_spaced"
var _FormFieldTypeIndex = [...]uint8{0, 11, 24, 37, 49, 62}
var _FormFieldTypeIndex = [...]uint8{0, 11, 24, 37, 49, 62, 82}
const _FormFieldTypeLowerName = "text_singletext_multiplesingle_selectmulti_selectsingle_choice"
const _FormFieldTypeLowerName = "text_singletext_multiplesingle_selectmulti_selectsingle_choicesingle_choice_spaced"
func (i FormFieldType) String() string {
if i < 0 || i >= FormFieldType(len(_FormFieldTypeIndex)-1) {
@ -30,9 +30,10 @@ func _FormFieldTypeNoOp() {
_ = x[FormFieldTypeSingleSelect-(2)]
_ = x[FormFieldTypeMultiSelect-(3)]
_ = x[FormFieldTypeSingleChoice-(4)]
_ = x[FormFieldTypeSingleChoiceSpaced-(5)]
}
var _FormFieldTypeValues = []FormFieldType{FormFieldTypeTextSingle, FormFieldTypeTextMultiple, FormFieldTypeSingleSelect, FormFieldTypeMultiSelect, FormFieldTypeSingleChoice}
var _FormFieldTypeValues = []FormFieldType{FormFieldTypeTextSingle, FormFieldTypeTextMultiple, FormFieldTypeSingleSelect, FormFieldTypeMultiSelect, FormFieldTypeSingleChoice, FormFieldTypeSingleChoiceSpaced}
var _FormFieldTypeNameToValueMap = map[string]FormFieldType{
_FormFieldTypeName[0:11]: FormFieldTypeTextSingle,
@ -45,6 +46,8 @@ var _FormFieldTypeNameToValueMap = map[string]FormFieldType{
_FormFieldTypeLowerName[37:49]: FormFieldTypeMultiSelect,
_FormFieldTypeName[49:62]: FormFieldTypeSingleChoice,
_FormFieldTypeLowerName[49:62]: FormFieldTypeSingleChoice,
_FormFieldTypeName[62:82]: FormFieldTypeSingleChoiceSpaced,
_FormFieldTypeLowerName[62:82]: FormFieldTypeSingleChoiceSpaced,
}
var _FormFieldTypeNames = []string{
@ -53,6 +56,7 @@ var _FormFieldTypeNames = []string{
_FormFieldTypeName[24:37],
_FormFieldTypeName[37:49],
_FormFieldTypeName[49:62],
_FormFieldTypeName[62:82],
}
// FormFieldTypeString retrieves an enum value from the enum constants string name.

View file

@ -24,11 +24,12 @@ func (v ValidationErrors) Any() bool {
type FormFieldType int
const (
FormFieldTypeTextSingle FormFieldType = iota // single line of text
FormFieldTypeTextMultiple // multiple lines of text
FormFieldTypeSingleSelect // single-select dropdown
FormFieldTypeMultiSelect // multi-select dropdown
FormFieldTypeSingleChoice
FormFieldTypeTextSingle FormFieldType = iota // single line of text
FormFieldTypeTextMultiple // multiple lines of text
FormFieldTypeSingleSelect // single-select dropdown
FormFieldTypeMultiSelect // multi-select dropdown
FormFieldTypeSingleChoice // nicely styled radio buttons
FormFieldTypeSingleChoiceSpaced // nicely styled radio buttons, spaced out
)
// FormFieldDataType enum enumerates all possible data types for form fields
@ -155,7 +156,7 @@ func (f FormField) Validate(value []string) (err error) {
switch f.Type {
// ensure that the provided value is one of this field's available options
case FormFieldTypeSingleSelect, FormFieldTypeMultiSelect, FormFieldTypeSingleChoice:
case FormFieldTypeSingleSelect, FormFieldTypeMultiSelect, FormFieldTypeSingleChoice, FormFieldTypeSingleChoiceSpaced:
if !allValid(f, value) {
return ErrUnknownOpitonProvided
}

View file

@ -312,7 +312,7 @@ templ fieldSettingsConfiguration(form frm.Form, field types.FormField) {
autocomplete="off"
_={ fmt.Sprintf("on keyup debounced at 600ms trigger '%s'", FieldsFormUpdateEvent) }
/>
case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect, types.FormFieldTypeSingleChoice:
case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect, types.FormFieldTypeSingleChoice, types.FormFieldTypeSingleChoiceSpaced:
<div class="pt-3">
<label for={ fields.FieldName(field, "", "options") } class="pr-1">
Options

View file

@ -1052,7 +1052,7 @@ func fieldSettingsConfiguration(form frm.Form, field types.FormField) templ.Comp
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect, types.FormFieldTypeSingleChoice:
case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect, types.FormFieldTypeSingleChoice, types.FormFieldTypeSingleChoiceSpaced:
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "<div class=\"pt-3\"><label for=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err

View file

@ -40,7 +40,7 @@ templ FieldTypeIcon(fieldType types.FormFieldType) {
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"></path>
</svg>
case int(types.FormFieldTypeSingleChoice):
case int(types.FormFieldTypeSingleChoice), int(types.FormFieldTypeSingleChoiceSpaced):
<!-- heroicons: outline star -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 0 1 1.04 0l2.125 5.111a.563.563 0 0 0 .475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 0 0-.182.557l1.285 5.385a.562.562 0 0 1-.84.61l-4.725-2.885a.562.562 0 0 0-.586 0L6.982 20.54a.562.562 0 0 1-.84-.61l1.285-5.386a.562.562 0 0 0-.182-.557l-4.204-3.602a.562.562 0 0 1 .321-.988l5.518-.442a.563.563 0 0 0 .475-.345L11.48 3.5Z"></path>
@ -60,6 +60,8 @@ templ View(field types.FormField) {
@selectView(field)
case types.FormFieldTypeSingleChoice:
@SingleChoice(field)
case types.FormFieldTypeSingleChoiceSpaced:
@SingleChoiceSpaced(field)
}
}
@ -139,6 +141,8 @@ templ FormFieldTypeLabel(fieldType types.FormFieldType) {
Multi select
case int(types.FormFieldTypeSingleChoice):
Single Choice
case int(types.FormFieldTypeSingleChoiceSpaced):
Single Choice (spaced)
}
</label>
</div>

View file

@ -152,7 +152,7 @@ func FieldTypeIcon(fieldType types.FormFieldType) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
case int(types.FormFieldTypeSingleChoice):
case int(types.FormFieldTypeSingleChoice), int(types.FormFieldTypeSingleChoiceSpaced):
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<!-- heroicons: outline star --> <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M11.48 3.499a.562.562 0 0 1 1.04 0l2.125 5.111a.563.563 0 0 0 .475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 0 0-.182.557l1.285 5.385a.562.562 0 0 1-.84.61l-4.725-2.885a.562.562 0 0 0-.586 0L6.982 20.54a.562.562 0 0 1-.84-.61l1.285-5.386a.562.562 0 0 0-.182-.557l-4.204-3.602a.562.562 0 0 1 .321-.988l5.518-.442a.563.563 0 0 0 .475-.345L11.48 3.5Z\"></path></svg>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
@ -209,6 +209,11 @@ func View(field types.FormField) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
case types.FormFieldTypeSingleChoiceSpaced:
templ_7745c5c3_Err = SingleChoiceSpaced(field).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
return nil
})
@ -246,7 +251,7 @@ func singleLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 69, Col: 24}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 71, Col: 24}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@ -259,7 +264,7 @@ func singleLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 70, Col: 26}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 72, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@ -272,7 +277,7 @@ func singleLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(field.Placeholder)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 71, Col: 33}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 73, Col: 33}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@ -295,7 +300,7 @@ func singleLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 250ms trigger field_change(field_id: '%s', value: my.value)", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 77, Col: 121}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 79, Col: 121}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@ -308,7 +313,7 @@ func singleLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 80, Col: 73}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 82, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@ -354,7 +359,7 @@ func multiLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 86, Col: 24}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 88, Col: 24}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
@ -367,7 +372,7 @@ func multiLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 87, Col: 26}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 89, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@ -380,7 +385,7 @@ func multiLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(field.Placeholder)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 89, Col: 33}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 91, Col: 33}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
@ -403,7 +408,7 @@ func multiLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 250ms trigger field_change(field_id: '%s', value: my.value)", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 94, Col: 121}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 96, Col: 121}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
@ -416,7 +421,7 @@ func multiLineTextView(field types.FormField) templ.Component {
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 98, Col: 50}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 100, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
@ -474,7 +479,7 @@ func selectView(field types.FormField) templ.Component {
var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 118, Col: 50}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/fields.templ`, Line: 120, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
@ -548,8 +553,13 @@ func FormFieldTypeLabel(fieldType types.FormFieldType) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
case int(types.FormFieldTypeSingleChoiceSpaced):
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "Single Choice (spaced)")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</label></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</label></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View file

@ -33,4 +33,5 @@ Multi-line text
Single select
Multi select
Single Choice
Single Choice (spaced)
</label></div>

View file

@ -6,15 +6,16 @@ import (
"github.com/acaloiaro/frm/types"
)
// SingleChoice is a form input type allowing only a ingle option to be chosen
// SingleChoice is a form input type allowing only a single choice (radio)
templ SingleChoice(field types.FormField) {
@FieldLabel(field)
<div class="w-full">
<div>
<div class="flex join">
for _, option := range field.Options {
<div class="join w-full">
for _, option := range field.Options {
<label class="join-item h-auto flex-grow shrink btn has-[:checked]:bg-sky-400 first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50">
<!-- the input field is hidden with opacity, width, and height, but available for HTML validation when 'required' -->
<input
class="join-item btn checked:bg-none flex-grow first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50"
class="opacity-0 w-0 h-0"
type="radio"
id={ field.ID.String() }
name={ field.ID.String() }
@ -25,14 +26,47 @@ templ SingleChoice(field types.FormField) {
}
_={ fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()) }
/>
{ option.Label }
</label>
}
</div>
if len(field.OptionLabels) > 0 {
<div class="flex flex-grow w-full text-center text-gray-400">
for _, label := range field.OptionLabels {
<div class="w-full first:text-left last:text-right">{ label }</div>
}
</div>
if len(field.OptionLabels) > 0 {
<div class="flex flex-grow w-full text-center text-gray-400">
for _, label := range field.OptionLabels {
<div class="w-full first:text-left last:text-right">{ label }</div>
}
</div>
}
</div>
<div
id={ fmt.Sprintf("errors-%s", field.ID.String()) }
class="text-red-400"
></div>
}
// SingleChoiceSpaced is a form input type allowing only a single choice (radio), spaced out
templ SingleChoiceSpaced(field types.FormField) {
@FieldLabel(field)
<div class="w-full">
<div class="grid grid-cols-1 xl:grid-cols-2 gap-8">
for _, option := range field.Options {
<label class="flex w-auto h-auto btn bg-sky-50 has-[:checked]:bg-sky-400 has-[:checked]:border-sky-500 py-3">
<input
type="radio"
class="peer opacity-0 w-0 h-0"
name={ field.ID.String() }
aria-label={ option.Label }
value={ option.Value }
if field.Required {
required
}
_={ fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()) }
/>
{ option.Label }
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-7 justify-self-end invisible peer-checked:visible bg-sky-200 rounded-full p-1">
<path fill-rule="evenodd" d="M19.916 4.626a.75.75 0 0 1 .208 1.04l-9 13.5a.75.75 0 0 1-1.154.114l-6-6a.75.75 0 0 1 1.06-1.06l5.353 5.353 8.493-12.74a.75.75 0 0 1 1.04-.207Z" clip-rule="evenodd"></path>
</svg>
</label>
}
</div>
</div>

View file

@ -14,7 +14,7 @@ import (
"github.com/acaloiaro/frm/types"
)
// SingleChoice is a form input type allowing only a ingle option to be chosen
// SingleChoice is a form input type allowing only a single choice (radio)
func SingleChoice(field types.FormField) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
@ -40,19 +40,19 @@ func SingleChoice(field types.FormField) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"w-full\"><div><div class=\"flex join\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"w-full\"><div class=\"join w-full\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, option := range field.Options {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<input class=\"join-item btn checked:bg-none flex-grow first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50\" type=\"radio\" id=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<label class=\"join-item h-auto flex-grow shrink btn has-[:checked]:bg-sky-400 first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50\"><!-- the input field is hidden with opacity, width, and height, but available for HTML validation when 'required' --><input class=\"opacity-0 w-0 h-0\" type=\"radio\" id=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 19, Col: 28}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 20, Col: 28}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@ -65,7 +65,7 @@ func SingleChoice(field types.FormField) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 20, Col: 30}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 21, Col: 30}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@ -78,7 +78,7 @@ func SingleChoice(field types.FormField) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(option.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 21, Col: 31}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 22, Col: 31}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@ -91,7 +91,7 @@ func SingleChoice(field types.FormField) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(option.Value)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 22, Col: 26}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 23, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@ -114,64 +114,209 @@ func SingleChoice(field types.FormField) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 26, Col: 107}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 27, Col: 107}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(option.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 29, Col: 19}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</label>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(field.OptionLabels) > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"flex flex-grow w-full text-center text-gray-400\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"flex flex-grow w-full text-center text-gray-400\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, label := range field.OptionLabels {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"w-full first:text-left last:text-right\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"w-full first:text-left last:text-right\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(label)
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 33, Col: 65}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 36, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div></div><div id=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div><div id=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 40, Col: 50}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 42, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" class=\"text-red-400\"></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" class=\"text-red-400\"></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
// SingleChoiceSpaced is a form input type allowing only a single choice (radio), spaced out
func SingleChoiceSpaced(field types.FormField) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
if templ_7745c5c3_Var10 == nil {
templ_7745c5c3_Var10 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = FieldLabel(field).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<div class=\"w-full\"><div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, option := range field.Options {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<label class=\"flex w-auto h-auto btn bg-sky-50 has-[:checked]:bg-sky-400 has-[:checked]:border-sky-500 py-3\"><input type=\"radio\" class=\"peer opacity-0 w-0 h-0\" name=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 57, Col: 30}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" aria-label=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(option.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 58, Col: 31}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(option.Value)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 59, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if field.Required {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " required")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " _=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 63, Col: 107}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\"> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(option.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 65, Col: 19}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-7 justify-self-end invisible peer-checked:visible bg-sky-200 rounded-full p-1\"><path fill-rule=\"evenodd\" d=\"M19.916 4.626a.75.75 0 0 1 .208 1.04l-9 13.5a.75.75 0 0 1-1.154.114l-6-6a.75.75 0 0 1 1.06-1.06l5.353 5.353 8.493-12.74a.75.75 0 0 1 1.04-.207Z\" clip-rule=\"evenodd\"></path></svg></label>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</div></div><div id=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("errors-%s", field.ID.String()))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/fields/single_choice.templ`, Line: 74, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" class=\"text-red-400\"></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View file

@ -1,16 +1,28 @@
<div class=\"w-full\"><div><div class=\"flex join\">
<input class=\"join-item btn checked:bg-none flex-grow first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50\" type=\"radio\" id=\"
<div class=\"w-full\"><div class=\"join w-full\">
<label class=\"join-item h-auto flex-grow shrink btn has-[:checked]:bg-sky-400 first:border-x-0 last:border-r-0 border-y-0 border-black bg-sky-50\"><!-- the input field is hidden with opacity, width, and height, but available for HTML validation when 'required' --><input class=\"opacity-0 w-0 h-0\" type=\"radio\" id=\"
\" name=\"
\" aria-label=\"
\" value=\"
\"
required
_=\"
\">
\">
</label>
</div>
<div class=\"flex flex-grow w-full text-center text-gray-400\">
<div class=\"w-full first:text-left last:text-right\">
</div>
</div>
</div><div id=\"
\" class=\"text-red-400\"></div>
<div class=\"w-full\"><div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">
<label class=\"flex w-auto h-auto btn bg-sky-50 has-[:checked]:bg-sky-400 has-[:checked]:border-sky-500 py-3\"><input type=\"radio\" class=\"peer opacity-0 w-0 h-0\" name=\"
\" aria-label=\"
\" value=\"
\"
required
_=\"
\">
<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-7 justify-self-end invisible peer-checked:visible bg-sky-200 rounded-full p-1\"><path fill-rule=\"evenodd\" d=\"M19.916 4.626a.75.75 0 0 1 .208 1.04l-9 13.5a.75.75 0 0 1-1.154.114l-6-6a.75.75 0 0 1 1.06-1.06l5.353 5.353 8.493-12.74a.75.75 0 0 1 1.04-.207Z\" clip-rule=\"evenodd\"></path></svg></label>
</div></div><div id=\"
\" class=\"text-red-400\"></div>