mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-16 04:35:24 +02:00
refactor: extract TagBadge into shared component
Replace duplicated inline badge styling with a reusable TagBadge component to ensure consistent appearance across all tag displays.
This commit is contained in:
@@ -17,6 +17,7 @@ import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
|
||||
import { DateTooltip } from "@/components/shared/date-tooltip";
|
||||
import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input";
|
||||
import { StatusTooltip } from "@/components/shared/status-tooltip";
|
||||
import { TagBadge } from "@/components/shared/tag-badge";
|
||||
import { TagFilter } from "@/components/shared/tag-filter";
|
||||
import {
|
||||
AlertDialog,
|
||||
@@ -29,7 +30,6 @@ import {
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -486,23 +486,11 @@ export const ShowProjects = () => {
|
||||
project.projectTags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1.5 mt-2">
|
||||
{project.projectTags.map((pt) => (
|
||||
<Badge
|
||||
<TagBadge
|
||||
key={pt.tag.tagId}
|
||||
variant="blank"
|
||||
style={{
|
||||
backgroundColor: pt.tag.color
|
||||
? `${pt.tag.color}33`
|
||||
: undefined,
|
||||
color:
|
||||
pt.tag.color || undefined,
|
||||
borderColor: pt.tag.color
|
||||
? `${pt.tag.color}66`
|
||||
: undefined,
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
{pt.tag.name}
|
||||
</Badge>
|
||||
name={pt.tag.name}
|
||||
color={pt.tag.color}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { TagBadge } from "@/components/shared/tag-badge";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -232,16 +232,10 @@ export const HandleTag = ({ tagId }: HandleTagProps) => {
|
||||
{colorValue && (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-muted-foreground">Preview:</span>
|
||||
<Badge
|
||||
style={{
|
||||
backgroundColor: `${colorValue}33`,
|
||||
color: colorValue,
|
||||
borderColor: `${colorValue}66`,
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
{form.watch("name") || "Tag Name"}
|
||||
</Badge>
|
||||
<TagBadge
|
||||
name={form.watch("name") || "Tag Name"}
|
||||
color={colorValue}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
@@ -355,18 +349,7 @@ export const TagManager = () => {
|
||||
className="flex items-center justify-between rounded-lg border p-3 hover:bg-accent/50 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Badge
|
||||
style={{
|
||||
backgroundColor: tag.color
|
||||
? `${tag.color}33`
|
||||
: undefined,
|
||||
color: tag.color || undefined,
|
||||
borderColor: tag.color ? `${tag.color}66` : undefined,
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
<TagBadge name={tag.name} color={tag.color} />
|
||||
{tag.color && (
|
||||
<span className="text-xs text-muted-foreground font-mono">
|
||||
{tag.color}
|
||||
|
||||
25
apps/dokploy/components/shared/tag-badge.tsx
Normal file
25
apps/dokploy/components/shared/tag-badge.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface TagBadgeProps {
|
||||
name: string;
|
||||
color?: string | null;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function TagBadge({ name, color, className, children }: TagBadgeProps) {
|
||||
return (
|
||||
<Badge
|
||||
style={{
|
||||
backgroundColor: color ? `${color}33` : undefined,
|
||||
color: color || undefined,
|
||||
borderColor: color ? `${color}66` : undefined,
|
||||
}}
|
||||
className={cn("border", className)}
|
||||
>
|
||||
{name}
|
||||
{children}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Filter } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { HandleTag } from "@/components/dashboard/settings/tags/tag-manager";
|
||||
import { TagBadge } from "@/components/shared/tag-badge";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
@@ -109,18 +110,7 @@ export function TagFilter({
|
||||
className="mr-2"
|
||||
onCheckedChange={() => handleTagToggle(tag.id)}
|
||||
/>
|
||||
<Badge
|
||||
style={{
|
||||
backgroundColor: tag.color
|
||||
? `${tag.color}33`
|
||||
: undefined,
|
||||
color: tag.color || undefined,
|
||||
borderColor: tag.color ? `${tag.color}66` : undefined,
|
||||
}}
|
||||
className="border"
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
<TagBadge name={tag.name} color={tag.color} />
|
||||
</CommandItem>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Check, ChevronsUpDown, X } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { HandleTag } from "@/components/dashboard/settings/tags/tag-manager";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { TagBadge } from "@/components/shared/tag-badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import {
|
||||
@@ -77,17 +77,12 @@ export function TagSelector({
|
||||
<div className="flex flex-wrap gap-1 flex-1">
|
||||
{selectedTagObjects.length > 0 ? (
|
||||
selectedTagObjects.map((tag) => (
|
||||
<Badge
|
||||
<TagBadge
|
||||
key={tag.id}
|
||||
variant="blank"
|
||||
style={{
|
||||
backgroundColor: tag.color ? `${tag.color}33` : undefined,
|
||||
color: tag.color || undefined,
|
||||
borderColor: tag.color ? `${tag.color}66` : undefined,
|
||||
}}
|
||||
className="flex items-center gap-1 pr-1 border"
|
||||
name={tag.name}
|
||||
color={tag.color}
|
||||
className="flex items-center gap-1 pr-1"
|
||||
>
|
||||
<span>{tag.name}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => handleTagRemove(tag.id, e)}
|
||||
@@ -97,7 +92,7 @@ export function TagSelector({
|
||||
<X className="h-3 w-3 hover:opacity-70" />
|
||||
<span className="sr-only">Remove {tag.name}</span>
|
||||
</button>
|
||||
</Badge>
|
||||
</TagBadge>
|
||||
))
|
||||
) : (
|
||||
<span className="text-muted-foreground">{placeholder}</span>
|
||||
@@ -132,19 +127,11 @@ export function TagSelector({
|
||||
className="mr-2"
|
||||
onCheckedChange={() => handleTagToggle(tag.id)}
|
||||
/>
|
||||
<Badge
|
||||
variant="blank"
|
||||
style={{
|
||||
backgroundColor: tag.color
|
||||
? `${tag.color}33`
|
||||
: undefined,
|
||||
color: tag.color || undefined,
|
||||
borderColor: tag.color ? `${tag.color}66` : undefined,
|
||||
}}
|
||||
className="mr-2 border"
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
<TagBadge
|
||||
name={tag.name}
|
||||
color={tag.color}
|
||||
className="mr-2"
|
||||
/>
|
||||
<Check
|
||||
className={cn(
|
||||
"ml-auto h-4 w-4",
|
||||
|
||||
Reference in New Issue
Block a user