mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-19 13:55:40 -04:00
[ENG-1694] Dialogs visual improvements (#2684)
Improve how dialogs look + add location modal improvements
This commit is contained in:
@@ -71,7 +71,6 @@ const ExifMediaData = (data: ExifMetadata) => {
|
||||
const platform = usePlatform();
|
||||
const { t } = useLocale();
|
||||
const coordinatesFormat = useUnitFormatStore().coordinatesFormat;
|
||||
const showMoreInfo = useSelector(explorerStore, (s) => s.showMoreInfo);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -22,8 +22,8 @@ const AddDeviceDialog = ({ node, ...dialogProps }: Props) => {
|
||||
icon={
|
||||
<Icon name={hardwareModelToIcon(node?.device_model as HardwareModel)} size={28} />
|
||||
}
|
||||
ctaLabel="Add"
|
||||
closeLabel="Close"
|
||||
closeLabel={t('cancel')}
|
||||
ctaLabel={t('add')}
|
||||
>
|
||||
<div className="mt-4 flex flex-col items-center">
|
||||
<div className="size-32 rounded-lg bg-gray-600 shadow-lg" />
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
useZodForm
|
||||
} from '@sd/client';
|
||||
import {
|
||||
CheckBox,
|
||||
Dialog,
|
||||
ErrorMessage,
|
||||
Label,
|
||||
@@ -160,7 +159,12 @@ export const AddLocationDialog = ({
|
||||
}
|
||||
|
||||
if (message && get(form.formState.errors, REMOTE_ERROR_FORM_FIELD)?.message !== message)
|
||||
form.setError(REMOTE_ERROR_FORM_FIELD, { type: 'remote', message: message });
|
||||
form.setError(REMOTE_ERROR_FORM_FIELD, {
|
||||
type: 'remote',
|
||||
message: message.startsWith('location already exists')
|
||||
? 'This location has already been added'
|
||||
: message
|
||||
});
|
||||
return true;
|
||||
},
|
||||
[form]
|
||||
@@ -220,40 +224,20 @@ export const AddLocationDialog = ({
|
||||
dialog={useDialog(dialogProps)}
|
||||
icon={<Icon name="NewLocation" size={28} />}
|
||||
onSubmit={onSubmit}
|
||||
closeLabel={t('close')}
|
||||
closeLabel={t('cancel')}
|
||||
ctaLabel={t('add')}
|
||||
formClassName="min-w-[375px]"
|
||||
formClassName="w-[375px]"
|
||||
errorMessageException={t('location_is_already_linked')}
|
||||
description={platform.platform === 'web' ? t('new_location_web_description') : ''}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<ErrorMessage
|
||||
name={REMOTE_ERROR_FORM_FIELD}
|
||||
variant="large"
|
||||
className="mb-4 mt-2"
|
||||
/>
|
||||
<ErrorMessage name={REMOTE_ERROR_FORM_FIELD} variant="large" className="mb-4" />
|
||||
|
||||
<LocationPathInputField {...form.register('path')} />
|
||||
<p className="mb-1 text-sm font-medium text-ink">{t('path')}</p>
|
||||
<LocationPathInputField className="mb-1.5" {...form.register('path')} />
|
||||
|
||||
<input type="hidden" {...form.register('method')} />
|
||||
|
||||
<div className="mb-6 flex items-center gap-2">
|
||||
<Controller
|
||||
name="shouldRedirect"
|
||||
render={({ field }) => (
|
||||
<RadixCheckbox
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
className="text-xs font-semibold"
|
||||
/>
|
||||
)}
|
||||
control={form.control}
|
||||
/>
|
||||
<Label className="text-xs font-semibold">
|
||||
{t('open_new_location_once_added')}
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<Accordion title={t('advanced_settings')}>
|
||||
<Controller
|
||||
name="indexerRulesIds"
|
||||
@@ -269,6 +253,23 @@ export const AddLocationDialog = ({
|
||||
control={form.control}
|
||||
/>
|
||||
</Accordion>
|
||||
|
||||
<div className="mt-4 flex items-center gap-1.5">
|
||||
<Controller
|
||||
name="shouldRedirect"
|
||||
render={({ field }) => (
|
||||
<RadixCheckbox
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
className="size-4 text-xs font-semibold"
|
||||
/>
|
||||
)}
|
||||
control={form.control}
|
||||
/>
|
||||
<Label className="text-xs font-semibold">
|
||||
{t('open_new_location_once_added')}
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@ import { openDirectoryPickerDialog } from './openDirectoryPickerDialog';
|
||||
|
||||
export const LocationPathInputField = forwardRef<
|
||||
HTMLInputElement,
|
||||
Omit<InputFieldProps, 'onClick' | 'readOnly' | 'className'>
|
||||
Omit<InputFieldProps, 'onClick' | 'readOnly'>
|
||||
>((props, ref) => {
|
||||
const platform = usePlatform();
|
||||
const form = useFormContext();
|
||||
@@ -31,7 +31,7 @@ export const LocationPathInputField = forwardRef<
|
||||
.catch((error) => toast.error(t('error_message', { error: String(error) })))
|
||||
}
|
||||
readOnly={platform.platform !== 'web'}
|
||||
className={clsx('mb-3', platform.platform === 'web' || 'cursor-pointer')}
|
||||
className={clsx(props.className, platform.platform === 'web' || 'cursor-pointer')}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CaretDown } from '@phosphor-icons/react';
|
||||
import clsx from 'clsx';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { PropsWithChildren, useState } from 'react';
|
||||
|
||||
interface Props {
|
||||
@@ -13,8 +14,8 @@ interface Props {
|
||||
|
||||
const styles = {
|
||||
default: {
|
||||
container: 'flex flex-col gap-1 rounded-b-none px-3 py-2 bg-app-box',
|
||||
title: 'flex flex-row items-center justify-between px-3 py-2',
|
||||
container: 'flex flex-col gap-1 rounded-b-none bg-app-box',
|
||||
title: 'flex flex-row items-center justify-between',
|
||||
box: 'rounded-md border border-app-line bg-app-darkBox'
|
||||
},
|
||||
apple: {
|
||||
@@ -28,13 +29,13 @@ export const Accordion = ({ isOpen = false, ...props }: PropsWithChildren<Props>
|
||||
const [toggle, setToggle] = useState(isOpen);
|
||||
const variant = styles[props.variant ?? 'default'];
|
||||
return (
|
||||
<div className={clsx(variant.box, props.className)}>
|
||||
<div className={clsx(variant.box, props.className, 'overflow-hidden')}>
|
||||
<div
|
||||
onClick={() => {
|
||||
setToggle((t) => !t);
|
||||
props.onToggle?.(!toggle);
|
||||
}}
|
||||
className={variant.title}
|
||||
className={clsx(variant.title, 'cursor-pointer px-3 py-2')}
|
||||
>
|
||||
<p className="text-xs">{props.title}</p>
|
||||
<CaretDown
|
||||
@@ -45,7 +46,19 @@ export const Accordion = ({ isOpen = false, ...props }: PropsWithChildren<Props>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{(isOpen || toggle) && <div className={variant.container}>{props.children}</div>}
|
||||
<AnimatePresence>
|
||||
{(isOpen || toggle) && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className={variant.container}
|
||||
>
|
||||
<div className="px-3 py-2">{props.children}</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -31,12 +31,12 @@ export interface RadixCheckboxProps extends ComponentProps<typeof Checkbox.Root>
|
||||
export const RadixCheckbox = ({ className, labelClassName, ...props }: RadixCheckboxProps) => (
|
||||
<div className={clsx('flex items-center', className)}>
|
||||
<Checkbox.Root
|
||||
className="flex size-[17px] shrink-0 items-center justify-center rounded-[4px] border border-gray-300/10 bg-app-selected radix-state-checked:bg-accent"
|
||||
className="flex size-[15px] shrink-0 items-center justify-center rounded-[4px] border border-gray-300/10 bg-app-selected radix-state-checked:bg-accent"
|
||||
id={props.name}
|
||||
{...props}
|
||||
>
|
||||
<Checkbox.Indicator className="text-white">
|
||||
<Check weight="bold" size={14} />
|
||||
<Check weight="bold" size={12} />
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox.Root>
|
||||
{props.label && (
|
||||
|
||||
@@ -286,12 +286,11 @@ export function Dialog<S extends FieldValues>({
|
||||
props.formClassName
|
||||
)}
|
||||
>
|
||||
<RDialog.Title className="flex items-center gap-2.5 border-b border-app-line bg-app-input/60 p-3 font-bold">
|
||||
{props.icon && props.icon}
|
||||
{props.title}
|
||||
</RDialog.Title>
|
||||
<div className="p-5">
|
||||
<RDialog.Title className="mb-3 flex items-center gap-2.5 font-bold">
|
||||
{props.icon && props.icon}
|
||||
{props.title}
|
||||
</RDialog.Title>
|
||||
|
||||
{props.description && (
|
||||
<RDialog.Description className="mb-2 text-sm text-ink-dull">
|
||||
{props.description}
|
||||
|
||||
Reference in New Issue
Block a user