What could be going on here? #2747
Answered
by
benoitgrelard
StephenSHorton
asked this question in
Help
-
Screen.Recording.2024-03-01.at.3.05.10.PM.movIs this an outline appearing on my sheet content? Sheet dialog code
import * as SheetPrimitive from '@radix-ui/react-dialog'
import { cva, type VariantProps } from 'class-variance-authority'
import * as React from 'react'
import { cn } from '@/lib/utils'
const Sheet = SheetPrimitive.Root
const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close
const SheetPortal = SheetPrimitive.Portal
const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
'fixed inset-0 z-50 bg-[#94A3B866] backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 dark:bg-black/20',
className,
)}
{...props}
ref={ref}
/>
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva(
'flex flex-col fixed z-50 gap-3 bg-surface-secondary shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
{
variants: {
side: {
top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
bottom:
'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left',
right:
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right',
},
},
defaultVariants: {
side: 'right',
},
},
)
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = 'right', className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children}
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
'flex flex-col space-y-1 bg-surface-secondary text-center sm:text-left',
className,
)}
{...props}
/>
)
SheetHeader.displayName = 'SheetHeader'
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
'mt-auto flex items-center justify-end gap-3 bg-surface-secondary',
className,
)}
{...props}
/>
)
SheetFooter.displayName = 'SheetFooter'
const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn('typography-h2', className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn('text-text-secondary', className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
export {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetOverlay,
SheetPortal,
SheetTitle,
SheetTrigger,
} Form code
import { zodResolver } from '@hookform/resolvers/zod'
import { useRef } from 'react'
import { useForm } from 'react-hook-form'
import { create, InstanceProps } from 'react-modal-promise'
import { toast } from 'sonner'
import { z } from 'zod'
import { AdminRoles, Roles, UpdateUser, UserSchema } from '@/api/auth/auth'
import { XMarkMini } from '@/assets/icons'
import { Button } from '@/components/ui/button'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet'
import useConfirm from '@/lib/hooks/useConfirm'
import { capitalize, isAdminRole, isAgilityRole } from '@/lib/utils'
type UserWithoutPartner = Omit<z.infer<typeof UserSchema>, 'partner'>
type Input = {
userToBeEdited: UserWithoutPartner
authenticatedUser: z.infer<typeof UserSchema>
}
export default function useEditUser(): (
input: Input,
) => Promise<UserWithoutPartner | null> {
const modal = create(SheetComponent)
return (input: Input) => modal(input).catch(() => {})
}
const formSchema = UserSchema.pick({
token: true,
first_name: true,
last_name: true,
role: true,
email: true,
job_title: true,
})
function SheetComponent({
isOpen,
onResolve,
userToBeEdited,
authenticatedUser,
}: InstanceProps<UserWithoutPartner | null, ApiError> & Input) {
const { token, first_name, last_name, role, email, job_title } =
userToBeEdited
const isAdmin =
isAdminRole(authenticatedUser.role) || isAgilityRole(authenticatedUser.role)
const roles: string[] = isAdmin ? [...AdminRoles, ...Roles] : [...Roles]
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
token,
first_name,
last_name,
role,
email,
job_title,
},
})
const confirmationContainer = useRef<HTMLDivElement>(null)
const { confirm: confirmClose } = useConfirm({
title: 'You have unsaved changes',
prompt:
'Are you sure you want to cancel? All unsaved changes will be lost.',
container: confirmationContainer.current,
})
const canClose = !form.formState.isDirty && !form.formState.isSubmitting
async function handleClose() {
if (canClose) return onResolve(null)
const yes = await confirmClose()
if (yes) onResolve(null)
}
async function onSubmit(data: z.infer<typeof formSchema>) {
if (canClose) return onResolve(null)
const error = await UpdateUser(data)
if (error) {
toast.error(error.displayable_message)
} else {
onResolve({ ...userToBeEdited, ...data })
}
}
return (
<Sheet open={isOpen}>
<SheetContent
className="w-[600px] overflow-y-scroll"
ref={confirmationContainer}
>
<SheetHeader className="sticky top-0 z-50 p-5 pb-0">
<div className="flex items-center justify-between">
<SheetTitle>Edit Team Member</SheetTitle>
<SheetClose onClick={handleClose}>
<XMarkMini />
</SheetClose>
</div>
<SheetDescription>
Edit Team Member information and details.
</SheetDescription>
</SheetHeader>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex flex-col gap-4 p-5 pt-0"
>
<div className="flex items-center gap-4">
<FormField
control={form.control}
name="first_name"
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>First Name</FormLabel>
<FormControl>
<Input
tabIndex={1}
className="w-full"
autoComplete="off"
placeholder="Enter First Name"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="last_name"
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>Last Name</FormLabel>
<FormControl>
<Input
tabIndex={2}
className="w-full"
autoComplete="off"
placeholder="Enter Last Name"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="job_title"
render={({ field }) => (
<FormItem>
<FormLabel>Job Title</FormLabel>
<FormControl>
<Input
tabIndex={3}
className="w-full"
autoComplete="off"
placeholder="Enter Job Title"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input
tabIndex={4}
className="w-full"
autoComplete="off"
type="email"
placeholder="Enter Company Domain"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="role"
render={({ field: { value, onChange, ...rest } }) => (
<FormItem className="flex-1">
<FormLabel>Role</FormLabel>
<Select value={value} onValueChange={onChange}>
<FormControl>
<SelectTrigger className="w-full" tabIndex={5} {...rest}>
<SelectValue placeholder="Select Role" />
</SelectTrigger>
</FormControl>
<SelectContent>
{roles.map((role) => (
<SelectItem key={role} value={role}>
{role
.split('-')
.map((x) => capitalize(x))
.join(' - ')}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
<SheetFooter className="sticky bottom-0 z-50 p-5">
<SheetClose onClick={handleClose} asChild>
<Button tabIndex={7} variant="secondary">
Cancel
</Button>
</SheetClose>
<Button
tabIndex={6}
isLoading={form.formState.isSubmitting}
onClick={form.handleSubmit(onSubmit)}
>
Save Changes
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
)
} |
Beta Was this translation helpful? Give feedback.
Answered by
benoitgrelard
Mar 1, 2024
Replies: 1 comment 1 reply
-
It does look like a default browser outline potentially? Try maybe adding |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
StephenSHorton
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It does look like a default browser outline potentially? Try maybe adding
outline: none
to theDialogContent
part.