- {tag.length > 15 ? `${tag.substring(0, 12)}...` : tag}
+ {shortenId(tag, {
+ endChars: 0,
+ minLength: 14,
+ startChars: 10,
+ })}
))
diff --git a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/_components/components/table/keys-list.tsx b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/_components/components/table/keys-list.tsx
index 980f410785..5bdfa1f9ed 100644
--- a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/_components/components/table/keys-list.tsx
+++ b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/_components/components/table/keys-list.tsx
@@ -1,6 +1,7 @@
"use client";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
+import { shortenId } from "@/lib/shorten-id";
import type { KeyDetails } from "@/lib/trpc/routers/api/keys/query-api-keys/schema";
import { BookBookmark, Dots, Focus, Key } from "@unkey/icons";
import { Button, Checkbox, Empty, InfoTooltip, Loading } from "@unkey/ui";
@@ -182,8 +183,7 @@ export const KeysList = ({
}}
>
- {key.id.substring(0, 8)}...
- {key.id.substring(key.id.length - 4)}
+ {shortenId(key.id)}
{key.name && (
diff --git a/apps/dashboard/app/(app)/audit/components/controls/components/logs-filters/components/root-keys-filter.tsx b/apps/dashboard/app/(app)/audit/components/controls/components/logs-filters/components/root-keys-filter.tsx
index 575673aa4c..67cb6b8bdd 100644
--- a/apps/dashboard/app/(app)/audit/components/controls/components/logs-filters/components/root-keys-filter.tsx
+++ b/apps/dashboard/app/(app)/audit/components/controls/components/logs-filters/components/root-keys-filter.tsx
@@ -1,5 +1,6 @@
import { useFilters } from "@/app/(app)/audit/hooks/use-filters";
import { FilterCheckbox } from "@/components/logs/checkbox/filter-checkbox";
+import { shortenId } from "@/lib/shorten-id";
export const RootKeysFilter = ({
rootKeys,
@@ -37,10 +38,5 @@ export const RootKeysFilter = ({
// This is to avoid displaying the full id in the filter.
const getRootKeyLabel = (rootKey: { id: string; name: string | null }) => {
const id = rootKey.id;
- const prefix = id.substring(0, id.indexOf("_") + 1);
- const obfuscatedMiddle =
- id.substring(id.indexOf("_") + 1, id.indexOf("_") + 5).length > 0 ? "..." : "";
- const nextFour = id.substring(id.indexOf("_") + 1, id.indexOf("_") + 5);
- const lastFour = id.substring(id.length - 4);
- return rootKey.name ?? prefix + nextFour + obfuscatedMiddle + lastFour;
+ return rootKey.name ?? shortenId(id);
};
diff --git a/apps/dashboard/lib/shorten-id.ts b/apps/dashboard/lib/shorten-id.ts
new file mode 100644
index 0000000000..172afa5c8c
--- /dev/null
+++ b/apps/dashboard/lib/shorten-id.ts
@@ -0,0 +1,48 @@
+/**
+ * Shortens an ID by keeping a specified number of characters from the start and end,
+ * with customizable separator in between.
+ */
+export function shortenId(
+ id: string,
+ options: {
+ /** Number of characters to keep from the start (default: 8) */
+ startChars?: number;
+ /** Number of characters to keep from the end (default: 4) */
+ endChars?: number;
+ /** Separator between start and end (default: "...") */
+ separator?: string;
+ /** Minimum length required to apply shortening (default: startChars + endChars + 3) */
+ minLength?: number;
+ } = {},
+): string {
+ const {
+ startChars = 8,
+ endChars = 4,
+ separator = "...",
+ minLength = startChars + endChars + 3,
+ } = options;
+
+ // Validate inputs
+ if (startChars < 0 || endChars < 0) {
+ throw new Error("startChars and endChars must be non-negative");
+ }
+
+ if (startChars + endChars === 0) {
+ throw new Error("At least one of startChars or endChars must be greater than 0");
+ }
+
+ // Return original if too short to meaningfully shorten
+ if (id.length <= minLength) {
+ return id;
+ }
+
+ // Handle edge case where requested chars exceed ID length
+ if (startChars + endChars >= id.length) {
+ return id;
+ }
+
+ const start = id.substring(0, startChars);
+ const end = id.substring(id.length - endChars);
+
+ return `${start}${separator}${end}`;
+}