fix(dialogs): fix height of dialogs for small screens (#440)

* fix(dialogs): fix height of dialogs on small screens

* fix type
This commit is contained in:
Guy Ben-Aharon
2024-11-24 12:21:15 +02:00
committed by GitHub
parent 2940431efa
commit 667685ed0f
10 changed files with 258 additions and 224 deletions

View File

@@ -3,6 +3,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
import { Cross2Icon } from '@radix-ui/react-icons'; import { Cross2Icon } from '@radix-ui/react-icons';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ScrollArea } from '../scroll-area/scroll-area';
const Dialog = DialogPrimitive.Root; const Dialog = DialogPrimitive.Root;
@@ -110,6 +111,18 @@ const DialogDescription = React.forwardRef<
)); ));
DialogDescription.displayName = DialogPrimitive.Description.displayName; DialogDescription.displayName = DialogPrimitive.Description.displayName;
const DialogInternalContent = React.forwardRef<
React.ElementRef<typeof ScrollArea>,
React.ComponentPropsWithoutRef<typeof ScrollArea>
>(({ className, ...props }, ref) => (
<ScrollArea
ref={ref}
className={cn('flex max-h-screen flex-col overflow-y-auto', className)}
{...props}
/>
));
DialogInternalContent.displayName = 'DialogInternalContent';
export { export {
Dialog, Dialog,
DialogPortal, DialogPortal,
@@ -121,4 +134,5 @@ export {
DialogFooter, DialogFooter,
DialogTitle, DialogTitle,
DialogDescription, DialogDescription,
DialogInternalContent,
}; };

View File

@@ -12,7 +12,7 @@ const ScrollArea = React.forwardRef<
className={cn('relative overflow-hidden', className)} className={cn('relative overflow-hidden', className)}
{...props} {...props}
> >
<ScrollAreaPrimitive.Viewport className="scrollable-flex size-full rounded-[inherit]"> <ScrollAreaPrimitive.Viewport className="size-full rounded-[inherit]">
{children} {children}
</ScrollAreaPrimitive.Viewport> </ScrollAreaPrimitive.Viewport>
<ScrollBar /> <ScrollBar />
@@ -40,7 +40,7 @@ const ScrollBar = React.forwardRef<
)} )}
{...props} {...props}
> >
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" /> <ScrollAreaPrimitive.ScrollAreaThumb className="relative z-20 flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar> </ScrollAreaPrimitive.ScrollAreaScrollbar>
)); ));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;

View File

