mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: better focus-visible a11y (#1017)
* refactor: better focus-visible a11y * style: fix tree leaf width * style: input focus ring size * refactor: focus a11y on project pages * fix: project-environment import statement * style: `ring-border` on input * refactor: use ring border --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
This commit is contained in:
@@ -226,7 +226,7 @@ export const DockerLogsId: React.FC<Props> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="rounded-lg overflow-hidden">
|
<div className="rounded-lg">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex flex-wrap justify-between items-start sm:items-center gap-4">
|
<div className="flex flex-wrap justify-between items-start sm:items-center gap-4">
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export const ShowContainers = ({ serverId }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 grid gap-4 pb-20 w-full">
|
<div className="mt-6 grid gap-4 pb-20 w-full">
|
||||||
<div className="flex flex-col gap-4 w-full overflow-auto">
|
<div className="flex flex-col gap-4 w-full">
|
||||||
<div className="flex items-center gap-2 max-sm:flex-wrap">
|
<div className="flex items-center gap-2 max-sm:flex-wrap">
|
||||||
<Input
|
<Input
|
||||||
placeholder="Filter by name..."
|
placeholder="Filter by name..."
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ export const AddTemplate = ({ projectId }: Props) => {
|
|||||||
href={template.links.github}
|
href={template.links.github}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className={
|
className={
|
||||||
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors"
|
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Github className="size-4 text-muted-foreground" />
|
<Github className="size-4 text-muted-foreground" />
|
||||||
@@ -236,7 +236,7 @@ export const AddTemplate = ({ projectId }: Props) => {
|
|||||||
href={template.links.website}
|
href={template.links.website}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className={
|
className={
|
||||||
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors"
|
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Globe className="size-4 text-muted-foreground" />
|
<Globe className="size-4 text-muted-foreground" />
|
||||||
@@ -247,7 +247,7 @@ export const AddTemplate = ({ projectId }: Props) => {
|
|||||||
href={template.links.docs}
|
href={template.links.docs}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className={
|
className={
|
||||||
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors"
|
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<BookText className="size-4 text-muted-foreground" />
|
<BookText className="size-4 text-muted-foreground" />
|
||||||
@@ -257,7 +257,7 @@ export const AddTemplate = ({ projectId }: Props) => {
|
|||||||
href={`https://github.com/Dokploy/dokploy/tree/canary/apps/dokploy/templates/${template.id}`}
|
href={`https://github.com/Dokploy/dokploy/tree/canary/apps/dokploy/templates/${template.id}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className={
|
className={
|
||||||
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors"
|
"text-sm text-muted-foreground p-3 rounded-full hover:bg-border items-center flex transition-colors focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Code className="size-4 text-muted-foreground" />
|
<Code className="size-4 text-muted-foreground" />
|
||||||
|
|||||||
@@ -126,13 +126,16 @@ export const ShowProjects = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={project.projectId} className="w-full lg:max-w-md">
|
<div key={project.projectId} className="w-full lg:max-w-md">
|
||||||
<Link href={`/dashboard/project/${project.projectId}`}>
|
<Link
|
||||||
|
href={`/dashboard/project/${project.projectId}`}
|
||||||
|
className="focus-visible:outline-none ring-ring focus-visible:ring-offset-2 focus-visible:ring-1 block rounded-lg"
|
||||||
|
>
|
||||||
<Card className="group relative w-full bg-transparent transition-colors hover:bg-card">
|
<Card className="group relative w-full bg-transparent transition-colors hover:bg-card">
|
||||||
{flattedDomains.length > 1 ? (
|
{flattedDomains.length > 1 ? (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100"
|
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100 focus-visible:translate-y-0 focus-visible:opacity-100"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="default"
|
variant="default"
|
||||||
>
|
>
|
||||||
@@ -149,10 +152,11 @@ export const ShowProjects = () => {
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
) : flattedDomains[0] ? (
|
) : flattedDomains[0] ? (
|
||||||
<Button
|
<Button
|
||||||
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100"
|
className="absolute -right-3 -top-3 size-9 translate-y-1 rounded-full p-0 opacity-0 transition-all duration-200 group-hover:translate-y-0 group-hover:opacity-100 focus-visible:translate-y-0 focus-visible:opacity-100"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="default"
|
variant="default"
|
||||||
onClick={(e) => e.stopPropagation()}
|
/* onClick={(e) => e.stopPropagation()} */
|
||||||
|
asChild
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
href={`${
|
href={`${
|
||||||
|
|||||||
@@ -194,11 +194,11 @@ export const ProfileForm = () => {
|
|||||||
}}
|
}}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
className="flex flex-row flex-wrap gap-2 max-xl:justify-center"
|
className="flex flex-row flex-wrap gap-2 max-xl:justify-center "
|
||||||
>
|
>
|
||||||
{availableAvatars.map((image) => (
|
{availableAvatars.map((image) => (
|
||||||
<FormItem key={image}>
|
<FormItem key={image}>
|
||||||
<FormLabel className="[&:has([data-state=checked])>img]:border-primary [&:has([data-state=checked])>img]:border-1 [&:has([data-state=checked])>img]:p-px cursor-pointer">
|
<FormLabel className="[&:has([data-state=checked])>img]:border-primary [&:has([data-state=checked])>img]:ring-ring [&:has([data-state=checked])>img]:ring-2 [&:has([data-state=checked])>img]:p-px cursor-pointer">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RadioGroupItem
|
<RadioGroupItem
|
||||||
value={image}
|
value={image}
|
||||||
|
|||||||
@@ -97,7 +97,9 @@ export const Navbar = () => {
|
|||||||
<div className="text-medium box-border flex flex-grow basis-0 flex-row flex-nowrap items-center justify-start whitespace-nowrap bg-transparent no-underline">
|
<div className="text-medium box-border flex flex-grow basis-0 flex-row flex-nowrap items-center justify-start whitespace-nowrap bg-transparent no-underline">
|
||||||
<Link
|
<Link
|
||||||
href="/dashboard/projects"
|
href="/dashboard/projects"
|
||||||
className={cn("flex flex-row items-center gap-2")}
|
className={cn(
|
||||||
|
"flex flex-row items-center gap-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<Logo />
|
<Logo />
|
||||||
<span className="text-sm font-semibold text-primary max-sm:hidden">
|
<span className="text-sm font-semibold text-primary max-sm:hidden">
|
||||||
@@ -130,8 +132,11 @@ export const Navbar = () => {
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<Avatar
|
||||||
<Avatar className="size-10 cursor-pointer border border-border items-center">
|
className="size-10 cursor-pointer border border-border items-center focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<DropdownMenuTrigger>
|
||||||
<AvatarImage src={data?.image || ""} alt="@shadcn" />
|
<AvatarImage src={data?.image || ""} alt="@shadcn" />
|
||||||
<AvatarFallback>
|
<AvatarFallback>
|
||||||
{data?.email
|
{data?.email
|
||||||
@@ -139,8 +144,8 @@ export const Navbar = () => {
|
|||||||
.map((n) => n[0])
|
.map((n) => n[0])
|
||||||
.join("")}
|
.join("")}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</DropdownMenuTrigger>
|
||||||
</DropdownMenuTrigger>
|
</Avatar>
|
||||||
<DropdownMenuContent className="w-56" align="end">
|
<DropdownMenuContent className="w-56" align="end">
|
||||||
<DropdownMenuLabel className="flex flex-col">
|
<DropdownMenuLabel className="flex flex-col">
|
||||||
My Account
|
My Account
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ export const NavigationTabs = ({ tab, children }: Props) => {
|
|||||||
router.push(tab?.index || "");
|
router.push(tab?.index || "");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4 max-sm:overflow-x-auto overflow-y-hidden border-b border-b-divider pb-1">
|
<div className="flex flex-row items-center justify-between w-full gap-4 max-sm:overflow-x-auto border-b border-b-divider pb-1">
|
||||||
<TabsList className="bg-transparent relative px-0">
|
<TabsList className="bg-transparent relative px-0 pb-[8px]">
|
||||||
{tabMap.map((tab, index) => {
|
{tabMap.map((tab, index) => {
|
||||||
if (tab?.isShow && !tab?.isShow?.({ rol: data?.rol, user })) {
|
if (tab?.isShow && !tab?.isShow?.({ rol: data?.rol, user })) {
|
||||||
return null;
|
return null;
|
||||||
@@ -172,7 +172,11 @@ export const NavigationTabs = ({ tab, children }: Props) => {
|
|||||||
</TabsList>
|
</TabsList>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TabsContent value={activeTab} className="w-full">
|
<TabsContent
|
||||||
|
value={activeTab}
|
||||||
|
className="w-full"
|
||||||
|
tabIndex={undefined}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Slot } from "@radix-ui/react-slot";
|
import { Slot, Slottable } from "@radix-ui/react-slot";
|
||||||
import { type VariantProps, cva } from "class-variance-authority";
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{isLoading && <Loader2 className="animate-spin" />}
|
{isLoading && <Loader2 className="animate-spin" />}
|
||||||
{children}
|
<Slottable>{children}</Slottable>
|
||||||
</Comp>
|
</Comp>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ const TreeItem = React.forwardRef<HTMLDivElement, TreeItemProps>(
|
|||||||
<AccordionPrimitive.Item value={item.id}>
|
<AccordionPrimitive.Item value={item.id}>
|
||||||
<AccordionTrigger
|
<AccordionTrigger
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-2 hover:before:opacity-100 before:absolute before:left-0 before:w-full before:opacity-0 before:bg-muted/80 before:h-[1.75rem] before:-z-10",
|
"px-2 hover:before:opacity-100 before:absolute before:left-0 before:w-full before:opacity-0 before:bg-muted/80 before:h-[1.75rem] before:-z-10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
||||||
selectedItemId === item.id &&
|
selectedItemId === item.id &&
|
||||||
"before:opacity-100 before:bg-accent text-accent-foreground before:border-l-2 before:border-l-accent-foreground/50 dark:before:border-0",
|
"before:opacity-100 before:bg-accent text-accent-foreground before:border-l-2 before:border-l-accent-foreground/50 dark:before:border-0",
|
||||||
)}
|
)}
|
||||||
@@ -214,19 +214,20 @@ const TreeItem = React.forwardRef<HTMLDivElement, TreeItemProps>(
|
|||||||
TreeItem.displayName = "TreeItem";
|
TreeItem.displayName = "TreeItem";
|
||||||
|
|
||||||
const Leaf = React.forwardRef<
|
const Leaf = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLButtonElement,
|
||||||
React.HTMLAttributes<HTMLDivElement> & {
|
React.HTMLAttributes<HTMLButtonElement> & {
|
||||||
item: TreeDataItem;
|
item: TreeDataItem;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
Icon?: LucideIcon;
|
Icon?: LucideIcon;
|
||||||
}
|
}
|
||||||
>(({ className, item, isSelected, Icon, ...props }, ref) => {
|
>(({ className, item, isSelected, Icon, ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
type="button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center py-2 px-2 cursor-pointer \
|
"flex items-center py-2 px-2 cursor-pointer \
|
||||||
hover:before:opacity-100 before:absolute before:left-0 before:right-1 before:w-full transition-colors before:opacity-0 before:bg-muted/80 before:h-[1.75rem] before:-z-10",
|
hover:before:opacity-100 before:absolute before:left-0 before:right-1 before:w-full transition-colors before:opacity-0 before:bg-muted/80 before:h-[1.75rem] before:-z-10 rounded-lg focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 relative focus-visible:z-10 w-full",
|
||||||
className,
|
className,
|
||||||
isSelected &&
|
isSelected &&
|
||||||
"before:opacity-100 before:bg-accent bg-border rounded-lg text-accent-foreground before:border-l-2 before:border-l-accent-foreground/50 dark:before:border-0",
|
"before:opacity-100 before:bg-accent bg-border rounded-lg text-accent-foreground before:border-l-2 before:border-l-accent-foreground/50 dark:before:border-0",
|
||||||
@@ -246,7 +247,7 @@ const Leaf = React.forwardRef<
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<p className=" text-sm whitespace-normal font-mono">{item.name}</p>
|
<p className=" text-sm whitespace-normal font-mono">{item.name}</p>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||||||
type={type}
|
type={type}
|
||||||
className={cn(
|
className={cn(
|
||||||
// bg-gray
|
// bg-gray
|
||||||
"flex h-10 w-full rounded-md bg-input px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
"flex h-10 w-full rounded-md bg-input px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const SelectTrigger = React.forwardRef<
|
|||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-input px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-input px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -38,13 +38,14 @@ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|||||||
const TabsContent = React.forwardRef<
|
const TabsContent = React.forwardRef<
|
||||||
React.ElementRef<typeof TabsPrimitive.Content>,
|
React.ElementRef<typeof TabsPrimitive.Content>,
|
||||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, tabIndex, ...props }, ref) => (
|
||||||
<TabsPrimitive.Content
|
<TabsPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
tabIndex={tabIndex}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex min-h-[80px] w-full rounded-md border border-input bg-input px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
"flex min-h-[80px] w-full rounded-md border border-input bg-input px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -7,7 +7,19 @@ const TooltipProvider = TooltipPrimitive.Provider;
|
|||||||
|
|
||||||
const Tooltip = TooltipPrimitive.Root;
|
const Tooltip = TooltipPrimitive.Root;
|
||||||
|
|
||||||
const TooltipTrigger = TooltipPrimitive.Trigger;
|
const TooltipTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof TooltipPrimitive.Trigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<TooltipPrimitive.Trigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
const TooltipPortal = TooltipPrimitive.Portal;
|
const TooltipPortal = TooltipPrimitive.Portal;
|
||||||
|
|
||||||
@@ -19,7 +31,7 @@ const TooltipContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { AddApplication } from "@/components/dashboard/project/add-application";
|
import { AddApplication } from "@/components/dashboard/project/add-application";
|
||||||
|
import { ProjectEnvironment } from "@/components/dashboard/projects/project-environment";
|
||||||
import { AddCompose } from "@/components/dashboard/project/add-compose";
|
import { AddCompose } from "@/components/dashboard/project/add-compose";
|
||||||
import { AddDatabase } from "@/components/dashboard/project/add-database";
|
import { AddDatabase } from "@/components/dashboard/project/add-database";
|
||||||
import { AddTemplate } from "@/components/dashboard/project/add-template";
|
import { AddTemplate } from "@/components/dashboard/project/add-template";
|
||||||
import { ProjectEnvironment } from "@/components/dashboard/projects/project-environment";
|
|
||||||
import {
|
import {
|
||||||
MariadbIcon,
|
MariadbIcon,
|
||||||
MongodbIcon,
|
MongodbIcon,
|
||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
PostgresqlIcon,
|
PostgresqlIcon,
|
||||||
RedisIcon,
|
RedisIcon,
|
||||||
} from "@/components/icons/data-tools-icons";
|
} from "@/components/icons/data-tools-icons";
|
||||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
|
||||||
import { ProjectLayout } from "@/components/layouts/project-layout";
|
import { ProjectLayout } from "@/components/layouts/project-layout";
|
||||||
import { DateTooltip } from "@/components/shared/date-tooltip";
|
import { DateTooltip } from "@/components/shared/date-tooltip";
|
||||||
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
||||||
@@ -205,7 +204,7 @@ const Project = (
|
|||||||
{(auth?.rol === "admin" || user?.canCreateServices) && (
|
{(auth?.rol === "admin" || user?.canCreateServices) && (
|
||||||
<div className="flex flex-row gap-4 flex-wrap">
|
<div className="flex flex-row gap-4 flex-wrap">
|
||||||
<ProjectEnvironment projectId={projectId}>
|
<ProjectEnvironment projectId={projectId}>
|
||||||
<Button variant="outline">Project Environment</Button>
|
<Button variant="outline">Project Enviroment</Button>
|
||||||
</ProjectEnvironment>
|
</ProjectEnvironment>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@@ -236,7 +235,7 @@ const Project = (
|
|||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full gap-8">
|
<div className="flex w-full gap-8 ">
|
||||||
{emptyServices ? (
|
{emptyServices ? (
|
||||||
<div className="flex h-[70vh] w-full flex-col items-center justify-center">
|
<div className="flex h-[70vh] w-full flex-col items-center justify-center">
|
||||||
<FolderInput className="size-10 md:size-28 text-muted" />
|
<FolderInput className="size-10 md:size-28 text-muted" />
|
||||||
|
|||||||
Reference in New Issue
Block a user