feat: add horizontal radio

This commit is contained in:
David Nguyen
2025-10-15 11:17:57 +11:00
parent f48813bb3c
commit a26a740fe5
11 changed files with 196 additions and 58 deletions

View File

@ -127,12 +127,12 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
const distributionMethod = watch('meta.distributionMethod'); const distributionMethod = watch('meta.distributionMethod');
const everySignerHasSignature = useMemo( const recipientsMissingSignatureFields = useMemo(
() => () =>
envelope.recipients envelope.recipients.filter(
.filter((recipient) => recipient.role === RecipientRole.SIGNER) (recipient) =>
.every((recipient) => recipient.role === RecipientRole.SIGNER &&
envelope.fields.some( !envelope.fields.some(
(field) => field.type === FieldType.SIGNATURE && field.recipientId === recipient.id, (field) => field.type === FieldType.SIGNATURE && field.recipientId === recipient.id,
), ),
), ),
@ -178,7 +178,7 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
<Trans>Recipients will be able to sign the document once sent</Trans> <Trans>Recipients will be able to sign the document once sent</Trans>
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
{everySignerHasSignature ? ( {recipientsMissingSignatureFields.length === 0 ? (
<Form {...form}> <Form {...form}>
<form onSubmit={handleSubmit(onFormSubmit)}> <form onSubmit={handleSubmit(onFormSubmit)}>
<fieldset disabled={isSubmitting}> <fieldset disabled={isSubmitting}>
@ -350,6 +350,8 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
</div> </div>
) : ( ) : (
<ul className="text-muted-foreground divide-y"> <ul className="text-muted-foreground divide-y">
{/* Todo: Envelopes - I don't think this section shows up */}
{recipients.length === 0 && ( {recipients.length === 0 && (
<li className="flex flex-col items-center justify-center py-6 text-sm"> <li className="flex flex-col items-center justify-center py-6 text-sm">
<Trans>No recipients</Trans> <Trans>No recipients</Trans>
@ -427,10 +429,13 @@ export const EnvelopeDistributeDialog = ({ envelope, trigger }: EnvelopeDistribu
<> <>
<Alert variant="warning"> <Alert variant="warning">
<AlertDescription> <AlertDescription>
<Trans> <Trans>The following signers are missing signature fields:</Trans>
Some signers have not been assigned a signature field. Please assign at least 1
signature field to each signer before proceeding. <ul className="ml-2 mt-1 list-inside list-disc">
</Trans> {recipientsMissingSignatureFields.map((recipient) => (
<li key={recipient.id}>{recipient.email}</li>
))}
</ul>
</AlertDescription> </AlertDescription>
</Alert> </Alert>

View File

@ -1,15 +1,32 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { Trans } from '@lingui/react/macro'; import { Trans, useLingui } from '@lingui/react/macro';
import { PlusIcon, Trash } from 'lucide-react'; import { PlusIcon, Trash } from 'lucide-react';
import { useForm, useWatch } from 'react-hook-form'; import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod'; import type { z } from 'zod';
import { type TRadioFieldMeta as RadioFieldMeta } from '@documenso/lib/types/field-meta'; import {
type TRadioFieldMeta as RadioFieldMeta,
ZRadioFieldMeta,
} from '@documenso/lib/types/field-meta';
import { Checkbox } from '@documenso/ui/primitives/checkbox'; import { Checkbox } from '@documenso/ui/primitives/checkbox';
import { Form, FormControl, FormField, FormItem } from '@documenso/ui/primitives/form/form'; import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@documenso/ui/primitives/form/form';
import { Input } from '@documenso/ui/primitives/input'; import { Input } from '@documenso/ui/primitives/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@documenso/ui/primitives/select';
import { Separator } from '@documenso/ui/primitives/separator'; import { Separator } from '@documenso/ui/primitives/separator';
import { import {
@ -17,18 +34,13 @@ import {
EditorGenericRequiredField, EditorGenericRequiredField,
} from './editor-field-generic-field-forms'; } from './editor-field-generic-field-forms';
const ZRadioFieldFormSchema = z const ZRadioFieldFormSchema = ZRadioFieldMeta.pick({
.object({ label: true,
label: z.string().optional(), direction: true,
values: z values: true,
.object({ id: z.number(), checked: z.boolean(), value: z.string() }) required: true,
.array() readOnly: true,
.min(1) }).refine(
.optional(),
required: z.boolean().optional(),
readOnly: z.boolean().optional(),
})
.refine(
(data) => { (data) => {
// There cannot be more than one checked option // There cannot be more than one checked option
if (data.values) { if (data.values) {
@ -41,7 +53,7 @@ const ZRadioFieldFormSchema = z
message: 'There cannot be more than one checked option', message: 'There cannot be more than one checked option',
path: ['values'], path: ['values'],
}, },
); );
type TRadioFieldFormSchema = z.infer<typeof ZRadioFieldFormSchema>; type TRadioFieldFormSchema = z.infer<typeof ZRadioFieldFormSchema>;
@ -53,9 +65,12 @@ export type EditorFieldRadioFormProps = {
export const EditorFieldRadioForm = ({ export const EditorFieldRadioForm = ({
value = { value = {
type: 'radio', type: 'radio',
direction: 'vertical',
}, },
onValueChange, onValueChange,
}: EditorFieldRadioFormProps) => { }: EditorFieldRadioFormProps) => {
const { t } = useLingui();
const form = useForm<TRadioFieldFormSchema>({ const form = useForm<TRadioFieldFormSchema>({
resolver: zodResolver(ZRadioFieldFormSchema), resolver: zodResolver(ZRadioFieldFormSchema),
mode: 'onChange', mode: 'onChange',
@ -64,6 +79,7 @@ export const EditorFieldRadioForm = ({
values: value.values || [{ id: 1, checked: false, value: 'Default value' }], values: value.values || [{ id: 1, checked: false, value: 'Default value' }],
required: value.required || false, required: value.required || false,
readOnly: value.readOnly || false, readOnly: value.readOnly || false,
direction: value.direction || 'vertical',
}, },
}); });
@ -107,7 +123,35 @@ export const EditorFieldRadioForm = ({
return ( return (
<Form {...form}> <Form {...form}>
<form> <form>
<fieldset className="flex flex-col gap-2 pb-2"> <fieldset className="flex flex-col gap-2">
<FormField
control={form.control}
name="direction"
render={({ field }) => (
<FormItem>
<FormLabel>
<Trans>Direction</Trans>
</FormLabel>
<FormControl>
<Select value={field.value} onValueChange={field.onChange}>
<SelectTrigger className="text-muted-foreground bg-background w-full">
<SelectValue placeholder={t`Select direction`} />
</SelectTrigger>
<SelectContent position="popper">
<SelectItem value="vertical">
<Trans>Vertical</Trans>
</SelectItem>
<SelectItem value="horizontal">
<Trans>Horizontal</Trans>
</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<EditorGenericRequiredField formControl={form.control} /> <EditorGenericRequiredField formControl={form.control} />
<EditorGenericReadOnlyField formControl={form.control} /> <EditorGenericReadOnlyField formControl={form.control} />

View File

@ -96,7 +96,7 @@ export const EnvelopeEditorFieldDragDrop = ({
selectedRecipientId, selectedRecipientId,
selectedEnvelopeItemId, selectedEnvelopeItemId,
}: EnvelopeEditorFieldDragDropProps) => { }: EnvelopeEditorFieldDragDropProps) => {
const { envelope, editorFields, isTemplate } = useCurrentEnvelopeEditor(); const { envelope, editorFields, isTemplate, getRecipientColorKey } = useCurrentEnvelopeEditor();
const { t } = useLingui(); const { t } = useLingui();
@ -262,6 +262,10 @@ export const EnvelopeEditorFieldDragDrop = ({
}; };
}, [onMouseClick, onMouseMove, selectedField]); }, [onMouseClick, onMouseMove, selectedField]);
const selectedRecipientColor = useMemo(() => {
return selectedRecipientId ? getRecipientColorKey(selectedRecipientId) : 'green';
}, [selectedRecipientId, getRecipientColorKey]);
return ( return (
<> <>
<div className="grid grid-cols-2 gap-x-2 gap-y-2.5"> <div className="grid grid-cols-2 gap-x-2 gap-y-2.5">
@ -273,12 +277,23 @@ export const EnvelopeEditorFieldDragDrop = ({
onClick={() => setSelectedField(field.type)} onClick={() => setSelectedField(field.type)}
onMouseDown={() => setSelectedField(field.type)} onMouseDown={() => setSelectedField(field.type)}
data-selected={selectedField === field.type ? true : undefined} data-selected={selectedField === field.type ? true : undefined}
className="group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-gray-200 px-4 transition-colors hover:border-blue-300 hover:bg-blue-50" className={cn(
'group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-gray-200 px-4 transition-colors',
RECIPIENT_COLOR_STYLES[selectedRecipientColor].fieldButton,
)}
> >
<p <p
className={cn( className={cn(
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
field.className, field.className,
{
'group-hover:text-recipient-green': selectedRecipientColor === 'green',
'group-hover:text-recipient-blue': selectedRecipientColor === 'blue',
'group-hover:text-recipient-purple': selectedRecipientColor === 'purple',
'group-hover:text-recipient-orange': selectedRecipientColor === 'orange',
'group-hover:text-recipient-yellow': selectedRecipientColor === 'yellow',
'group-hover:text-recipient-pink': selectedRecipientColor === 'pink',
},
)} )}
> >
{field.type !== FieldType.SIGNATURE && <field.icon className="h-4 w-4" />} {field.type !== FieldType.SIGNATURE && <field.icon className="h-4 w-4" />}
@ -292,8 +307,7 @@ export const EnvelopeEditorFieldDragDrop = ({
<div <div
className={cn( className={cn(
'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center rounded-[2px] bg-white ring-2 transition duration-200 [container-type:size]', 'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center rounded-[2px] bg-white ring-2 transition duration-200 [container-type:size]',
// selectedSignerStyles?.base, RECIPIENT_COLOR_STYLES[selectedRecipientColor].base,
RECIPIENT_COLOR_STYLES.yellow.base, // Todo: Envelopes
{ {
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds, '-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
'dark:text-black/60': isFieldWithinBounds, 'dark:text-black/60': isFieldWithinBounds,

View File

@ -224,8 +224,12 @@ export const EnvelopeEditorPageUpload = () => {
<div className="mx-auto max-w-4xl space-y-6 p-8"> <div className="mx-auto max-w-4xl space-y-6 p-8">
<Card backdropBlur={false} className="border"> <Card backdropBlur={false} className="border">
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<CardTitle>Documents</CardTitle> <CardTitle>
<CardDescription>Add and configure multiple documents</CardDescription> <Trans>Documents</Trans>
</CardTitle>
<CardDescription>
<Trans>Add and configure multiple documents</Trans>
</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>

View File

@ -128,6 +128,18 @@ export default function EnvelopeEditor() {
} }
}; };
// Watch the URL params and setStep if the step changes.
useEffect(() => {
const stepParam = searchParams.get('step') || envelopeEditorSteps[0].id;
const foundStep = envelopeEditorSteps.find((step) => step.id === stepParam);
if (foundStep && foundStep.id !== currentStep) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
navigateToStep(foundStep.id as EnvelopeEditorStep);
}
}, [searchParams]);
useEffect(() => { useEffect(() => {
if (!isAutosaving) { if (!isAutosaving) {
setIsStepLoading(false); setIsStepLoading(false);
@ -340,7 +352,6 @@ export default function EnvelopeEditor() {
{/* Main Content - Changes based on current step */} {/* Main Content - Changes based on current step */}
<div className="flex-1 overflow-y-auto"> <div className="flex-1 overflow-y-auto">
<p>{isAutosaving ? 'Autosaving...' : 'Not autosaving'}</p>
<AnimateGenericFadeInOut key={currentStep}> <AnimateGenericFadeInOut key={currentStep}>
{match({ currentStep, isStepLoading }) {match({ currentStep, isStepLoading })
.with({ isStepLoading: true }, () => <SpinnerBox className="py-32" />) .with({ isStepLoading: true }, () => <SpinnerBox className="py-32" />)

View File

@ -135,7 +135,12 @@ export const EnvelopeEditorProvider = ({
}); });
const envelopeRecipientSetMutationQuery = trpc.envelope.recipient.set.useMutation({ const envelopeRecipientSetMutationQuery = trpc.envelope.recipient.set.useMutation({
onSuccess: () => { onSuccess: ({ recipients }) => {
setEnvelope((prev) => ({
...prev,
recipients,
}));
setAutosaveError(false); setAutosaveError(false);
}, },
onError: (error) => { onError: (error) => {
@ -215,14 +220,15 @@ export const EnvelopeEditorProvider = ({
const getRecipientColorKey = useCallback( const getRecipientColorKey = useCallback(
(recipientId: number) => { (recipientId: number) => {
// Todo: Envelopes - Local recipients
const recipientIndex = envelope.recipients.findIndex( const recipientIndex = envelope.recipients.findIndex(
(recipient) => recipient.id === recipientId, (recipient) => recipient.id === recipientId,
); );
return AVAILABLE_RECIPIENT_COLORS[Math.max(recipientIndex, 0)]; return AVAILABLE_RECIPIENT_COLORS[
Math.max(recipientIndex, 0) % AVAILABLE_RECIPIENT_COLORS.length
];
}, },
[envelope.recipients], // Todo: Envelopes - Local recipients [envelope.recipients],
); );
const { refetch: reloadEnvelope, isLoading: isReloadingEnvelope } = trpc.envelope.get.useQuery( const { refetch: reloadEnvelope, isLoading: isReloadingEnvelope } = trpc.envelope.get.useQuery(

View File

@ -81,6 +81,7 @@ export const ZRadioFieldMeta = ZBaseFieldMeta.extend({
}), }),
) )
.optional(), .optional(),
direction: z.enum(['vertical', 'horizontal']).optional().default('vertical'),
}); });
export type TRadioFieldMeta = z.infer<typeof ZRadioFieldMeta>; export type TRadioFieldMeta = z.infer<typeof ZRadioFieldMeta>;
@ -278,6 +279,7 @@ export const FIELD_RADIO_META_DEFAULT_VALUES: TRadioFieldMeta = {
values: [{ id: 1, checked: false, value: '' }], values: [{ id: 1, checked: false, value: '' }],
required: false, required: false,
readOnly: false, readOnly: false,
direction: 'vertical',
}; };
export const FIELD_CHECKBOX_META_DEFAULT_VALUES: TCheckboxFieldMeta = { export const FIELD_CHECKBOX_META_DEFAULT_VALUES: TCheckboxFieldMeta = {

View File

@ -107,6 +107,11 @@ type CalculateMultiItemPositionOptions = {
*/ */
fieldPadding: number; fieldPadding: number;
/**
* The direction of the items.
*/
direction: 'horizontal' | 'vertical';
type: 'checkbox' | 'radio'; type: 'checkbox' | 'radio';
}; };
@ -122,6 +127,7 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
itemSize, itemSize,
spacingBetweenItemAndText, spacingBetweenItemAndText,
fieldPadding, fieldPadding,
direction,
type, type,
} = options; } = options;
@ -130,6 +136,39 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
const innerFieldX = fieldPadding; const innerFieldX = fieldPadding;
const innerFieldY = fieldPadding; const innerFieldY = fieldPadding;
if (direction === 'horizontal') {
const itemHeight = innerFieldHeight;
const itemWidth = innerFieldWidth / itemCount;
const y = innerFieldY;
const x = itemIndex * itemWidth + innerFieldX;
let itemInputY = y + itemHeight / 2 - itemSize / 2;
let itemInputX = x;
// We need a little different logic to center the radio circle icon.
if (type === 'radio') {
itemInputX = x + itemSize / 2;
itemInputY = y + itemHeight / 2;
}
const textX = x + itemSize + spacingBetweenItemAndText;
const textY = y;
// Multiplied by 2 for extra padding on the right hand side of the text and the next item.
const textWidth = itemWidth - itemSize - spacingBetweenItemAndText * 2;
const textHeight = itemHeight;
return {
itemInputX,
itemInputY,
textX,
textY,
textWidth,
textHeight,
};
}
const itemHeight = innerFieldHeight / itemCount; const itemHeight = innerFieldHeight / itemCount;
const y = itemIndex * itemHeight + innerFieldY; const y = itemIndex * itemHeight + innerFieldY;
@ -137,6 +176,7 @@ export const calculateMultiItemPosition = (options: CalculateMultiItemPositionOp
let itemInputY = y + itemHeight / 2 - itemSize / 2; let itemInputY = y + itemHeight / 2 - itemSize / 2;
let itemInputX = innerFieldX; let itemInputX = innerFieldX;
// We need a little different logic to center the radio circle icon.
if (type === 'radio') { if (type === 'radio') {
itemInputX = innerFieldX + itemSize / 2; itemInputX = innerFieldX + itemSize / 2;
itemInputY = y + itemHeight / 2; itemInputY = y + itemHeight / 2;

View File

@ -26,6 +26,9 @@ export const renderCheckboxFieldElement = (
fieldGroup.add(upsertFieldRect(field, options)); fieldGroup.add(upsertFieldRect(field, options));
const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
const checkboxValues = checkboxMeta?.values || [];
if (isFirstRender) { if (isFirstRender) {
pageLayer.add(fieldGroup); pageLayer.add(fieldGroup);
@ -72,6 +75,7 @@ export const renderCheckboxFieldElement = (
itemSize: checkboxSize, itemSize: checkboxSize,
spacingBetweenItemAndText: spacingBetweenCheckboxAndText, spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
fieldPadding: checkboxFieldPadding, fieldPadding: checkboxFieldPadding,
direction: checkboxMeta?.direction || 'vertical',
type: 'checkbox', type: 'checkbox',
}); });
@ -113,9 +117,6 @@ export const renderCheckboxFieldElement = (
}); });
} }
const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
const checkboxValues = checkboxMeta?.values || [];
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight); const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
checkboxValues.forEach(({ id, value, checked }, index) => { checkboxValues.forEach(({ id, value, checked }, index) => {
@ -128,6 +129,7 @@ export const renderCheckboxFieldElement = (
itemSize: checkboxSize, itemSize: checkboxSize,
spacingBetweenItemAndText: spacingBetweenCheckboxAndText, spacingBetweenItemAndText: spacingBetweenCheckboxAndText,
fieldPadding: checkboxFieldPadding, fieldPadding: checkboxFieldPadding,
direction: checkboxMeta?.direction || 'vertical',
type: 'checkbox', type: 'checkbox',
}); });

View File

@ -26,6 +26,9 @@ export const renderRadioFieldElement = (
fieldGroup.add(upsertFieldRect(field, options)); fieldGroup.add(upsertFieldRect(field, options));
const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
const radioValues = radioMeta?.values || [];
if (isFirstRender) { if (isFirstRender) {
pageLayer.add(fieldGroup); pageLayer.add(fieldGroup);
@ -66,6 +69,7 @@ export const renderRadioFieldElement = (
spacingBetweenItemAndText: spacingBetweenRadioAndText, spacingBetweenItemAndText: spacingBetweenRadioAndText,
fieldPadding: radioFieldPadding, fieldPadding: radioFieldPadding,
type: 'radio', type: 'radio',
direction: radioMeta?.direction || 'vertical',
}); });
circleElement.setAttrs({ circleElement.setAttrs({
@ -104,9 +108,6 @@ export const renderRadioFieldElement = (
}); });
} }
const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
const radioValues = radioMeta?.values || [];
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight); const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
radioValues.forEach(({ value, checked }, index) => { radioValues.forEach(({ value, checked }, index) => {
@ -120,6 +121,7 @@ export const renderRadioFieldElement = (
spacingBetweenItemAndText: spacingBetweenRadioAndText, spacingBetweenItemAndText: spacingBetweenRadioAndText,
fieldPadding: radioFieldPadding, fieldPadding: radioFieldPadding,
type: 'radio', type: 'radio',
direction: radioMeta?.direction || 'vertical',
}); });
// Circle which represents the radio button. // Circle which represents the radio button.

View File

@ -9,6 +9,7 @@ export type RecipientColorStyles = {
base: string; base: string;
baseRing: string; baseRing: string;
baseRingHover: string; baseRingHover: string;
fieldButton: string;
fieldItem: string; fieldItem: string;
fieldItemInitials: string; fieldItemInitials: string;
comboxBoxTrigger: string; comboxBoxTrigger: string;
@ -23,6 +24,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-neutral-400', base: 'ring-neutral-400',
baseRing: 'rgba(176, 176, 176, 1)', baseRing: 'rgba(176, 176, 176, 1)',
baseRingHover: 'rgba(176, 176, 176, 1)', baseRingHover: 'rgba(176, 176, 176, 1)',
fieldButton: 'border-neutral-400 hover:border-neutral-400',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: '', fieldItemInitials: '',
comboxBoxTrigger: comboxBoxTrigger:
@ -34,6 +36,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-green hover:bg-recipient-green/30', base: 'ring-recipient-green hover:bg-recipient-green/30',
baseRing: 'rgba(122, 195, 85, 1)', baseRing: 'rgba(122, 195, 85, 1)',
baseRingHover: 'rgba(122, 195, 85, 0.3)', baseRingHover: 'rgba(122, 195, 85, 0.3)',
fieldButton: 'hover:border-recipient-green hover:bg-recipient-green/30 ',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-green', fieldItemInitials: 'group-hover/field-item:bg-recipient-green',
comboxBoxTrigger: comboxBoxTrigger:
@ -45,6 +48,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-blue hover:bg-recipient-blue/30', base: 'ring-recipient-blue hover:bg-recipient-blue/30',
baseRing: 'rgba(56, 123, 199, 1)', baseRing: 'rgba(56, 123, 199, 1)',
baseRingHover: 'rgba(56, 123, 199, 0.3)', baseRingHover: 'rgba(56, 123, 199, 0.3)',
fieldButton: 'hover:border-recipient-blue hover:bg-recipient-blue/30',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-blue', fieldItemInitials: 'group-hover/field-item:bg-recipient-blue',
comboxBoxTrigger: comboxBoxTrigger:
@ -56,6 +60,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-purple hover:bg-recipient-purple/30', base: 'ring-recipient-purple hover:bg-recipient-purple/30',
baseRing: 'rgba(151, 71, 255, 1)', baseRing: 'rgba(151, 71, 255, 1)',
baseRingHover: 'rgba(151, 71, 255, 0.3)', baseRingHover: 'rgba(151, 71, 255, 0.3)',
fieldButton: 'hover:border-recipient-purple hover:bg-recipient-purple/30',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-purple', fieldItemInitials: 'group-hover/field-item:bg-recipient-purple',
comboxBoxTrigger: comboxBoxTrigger:
@ -67,6 +72,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-orange hover:bg-recipient-orange/30', base: 'ring-recipient-orange hover:bg-recipient-orange/30',
baseRing: 'rgba(246, 159, 30, 1)', baseRing: 'rgba(246, 159, 30, 1)',
baseRingHover: 'rgba(246, 159, 30, 0.3)', baseRingHover: 'rgba(246, 159, 30, 0.3)',
fieldButton: 'hover:border-recipient-orange hover:bg-recipient-orange/30',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-orange', fieldItemInitials: 'group-hover/field-item:bg-recipient-orange',
comboxBoxTrigger: comboxBoxTrigger:
@ -78,6 +84,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-yellow hover:bg-recipient-yellow/30', base: 'ring-recipient-yellow hover:bg-recipient-yellow/30',
baseRing: 'rgba(219, 186, 0, 1)', baseRing: 'rgba(219, 186, 0, 1)',
baseRingHover: 'rgba(219, 186, 0, 0.3)', baseRingHover: 'rgba(219, 186, 0, 0.3)',
fieldButton: 'hover:border-recipient-yellow hover:bg-recipient-yellow/30',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-yellow', fieldItemInitials: 'group-hover/field-item:bg-recipient-yellow',
comboxBoxTrigger: comboxBoxTrigger:
@ -89,6 +96,7 @@ export const RECIPIENT_COLOR_STYLES = {
base: 'ring-recipient-pink hover:bg-recipient-pink/30', base: 'ring-recipient-pink hover:bg-recipient-pink/30',
baseRing: 'rgba(217, 74, 186, 1)', baseRing: 'rgba(217, 74, 186, 1)',
baseRingHover: 'rgba(217, 74, 186, 0.3)', baseRingHover: 'rgba(217, 74, 186, 0.3)',
fieldButton: 'hover:border-recipient-pink hover:bg-recipient-pink/30',
fieldItem: 'group/field-item rounded-[2px]', fieldItem: 'group/field-item rounded-[2px]',
fieldItemInitials: 'group-hover/field-item:bg-recipient-pink', fieldItemInitials: 'group-hover/field-item:bg-recipient-pink',
comboxBoxTrigger: comboxBoxTrigger: