diff options
Diffstat (limited to 'packages/web-util/src/forms/InputChoiceHorizontal.tsx')
-rw-r--r-- | packages/web-util/src/forms/InputChoiceHorizontal.tsx | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/packages/web-util/src/forms/InputChoiceHorizontal.tsx b/packages/web-util/src/forms/InputChoiceHorizontal.tsx new file mode 100644 index 000000000..82a7c3115 --- /dev/null +++ b/packages/web-util/src/forms/InputChoiceHorizontal.tsx @@ -0,0 +1,81 @@ +import { TranslatedString } from "@gnu-taler/taler-util"; +import { Fragment, VNode, h } from "preact"; +import { UIFormProps } from "./FormProvider.js"; +import { LabelWithTooltipMaybeRequired } from "./InputLine.js"; +import { useField } from "./useField.js"; +import { noHandlerPropsAndNoContextForField } from "./InputArray.js"; + +export interface ChoiceH<V> { + label: TranslatedString; + value: V; +} + +export function InputChoiceHorizontal<T extends object, K extends keyof T>( + props: { + choices: ChoiceH<T[K]>[]; + } & UIFormProps<T, K>, +): VNode { + const { choices, label, tooltip, help, required } = props; + //FIXME: remove deprecated + const fieldCtx = useField<T, K>(props.name); + const { value, onChange, state } = + props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name); + if (state.hidden) { + return <Fragment />; + } + + return ( + <div class="sm:col-span-6"> + <LabelWithTooltipMaybeRequired + label={label} + required={required} + tooltip={tooltip} + /> + <fieldset class="mt-2"> + <div class="isolate inline-flex rounded-md shadow-sm"> + {choices.map((choice, idx) => { + const isFirst = idx === 0; + const isLast = idx === choices.length - 1; + let clazz = + "relative inline-flex items-center px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 focus:z-10"; + if (choice.value === value) { + clazz += + " text-white bg-indigo-600 hover:bg-indigo-500 ring-2 ring-indigo-600 hover:ring-indigo-500"; + } else { + clazz += " hover:bg-gray-100 border-gray-300"; + } + if (isFirst) { + clazz += " rounded-l-md"; + } else { + clazz += " -ml-px"; + } + if (isLast) { + clazz += " rounded-r-md"; + } + return ( + <button + type="button" + key={idx} + disabled={state.disabled} + label={choice.label} + class={clazz} + onClick={(e) => { + onChange( + (value === choice.value ? undefined : choice.value) as any, + ); + }} + > + {choice.label} + </button> + ); + })} + </div> + </fieldset> + {help && ( + <p class="mt-2 text-sm text-gray-500" id="email-description"> + {help} + </p> + )} + </div> + ); +} |