@@ -5,6 +5,7 @@ import {
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogInternalContent,
DialogTitle, DialogTitle,
} from '@/components/dialog/dialog'; } from '@/components/dialog/dialog';
import { ToggleGroup, ToggleGroupItem } from '@/components/toggle/toggle-group'; import { ToggleGroup, ToggleGroupItem } from '@/components/toggle/toggle-group';
@@ -157,188 +158,201 @@ export const ImportDatabase: React.FC<ImportDatabaseProps> = ({
const renderContent = useCallback(() => { const renderContent = useCallback(() => {
return ( return (
<div className="flex w-full flex-1 flex-col gap-6"> <DialogInternalContent>
{databaseTypeToEditionMap[databaseType].length > 0 ? ( <div className="flex w-full flex-1 flex-col gap-6">
<div className="flex flex-col gap-1 md:flex-row"> {databaseTypeToEditionMap[databaseType].length > 0 ? (
<p className="text-sm leading-6 text-muted-foreground"> <div className="flex flex-col gap-1 md:flex-row">
{t( <p className="text-sm leading-6 text-muted-foreground">
'new_diagram_dialog.import_database.database_edition' {t(
)} 'new_diagram_dialog.import_database.database_edition'
</p> )}
<ToggleGroup </p>
type="single" <ToggleGroup
className="ml-1 flex-wrap gap-2" type="single"
value={ className="ml-1 flex-wrap gap-2"
!databaseEdition ? 'regular' : databaseEdition value={
} !databaseEdition
onValueChange={(value) => { ? 'regular'
setDatabaseEdition( : databaseEdition
value === 'regular' }
? undefined onValueChange={(value) => {
: (value as DatabaseEdition) setDatabaseEdition(
); value === 'regular'
}} ? undefined
> : (value as DatabaseEdition)
<ToggleGroupItem );
value="regular" }}
variant="outline"
className="h-6 gap-1 p-0 px-2 shadow-none"
> >
<Avatar className="size-4 rounded-none"> <ToggleGroupItem
<AvatarImage value="regular"
src={ variant="outline"
databaseSecondaryLogoMap[ className="h-6 gap-1 p-0 px-2 shadow-none"
databaseType >
] <Avatar className="size-4 rounded-none">
} <AvatarImage
alt="Regular" src={
/> databaseSecondaryLogoMap[
<AvatarFallback>Regular</AvatarFallback> databaseType
</Avatar> ]
Regular }
</ToggleGroupItem> alt="Regular"
{databaseTypeToEditionMap[databaseType].map( />
(edition) => ( <AvatarFallback>Regular</AvatarFallback>
<ToggleGroupItem </Avatar>
value={edition} Regular
key={edition} </ToggleGroupItem>
variant="outline" {databaseTypeToEditionMap[databaseType].map(
className="h-6 gap-1 p-0 px-2 shadow-none" (edition) => (
> <ToggleGroupItem
<Avatar className="size-4"> value={edition}
<AvatarImage key={edition}
src={ variant="outline"
databaseEditionToImageMap[ className="h-6 gap-1 p-0 px-2 shadow-none"
edition
]
}
alt={
databaseEditionToLabelMap[
edition
]
}
/>
<AvatarFallback>
{
databaseEditionToLabelMap[
edition
]
}
</AvatarFallback>
</Avatar>
{databaseEditionToLabelMap[edition]}
</ToggleGroupItem>
)
)}
</ToggleGroup>
</div>
) : null}
<div className="flex flex-col gap-1">
<div className="flex flex-col gap-1 text-sm text-muted-foreground md:flex-row md:justify-between">
<div>
1. {t('new_diagram_dialog.import_database.step_1')}
</div>
{databaseType === DatabaseType.SQL_SERVER && (
<SSMSInfo />
)}
</div>
{databaseTypeToClientsMap[databaseType].length > 0 ? (
<Tabs
value={
!databaseClient ? 'dbclient' : databaseClient
}
onValueChange={(value) => {
setDatabaseClient(
value === 'dbclient'
? undefined
: (value as DatabaseClient)
);
}}
>
<div className="flex flex-1">
<TabsList className="h-8 justify-start rounded-none rounded-t-sm ">
<TabsTrigger
value="dbclient"
className="h-6 w-20"
>
DB Client
</TabsTrigger>
{databaseClients?.map((client) => (
<TabsTrigger
key={client}
value={client}
className="h-6 !w-20"
> >
{databaseClientToLabelMap[client]} <Avatar className="size-4">
</TabsTrigger> <AvatarImage
)) ?? []} src={
</TabsList> databaseEditionToImageMap[
edition
]
}
alt={
databaseEditionToLabelMap[
edition
]
}
/>
<AvatarFallback>
{
databaseEditionToLabelMap[
edition
]
}
</AvatarFallback>
</Avatar>
{databaseEditionToLabelMap[edition]}
</ToggleGroupItem>
)
)}
</ToggleGroup>
</div>
) : null}
<div className="flex flex-col gap-1">
<div className="flex flex-col gap-1 text-sm text-muted-foreground md:flex-row md:justify-between">
<div>
1.{' '}
{t('new_diagram_dialog.import_database.step_1')}
</div> </div>
{databaseType === DatabaseType.SQL_SERVER && (
<SSMSInfo />
)}
</div>
{databaseTypeToClientsMap[databaseType].length > 0 ? (
<Tabs
value={
!databaseClient
? 'dbclient'
: databaseClient
}
onValueChange={(value) => {
setDatabaseClient(
value === 'dbclient'
? undefined
: (value as DatabaseClient)
);
}}
>
<div className="flex flex-1">
<TabsList className="h-8 justify-start rounded-none rounded-t-sm ">
<TabsTrigger
value="dbclient"
className="h-6 w-20"
>
DB Client
</TabsTrigger>
{databaseClients?.map((client) => (
<TabsTrigger
key={client}
value={client}
className="h-6 !w-20"
>
{
databaseClientToLabelMap[
client
]
}
</TabsTrigger>
)) ?? []}
</TabsList>
</div>
<CodeSnippet
className="h-40 w-full"
loading={!importMetadataScripts}
code={
importMetadataScripts?.[databaseType]?.(
{
databaseEdition,
databaseClient,
}
) ?? ''
}
language={databaseClient ? 'shell' : 'sql'}
/>
</Tabs>
) : (
<CodeSnippet <CodeSnippet
className="h-40 w-full" className="h-40 w-full flex-auto"
loading={!importMetadataScripts} loading={!importMetadataScripts}
code={ code={
importMetadataScripts?.[databaseType]?.({ importMetadataScripts?.[databaseType]?.({
databaseEdition, databaseEdition,
databaseClient,
}) ?? '' }) ?? ''
} }
language={databaseClient ? 'shell' : 'sql'} language="sql"
/> />
</Tabs>
) : (
<CodeSnippet
className="h-40 w-full flex-auto"
loading={!importMetadataScripts}
code={
importMetadataScripts?.[databaseType]?.({
databaseEdition,
}) ?? ''
}
language="sql"
/>
)}
</div>
<div className="flex h-48 flex-col gap-1">
<p className="text-sm text-muted-foreground">
2. {t('new_diagram_dialog.import_database.step_2')}
</p>
<Textarea
className="w-full flex-1 rounded-md bg-muted p-2 text-sm"
placeholder={t(
'new_diagram_dialog.import_database.script_results_placeholder'
)} )}
value={scriptResult} </div>
onChange={handleInputChange} <div className="flex h-48 flex-col gap-1">
/> <p className="text-sm text-muted-foreground">
{showCheckJsonButton || errorMessage ? ( 2. {t('new_diagram_dialog.import_database.step_2')}
<div className="mt-2 flex items-center gap-2"> </p>
{showCheckJsonButton ? ( <Textarea
<Button className="w-full flex-1 rounded-md bg-muted p-2 text-sm"
type="button" placeholder={t(
variant="outline" 'new_diagram_dialog.import_database.script_results_placeholder'
size="sm"
onClick={handleCheckJson}
disabled={isCheckingJson}
>
{isCheckingJson ? (
<Spinner size="small" />
) : (
t(
'new_diagram_dialog.import_database.check_script_result'
)
)}
</Button>
) : (
<p className="text-sm text-red-700">
{errorMessage}
</p>
)} )}
</div> value={scriptResult}
) : null} onChange={handleInputChange}
/>
{showCheckJsonButton || errorMessage ? (
<div className="mt-2 flex items-center gap-2">
{showCheckJsonButton ? (
<Button
type="button"
variant="outline"
size="sm"
onClick={handleCheckJson}
disabled={isCheckingJson}
>
{isCheckingJson ? (
<Spinner size="small" />
) : (
t(
'new_diagram_dialog.import_database.check_script_result'
)
)}
</Button>
) : (
<p className="text-sm text-red-700">
{errorMessage}
</p>
)}
</div>
) : null}
</div>
</div> </div>
</div> </DialogInternalContent>
); );
}, [ }, [
databaseEdition, databaseEdition,

View File

@@ -128,7 +128,7 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({
}} }}
> >
<DialogContent <DialogContent
className="flex w-[90vw] max-w-[90vw] flex-col overflow-y-auto md:overflow-visible lg:max-w-[60vw] xl:lg:max-w-lg xl:min-w-[45vw]" className="flex max-h-screen w-[90vw] max-w-[90vw] flex-col overflow-y-auto md:overflow-visible lg:max-w-[60vw] xl:lg:max-w-lg xl:min-w-[45vw]"
showClose={hasExistingDiagram} showClose={hasExistingDiagram}
> >
{step === CreateDiagramDialogStep.SELECT_DATABASE ? ( {step === CreateDiagramDialogStep.SELECT_DATABASE ? (

View File

@@ -5,6 +5,7 @@ import {
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogInternalContent,
DialogTitle, DialogTitle,
} from '@/components/dialog/dialog'; } from '@/components/dialog/dialog';
import { DatabaseType } from '@/lib/domain/database-type'; import { DatabaseType } from '@/lib/domain/database-type';
@@ -40,11 +41,13 @@ export const SelectDatabase: React.FC<SelectDatabaseProps> = ({
{t('new_diagram_dialog.database_selection.description')} {t('new_diagram_dialog.database_selection.description')}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<SelectDatabaseContent <DialogInternalContent>
databaseType={databaseType} <SelectDatabaseContent
onContinue={onContinue} databaseType={databaseType}
setDatabaseType={setDatabaseType} onContinue={onContinue}
/> setDatabaseType={setDatabaseType}
/>
</DialogInternalContent>
<DialogFooter className="mt-4 flex !justify-between gap-2"> <DialogFooter className="mt-4 flex !justify-between gap-2">
{hasExistingDiagram ? ( {hasExistingDiagram ? (
<DialogClose asChild> <DialogClose asChild>

View File

@@ -7,6 +7,7 @@ import {
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogInternalContent,
DialogTitle, DialogTitle,
} from '@/components/dialog/dialog'; } from '@/components/dialog/dialog';
import { Label } from '@/components/label/label'; import { Label } from '@/components/label/label';
@@ -151,7 +152,7 @@ export const ExportSQLDialog: React.FC<ExportSQLDialogProps> = ({
}} }}
> >
<DialogContent <DialogContent
className="flex max-h-[80vh] flex-col overflow-y-auto xl:min-w-[75vw]" className="flex max-h-screen flex-col overflow-y-auto xl:min-w-[75vw]"
showClose showClose
> >
<DialogHeader> <DialogHeader>
@@ -167,23 +168,24 @@ export const ExportSQLDialog: React.FC<ExportSQLDialogProps> = ({
})} })}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="flex flex-1 items-center justify-center"> <DialogInternalContent>
{error ? ( <div className="flex flex-1 items-center justify-center">
renderError() {error ? (
) : script === undefined ? ( renderError()
renderLoader() ) : script === undefined ? (
) : script.length === 0 ? ( renderLoader()
renderError() ) : script.length === 0 ? (
) : ( renderError()
<CodeSnippet ) : (
className="h-96 w-full" <CodeSnippet
code={script!} className="h-96 w-full"
autoScroll={true} code={script!}
isComplete={!isScriptLoading} autoScroll={true}
/> isComplete={!isScriptLoading}
)} />
</div> )}
</div>
</DialogInternalContent>
<DialogFooter className="flex !justify-between gap-2"> <DialogFooter className="flex !justify-between gap-2">
<div /> <div />
<DialogClose asChild> <DialogClose asChild>

View File

@@ -323,7 +323,7 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({
}} }}
> >
<DialogContent <DialogContent
className="flex w-[90vw] flex-col overflow-y-auto md:overflow-visible xl:min-w-[45vw]" className="flex max-h-screen w-[90vw] flex-col overflow-y-auto md:overflow-visible xl:min-w-[45vw]"
showClose showClose
> >
<ImportDatabase <ImportDatabase

View File

@@ -7,6 +7,7 @@ import {
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogInternalContent,
DialogTitle, DialogTitle,
} from '@/components/dialog/dialog'; } from '@/components/dialog/dialog';
import { Button } from '@/components/button/button'; import { Button } from '@/components/button/button';
@@ -87,7 +88,7 @@ export const ImportDiagramDialog: React.FC<ImportDiagramDialogProps> = ({
} }
}} }}
> >
<DialogContent className="flex flex-col" showClose> <DialogContent className="flex max-h-screen flex-col" showClose>
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
{t('import_diagram_dialog.title')} {t('import_diagram_dialog.title')}
@@ -96,23 +97,27 @@ export const ImportDiagramDialog: React.FC<ImportDiagramDialogProps> = ({
{t('import_diagram_dialog.description')} {t('import_diagram_dialog.description')}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="flex flex-col p-1"> <DialogInternalContent>
<FileUploader <div className="flex flex-col p-1">
supportedExtensions={['.json']} <FileUploader
onFilesChange={onFileChange} supportedExtensions={['.json']}
/> onFilesChange={onFileChange}
{error ? ( />
<Alert variant="destructive" className="mt-2"> {error ? (
<AlertCircle className="size-4" /> <Alert variant="destructive" className="mt-2">
<AlertTitle> <AlertCircle className="size-4" />
{t('import_diagram_dialog.error.title')} <AlertTitle>
</AlertTitle> {t('import_diagram_dialog.error.title')}
<AlertDescription> </AlertTitle>
{t('import_diagram_dialog.error.description')} <AlertDescription>
</AlertDescription> {t(
</Alert> 'import_diagram_dialog.error.description'
) : null} )}
</div> </AlertDescription>
</Alert>
) : null}
</div>
</DialogInternalContent>
<DialogFooter className="flex gap-1 md:justify-between"> <DialogFooter className="flex gap-1 md:justify-between">
<DialogClose asChild> <DialogClose asChild>
<Button variant="secondary"> <Button variant="secondary">

View File

@@ -7,9 +7,9 @@ import {
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogInternalContent,
DialogTitle, DialogTitle,
} from '@/components/dialog/dialog'; } from '@/components/dialog/dialog';
import { ScrollArea } from '@/components/scroll-area/scroll-area';
import { import {
Table, Table,
TableBody, TableBody,
@@ -74,7 +74,7 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({
}} }}
> >
<DialogContent <DialogContent
className="flex w-[90vw] flex-col overflow-y-auto md:w-screen xl:min-w-[55vw]" className="flex h-[30rem] max-h-screen w-[90vw] flex-col overflow-y-auto md:w-screen xl:min-w-[55vw]"
showClose showClose
> >
<DialogHeader> <DialogHeader>
@@ -83,9 +83,9 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({
{t('open_diagram_dialog.description')} {t('open_diagram_dialog.description')}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="flex flex-1 items-center justify-center"> <DialogInternalContent>
<ScrollArea className="h-80 w-full"> <div className="flex flex-1 items-center justify-center">
<Table className="h-fit"> <Table>
<TableHeader className="sticky top-0 bg-background"> <TableHeader className="sticky top-0 bg-background">
<TableRow> <TableRow>
<TableHead /> <TableHead />
@@ -155,8 +155,8 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({
))} ))}
</TableBody> </TableBody>
</Table> </Table>
</ScrollArea> </div>
</div> </DialogInternalContent>
<DialogFooter className="flex !justify-between gap-2"> <DialogFooter className="flex !justify-between gap-2">
<DialogClose asChild> <DialogClose asChild>

View File

@@ -16,10 +16,6 @@
@apply hidden !important; @apply hidden !important;
} }
.scrollable-flex > div {
@apply !flex;
}
.marker-definitions { .marker-definitions {
} }
} }