diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_components/rbac-dialog-content.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_components/rbac-dialog-content.tsx index 9631ff95d7..3ebb9c97e9 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_components/rbac-dialog-content.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_components/rbac-dialog-content.tsx @@ -1,9 +1,8 @@ "use client"; -import { Badge } from "@/components/ui/badge"; import { formatNumber } from "@/lib/fmt"; import { trpc } from "@/lib/trpc/client"; -import { Button, Loading } from "@unkey/ui"; +import { Badge, Button, Loading } from "@unkey/ui"; import dynamic from "next/dynamic"; const PermissionList = dynamic( diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/log-details/components/log-header.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/log-details/components/log-header.tsx index 5c331286f5..89b345c247 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/log-details/components/log-header.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/log-details/components/log-header.tsx @@ -1,8 +1,7 @@ -import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import type { KeysOverviewLog } from "@unkey/clickhouse/src/keys/keys"; import { XMark } from "@unkey/icons"; -import { Button } from "@unkey/ui"; +import { Badge, Button } from "@unkey/ui"; export const LogHeader = ({ onClose, diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/outcome-popover.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/outcome-popover.tsx index b01ef557ae..4f52134dc2 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/outcome-popover.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/outcome-popover.tsx @@ -1,10 +1,9 @@ "use client"; -import { Badge } from "@/components/ui/badge"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { formatNumber } from "@/lib/fmt"; import { cn } from "@/lib/utils"; import { ChevronRight } from "@unkey/icons"; -import { Button } from "@unkey/ui"; +import { Badge, Button } from "@unkey/ui"; import { formatOutcomeName, getOutcomeBadgeStyle, getOutcomeColor } from "../../../utils"; import { STATUS_STYLES } from "../utils/get-row-class"; diff --git a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/logs-table.tsx b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/logs-table.tsx index 15dc58a86e..a72f135512 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/logs-table.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/logs-table.tsx @@ -1,11 +1,10 @@ "use client"; -import { Badge } from "@/components/ui/badge"; import { VirtualTable } from "@/components/virtual-table/index"; import type { Column } from "@/components/virtual-table/types"; import { cn } from "@/lib/utils"; import type { KeysOverviewLog } from "@unkey/clickhouse/src/keys/keys"; import { Ban, BookBookmark } from "@unkey/icons"; -import { Button, Empty, TimestampInfo } from "@unkey/ui"; +import { Badge, Button, Empty, TimestampInfo } from "@unkey/ui"; import { useSort } from "@/components/logs/hooks/use-sort"; import { formatNumber } from "@/lib/fmt"; diff --git a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/table/logs-table.tsx b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/table/logs-table.tsx index e54acad835..26706fae17 100644 --- a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/table/logs-table.tsx +++ b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/table/logs-table.tsx @@ -1,5 +1,4 @@ "use client"; -import { Badge } from "@/components/ui/badge"; import { VirtualTable } from "@/components/virtual-table/index"; import type { Column } from "@/components/virtual-table/types"; import { trpc } from "@/lib/trpc/client"; @@ -16,9 +15,7 @@ import { TimeClock, TriangleWarning2, } from "@unkey/icons"; -import { CopyButton } from "@unkey/ui"; -import { TimestampInfo } from "@unkey/ui"; -import { Button, Empty, InfoTooltip } from "@unkey/ui"; +import { Badge, Button, CopyButton, Empty, InfoTooltip, TimestampInfo } from "@unkey/ui"; import { useCallback, useState } from "react"; import { useKeyDetailsLogsContext } from "../../context/logs"; import { StatusBadge } from "./components/status-badge"; @@ -349,7 +346,6 @@ export const KeyDetailsLogsTable = ({ keyspaceId, keyId, selectedLog, onLogSelec asChild > +
+ Primary + Secondary + Success + Warning + Blocked + Error +
+ + ); +} + +export function SizeVariants() { + return ( + +
+
+ Default Size + Default +
+
+ + Small Size + + Small +
+
+
+ ); +} + +export function MonoFont() { + return ( + +
+ + uk_1234567890abcdef + + + v1.2.3 + + + 200 OK + + + 404 NOT_FOUND + +
+
+ ); +} + +export function StatusBadges() { + return ( + +
+
+ Active: + Online +
+
+ Warning: + Rate Limited +
+
+ Blocked: + Suspended +
+
+ Error: + Failed +
+
+ Info: + Pending +
+
+
+ ); +} + +export function InteractiveBadges() { + return ( + +
+ + Clickable Tag + + + Category + + + ✓ Verified + + + v2.1.0-beta + +
+
+ ); +} diff --git a/apps/engineering/content/design/components/badge.mdx b/apps/engineering/content/design/components/badge.mdx new file mode 100644 index 0000000000..c2db9b40af --- /dev/null +++ b/apps/engineering/content/design/components/badge.mdx @@ -0,0 +1,73 @@ +--- +title: Badge +description: A versatile badge component for displaying status, categories, or labels with multiple variants and styling options. +--- +import { DefaultVariants, SizeVariants, MonoFont, StatusBadges, InteractiveBadges } from "./badge.example"; + +## Usage + +```tsx +import { Badge } from "@unkey/ui"; + +export default function MyComponent() { + return ( +
+ Default + Success + Error +
+ ); +} +``` + +## Examples + +### Default Variants + + +### Size Variants + + +### Monospace Font + + +### Status Badges + + +### Interactive Badges + + +## Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `variant` | `"primary" \| "secondary" \| "success" \| "warning" \| "blocked" \| "error"` | `"primary"` | The visual variant of the badge. | +| `size` | `"DEFAULT" \| "sm"` | `"DEFAULT"` | The size of the badge. | +| `font` | `"mono"` | - | Use monospace font for the badge text. | +| `className` | `string` | - | Additional CSS classes to apply to the badge. | + +## Variants + +- **primary**: Default neutral appearance with gray background +- **secondary**: Subtle border style with lighter background +- **success**: Green styling for positive states +- **warning**: Yellow/orange styling for warnings +- **blocked**: Orange styling for blocked or restricted states +- **error**: Red styling for errors or negative states + +## Accessibility + +The Badge component follows accessibility best practices: + +- Uses semantic HTML with proper color contrast ratios +- Text is readable and meets WCAG guidelines +- Can be used with screen readers without issues +- Hover states provide visual feedback for interactive elements + +## Best Practices + +- Use badges to provide quick visual context about status or categories +- Choose appropriate variants that match the semantic meaning +- Keep badge text concise and descriptive +- Use consistent badge styling across your application +- Consider using the monospace font for technical content like IDs or codes \ No newline at end of file diff --git a/apps/engineering/content/design/components/dialogs/navigable-dialog.example.tsx b/apps/engineering/content/design/components/dialogs/navigable-dialog.example.tsx index 8053322383..44b4e9ebcd 100644 --- a/apps/engineering/content/design/components/dialogs/navigable-dialog.example.tsx +++ b/apps/engineering/content/design/components/dialogs/navigable-dialog.example.tsx @@ -84,7 +84,7 @@ export const NavigableDialogExample = memo(() => { subTitle="A simple demonstration" /> - + diff --git a/apps/dashboard/components/ui/badge.tsx b/internal/ui/src/components/badge.tsx similarity index 62% rename from apps/dashboard/components/ui/badge.tsx rename to internal/ui/src/components/badge.tsx index 68b02891b7..0500f36e8b 100644 --- a/apps/dashboard/components/ui/badge.tsx +++ b/internal/ui/src/components/badge.tsx @@ -1,14 +1,16 @@ -import { cn } from "@/lib/utils"; +// biome-ignore lint: React in this context is used throughout, so biome will change to types because no APIs are used even though React is needed. +import React from "react"; import { type VariantProps, cva } from "class-variance-authority"; -import type * as React from "react"; + import { forwardRef } from "react"; +import { cn } from "../lib/utils"; const badgeVariants = cva("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs", { variants: { variant: { primary: "border-transparent bg-grayA-3 text-grayA-11 hover:bg-grayA-4", secondary: "border-border bg-grayA-2 text-grayA-11 hover:bg-grayA-3 font-normal", - success: "border-transparent bg-grayA-3 text-grayA-11 hover:bg-grayA-4", + success: "border-transparent bg-successA-3 text-successA-11 hover:bg-successA-4", warning: "border-transparent bg-warningA-3 text-warningA-11 hover:bg-warningA-4", blocked: "border-transparent bg-orangeA-3 text-orangeA-11 hover:bg-orangeA-4", error: "border-transparent bg-errorA-3 text-errorA-11 hover:bg-errorA-4", @@ -27,13 +29,15 @@ const badgeVariants = cva("inline-flex items-center rounded-md border px-2.5 py- }); export interface BadgeProps - extends React.HTMLAttributes, + extends React.HTMLAttributes, VariantProps {} -const Badge = forwardRef( - ({ className, variant, size, font, ...props }, ref) => { +const Badge = forwardRef( + ({ className, variant, size, font, children, ...props }, ref) => { return ( -
+ + {children} + ); }, ); diff --git a/internal/ui/src/index.ts b/internal/ui/src/index.ts index 04037e24c5..1ac2df9016 100644 --- a/internal/ui/src/index.ts +++ b/internal/ui/src/index.ts @@ -20,3 +20,4 @@ export * from "./components/tooltip"; export * from "./components/keyboard-button"; export * from "./components/separator"; export * from "./components/visible-button"; +export * from "./components/badge";