Skip to content

Commit

Permalink
redesign insight form, minor ui tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
xvvvyz committed Sep 10, 2024
1 parent cf0e8be commit d34aed5
Show file tree
Hide file tree
Showing 25 changed files with 508 additions and 457 deletions.
44 changes: 31 additions & 13 deletions app/_components/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import Tip from '@/_components/tip';
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
import { forwardRef, InputHTMLAttributes, ReactNode, Ref } from 'react';
import { twMerge } from 'tailwind-merge';

interface CheckboxProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
label?: string;
tooltip?: ReactNode;
inputClassName?: string;
label?: ReactNode;
labelInside?: boolean;
right?: ReactNode;
}

const Checkbox = forwardRef(
(
{ className, label, name, tooltip, ...rest }: CheckboxProps,
{
className,
inputClassName,
label,
labelInside,
name,
right,
...rest
}: CheckboxProps,
ref: Ref<HTMLInputElement>,
) => (
<div className={twMerge('relative', className)}>
<label className="group w-full cursor-pointer">
{label && <span className="label">{label}</span>}
<div className="input group flex items-center justify-between gap-4 pr-2">
{label && !labelInside && <span className="label">{label}</span>}
<div
className={twMerge(
'input group flex items-center justify-between gap-4 pr-2',
inputClassName,
)}
>
<input
className="peer absolute h-6 w-6 opacity-0"
id={name}
Expand All @@ -26,15 +40,19 @@ const Checkbox = forwardRef(
type="checkbox"
{...rest}
/>
<span className="text-fg-4 transition-colors after:content-['No'] peer-checked:text-fg-2 peer-checked:after:content-['Yes']" />
<CheckIcon className="h-5 w-5 stroke-fg-2 opacity-0 transition-opacity peer-checked:opacity-100" />
<div
className={twMerge(
'text-fg-4 transition-colors peer-checked:text-fg-2',
(!label || !labelInside) &&
'after:content-["No"] peer-checked:after:content-["Yes"]',
)}
>
{label && labelInside && label}
</div>
<CheckIcon className="h-5 w-5 shrink-0 stroke-fg-2 opacity-0 transition-opacity peer-checked:opacity-100" />
</div>
</label>
{tooltip && (
<Tip className="absolute right-[0.55rem] top-px" side="left">
{tooltip}
</Tip>
)}
{right && <div className="absolute right-[0.55rem] top-px">{right}</div>}
</div>
),
);
Expand Down
4 changes: 2 additions & 2 deletions app/_components/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const Content = React.forwardRef<
<DropdownMenuPrimitive.Content
align="end"
ref={ref}
sideOffset={7}
sideOffset={0}
className={twMerge(
'z-10 w-60 overflow-hidden rounded border border-alpha-2 bg-bg-3 py-1 drop-shadow',
'z-10 my-1.5 w-60 overflow-hidden rounded border border-alpha-2 bg-bg-3 py-1 drop-shadow',
className,
)}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const EventComment = ({
</div>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="mx-2" sideOffset={4}>
<DropdownMenu.Content>
<DropdownMenuDeleteItem
confirmText="Delete comment"
onConfirm={() => deleteComment(id)}
Expand Down
6 changes: 3 additions & 3 deletions app/_components/event-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ const EventForm = ({
name={`inputs.${i}.0`}
render={({ field }) => (
<Select
className="rounded-r-none border-r-0"
controlClassName="rounded-r-none border-r-0"
inputType="number"
name={field.name}
onBlur={field.onBlur}
Expand All @@ -215,7 +215,7 @@ const EventForm = ({
name={`inputs.${i}.1`}
render={({ field }) => (
<Select
className="rounded-none"
controlClassName="rounded-none"
inputType="number"
name={field.name}
onBlur={field.onBlur}
Expand All @@ -234,7 +234,7 @@ const EventForm = ({
name={`inputs.${i}.2`}
render={({ field }) => (
<Select
className="rounded-l-none border-l-0"
controlClassName="rounded-l-none border-l-0"
inputType="number"
name={field.name}
onBlur={field.onBlur}
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const EventMenu = ({ className, eventId, isModal }: EventMenuProps) => {
)}
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="mx-2" sideOffset={0}>
<DropdownMenu.Content>
<DropdownMenuDeleteItem
confirmText="Delete event"
onConfirm={async () => {
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-type-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const EventTypeMenu = ({
)}
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="mx-2" sideOffset={-2}>
<DropdownMenu.Content className="mr-1.5">
<DropdownMenu.Button
href={`/subjects/${subjectId}/event-types/${eventTypeId}/edit`}
scroll={false}
Expand Down
84 changes: 41 additions & 43 deletions app/_components/event-type-use-template-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,56 +48,54 @@ const EventTypeUseTemplateModal = <T extends Form.FieldValues>({
Selecting a template will overwrite any existing event type
values.
</Modal.Description>
<div className="pt-16 text-left">
<Select
isLoading={isTransitioning}
noOptionsMessage={() => 'No templates.'}
onChange={(t) =>
startTransition(async () => {
const template = t as NonNullable<
ListTemplatesBySubjectIdAndTypeData | ListTemplatesData
>[0];
<Select
controlClassName="pt-16 text-left"
isLoading={isTransitioning}
noOptionsMessage={() => 'No templates.'}
onChange={(t) =>
startTransition(async () => {
const template = t as NonNullable<
ListTemplatesBySubjectIdAndTypeData | ListTemplatesData
>[0];

const { data: templateData } = await getTemplateData(
template.id,
);
const { data: templateData } = await getTemplateData(
template.id,
);

const data =
templateData?.data as EventTypeTemplateDataJson;
const data = templateData?.data as EventTypeTemplateDataJson;

const inputs = availableInputs.filter(({ id }) =>
forceArray(data?.inputIds).includes(id),
);
const inputs = availableInputs.filter(({ id }) =>
forceArray(data?.inputIds).includes(id),
);

form.setValue(
'name' as Form.FieldPath<T>,
template.name as Form.PathValue<T, Form.FieldPath<T>>,
{ shouldDirty: true },
);
form.setValue(
'name' as Form.FieldPath<T>,
template.name as Form.PathValue<T, Form.FieldPath<T>>,
{ shouldDirty: true },
);

form.setValue(
'content' as Form.FieldPath<T>,
(data?.content ?? '') as Form.PathValue<
T,
Form.FieldPath<T>
>,
{ shouldDirty: true },
);
form.setValue(
'content' as Form.FieldPath<T>,
(data?.content ?? '') as Form.PathValue<
T,
Form.FieldPath<T>
>,
{ shouldDirty: true },
);

form.setValue(
'inputs' as Form.FieldPath<T>,
inputs as Form.PathValue<T, Form.FieldPath<T>>,
{ shouldDirty: true },
);
form.setValue(
'inputs' as Form.FieldPath<T>,
inputs as Form.PathValue<T, Form.FieldPath<T>>,
{ shouldDirty: true },
);

toggleOpen();
})
}
options={availableEventTypeTemplates as IOption[]}
placeholder="Select a template…"
value={null}
/>
</div>
toggleOpen();
})
}
options={availableEventTypeTemplates as IOption[]}
placeholder="Select a template…"
value={null}
/>
<Modal.Close asChild onClick={(e) => e.preventDefault()}>
<Button
className="-mb-3 mt-14 w-full justify-center p-0 py-3"
Expand Down
7 changes: 4 additions & 3 deletions app/_components/input-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import IconButton from '@/_components/icon-button';
import Input from '@/_components/input';
import PageModalBackButton from '@/_components/page-modal-back-button';
import Select, { IOption } from '@/_components/select';
import Tip from '@/_components/tip';
import UnsavedChangesBanner from '@/_components/unsaved-changes-banner';
import INPUT_TYPE_LABELS from '@/_constants/constant-input-type-labels';
import InputType from '@/_constants/enum-input-type';
Expand Down Expand Up @@ -264,11 +265,11 @@ const InputForm = ({
</fieldset>
<Checkbox
label="Allow options to be created"
tooltip={
<>
right={
<Tip side="left">
Enable this when you don&rsquo;t know all possible options in
advance.
</>
</Tip>
}
{...form.register('settings.isCreatable')}
/>
Expand Down
2 changes: 1 addition & 1 deletion app/_components/input-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const InputMenu = ({ inputId }: InputMenuProps) => (
</div>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="mx-2" sideOffset={-2}>
<DropdownMenu.Content className="mr-1.5">
<DropdownMenu.Button
href={`/inputs/create/from-input/${inputId}`}
scroll={false}
Expand Down
8 changes: 5 additions & 3 deletions app/_components/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useFormStatus } from 'react-dom';
import { twMerge } from 'tailwind-merge';

interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
inputClassName?: string;
label?: ReactNode;
tooltip?: ReactNode;
}
Expand All @@ -14,18 +15,19 @@ const Input = forwardRef(
className,
disabled,
id,
inputClassName,
label,
type,
name,
tooltip,
type,
...rest
}: InputProps,
ref: Ref<HTMLInputElement>,
) => {
const { pending } = useFormStatus();

return (
<div className="group relative w-full">
<div className={twMerge('group relative w-full', className)}>
<div className="flex justify-between">
{label && (
<label className="label" htmlFor={id ?? name}>
Expand All @@ -40,7 +42,7 @@ const Input = forwardRef(
</div>
<input
autoComplete="off"
className={twMerge('input', className)}
className={twMerge('input', inputClassName)}
disabled={disabled || pending}
id={id ?? name}
name={name}
Expand Down
Loading

0 comments on commit d34aed5

Please sign in to comment.