feature: migrate to v3 badge, additional badge stories, re-useable documentation link badge and misc styling fixes/improvements

This commit is contained in:
Scott Wilson
2025-10-24 19:27:28 -07:00
parent 6c04dd1937
commit 01d6f5d35e
155 changed files with 1267 additions and 1740 deletions
@@ -1,10 +1,12 @@
import { faBan, faCheck, faEdit, faPlugCircleXmark } from "@fortawesome/free-solid-svg-icons";
import { faEdit } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { BanIcon, CheckIcon, UnplugIcon } from "lucide-react";
import { ProjectPermissionCan } from "@app/components/permissions";
import { EditSecretScanningDataSourceModal } from "@app/components/secret-scanning";
import { GenericFieldLabel } from "@app/components/secret-syncs";
import { Badge, IconButton, Tooltip } from "@app/components/v2";
import { IconButton, Tooltip } from "@app/components/v2";
import { Badge } from "@app/components/v3";
import { ProjectPermissionSub } from "@app/context";
import { ProjectPermissionSecretScanningDataSourceActions } from "@app/context/ProjectPermissionContext/types";
import { usePopUp } from "@app/hooks";
@@ -33,12 +35,9 @@ export const SecretScanningDataSourceSection = ({ dataSource }: Props) => {
content="The external data source has been removed and can no longer be scanned. Delete this data source and re-initialize the connection."
>
<div className="ml-auto">
<Badge
variant="danger"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faPlugCircleXmark} />
<span>Disconnected</span>
<Badge variant="danger">
<UnplugIcon />
Disconnected
</Badge>
</div>
</Tooltip>
@@ -71,17 +70,14 @@ export const SecretScanningDataSourceSection = ({ dataSource }: Props) => {
<DataSourceConfigDisplay dataSource={dataSource} />
<GenericFieldLabel label="Auto-Scan">
{isAutoScanEnabled ? (
<Badge
variant="success"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faCheck} />
<span>Enabled</span>
<Badge variant="success">
<CheckIcon />
Enabled
</Badge>
) : (
<Badge className="flex h-5 w-min items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Disabled</span>
<Badge variant="neutral">
<BanIcon />
Disabled
</Badge>
)}
</GenericFieldLabel>
@@ -1,24 +1,21 @@
import { useCallback } from "react";
import {
faBan,
faCheck,
faCopy,
faEllipsisV,
faExpand,
faInfoCircle,
faSearch,
faWarning
faInfoCircle
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNavigate } from "@tanstack/react-router";
import { formatDistance } from "date-fns";
import { AlertTriangleIcon, BanIcon, ScanTextIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import { SecretScanningScanStatusBadge } from "@app/components/secret-scanning";
import {
Badge,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@@ -28,6 +25,7 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { Badge } from "@app/components/v3";
import {
ProjectPermissionSecretScanningDataSourceActions,
ProjectPermissionSub
@@ -141,45 +139,38 @@ export const SecretScanningResourceRow = ({ resource, dataSource }: Props) => {
<Td>
{/* eslint-disable-next-line no-nested-ternary */}
{lastScanStatus?.match(/queued|scanning/) ? (
<Badge
variant="primary"
className="flex h-5 w-min animate-pulse items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300"
>
<FontAwesomeIcon icon={faSearch} />
<span>Scanning For Leaks</span>
<Badge variant="neutral">
<ScanTextIcon />
Scanning For Leaks
</Badge>
) : // eslint-disable-next-line no-nested-ternary
lastScannedAt ? (
// eslint-disable-next-line no-nested-ternary
unresolvedFindings ? (
<Badge
onClick={() =>
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId: dataSource.projectId
},
search: {
search: name,
status: SecretScanningFindingStatus.Unresolved
}
})
}
variant="primary"
className="flex h-5 w-min cursor-pointer items-center gap-1.5 whitespace-nowrap"
>
<FontAwesomeIcon icon={faWarning} />
<span>
<Badge asChild variant="warning">
<button
type="button"
onClick={() =>
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId: dataSource.projectId
},
search: {
search: name,
status: SecretScanningFindingStatus.Unresolved
}
})
}
>
<AlertTriangleIcon />
{unresolvedFindings} Secret{unresolvedFindings > 1 ? "s" : ""} Detected
</span>
</button>
</Badge>
) : lastScanStatus === SecretScanningScanStatus.Failed ? (
<span className="text-mineshaft-400">No findings</span>
) : (
<Badge
variant="success"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<Badge variant="success">
<FontAwesomeIcon icon={faCheck} />
No Secrets Detected
</Badge>
@@ -209,12 +200,10 @@ export const SecretScanningResourceRow = ({ resource, dataSource }: Props) => {
className="text-xs"
content={`This ${resourceDetails.singularNoun} will not be scanned due to exclusion in Data Source configuration.`}
>
<div className="ml-auto">
<Badge className="flex h-5 w-min items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Inactive</span>
</Badge>
</div>
<Badge className="ml-auto" variant="neutral">
<BanIcon />
Inactive
</Badge>
</Tooltip>
)}
<Tooltip className="max-w-sm text-center" content="Options">
@@ -1,14 +1,14 @@
import { useCallback } from "react";
import { faCheck, faCopy, faEllipsisV, faWarning } from "@fortawesome/free-solid-svg-icons";
import { faCheck, faCopy, faEllipsisV } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNavigate } from "@tanstack/react-router";
import { format } from "date-fns";
import { AlertTriangleIcon, CheckIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications";
import { SecretScanningScanStatusBadge } from "@app/components/secret-scanning";
import {
Badge,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@@ -18,6 +18,7 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { Badge } from "@app/components/v3";
import { useProject } from "@app/context";
import { useToggle } from "@app/hooks";
import {
@@ -92,40 +93,33 @@ export const SecretScanningScanRow = ({ scan }: Props) => {
) : // eslint-disable-next-line no-nested-ternary
totalFindings ? (
<div className="flex flex-col">
<Badge
onClick={() =>
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId: currentProject.id
},
search: {
search: `scanId:${id}`
}
})
}
variant={unresolvedFindings ? "primary" : undefined}
className={twMerge(
"flex h-5 w-min cursor-pointer items-center gap-1.5 whitespace-nowrap",
!unresolvedFindings && "bg-mineshaft-400/50 text-bunker-300"
)}
>
<FontAwesomeIcon icon={unresolvedFindings ? faWarning : faCheck} />
<span className="text-xs">
<Badge asChild variant={unresolvedFindings ? "warning" : "success"}>
<button
type="button"
onClick={() =>
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId: currentProject.id
},
search: {
search: `scanId:${id}`
}
})
}
>
{unresolvedFindings ? <AlertTriangleIcon /> : <CheckIcon />}
{totalFindings}{" "}
{unresolvedFindings
? `Secret${totalFindings > 1 ? "s" : ""} Detected`
: "Leak Resolved"}
</span>
</button>
</Badge>
</div>
) : status === SecretScanningScanStatus.Failed ? (
<span className="text-mineshaft-400">No findings</span>
) : (
<Badge
variant="success"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<Badge variant="success">
<FontAwesomeIcon icon={faCheck} />
No Secrets Detected
</Badge>
@@ -1,6 +1,5 @@
import { useCallback } from "react";
import {
faBan,
faCheck,
faCopy,
faEdit,
@@ -8,22 +7,20 @@ import {
faExpand,
faInfoCircle,
faPlugCircleXmark,
faSearch,
faToggleOff,
faToggleOn,
faTrash,
faWarning
faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNavigate } from "@tanstack/react-router";
import { formatDistance } from "date-fns";
import { AlertTriangleIcon, BanIcon, ScanTextIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import { SecretScanningScanStatusBadge } from "@app/components/secret-scanning";
import {
Badge,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@@ -33,6 +30,7 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { Badge } from "@app/components/v3";
import { ROUTE_PATHS } from "@app/const/routes";
import { ProjectPermissionSub } from "@app/context";
import { ProjectPermissionSecretScanningDataSourceActions } from "@app/context/ProjectPermissionContext/types";
@@ -139,46 +137,39 @@ export const SecretScanningDataSourceRow = ({
<Td>
{/* eslint-disable-next-line no-nested-ternary */}
{lastScanStatus?.match(/queued|scanning/) ? (
<Badge
variant="primary"
className="flex h-5 w-min animate-pulse items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300"
>
<FontAwesomeIcon icon={faSearch} />
<span>Scanning For Leaks</span>
<Badge variant="neutral">
<ScanTextIcon />
Scanning For Leaks
</Badge>
) : // eslint-disable-next-line no-nested-ternary
lastScannedAt ? (
// eslint-disable-next-line no-nested-ternary
unresolvedFindings ? (
<Badge
variant="primary"
className="flex h-5 w-min cursor-pointer items-center gap-1.5 whitespace-nowrap"
onClick={(e) => {
e.stopPropagation();
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId
},
search: {
search: name,
status: SecretScanningFindingStatus.Unresolved
}
});
}}
>
<FontAwesomeIcon icon={faWarning} />
<span>
<Badge variant="warning" asChild>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
navigate({
to: "/projects/secret-scanning/$projectId/findings",
params: {
projectId
},
search: {
search: name,
status: SecretScanningFindingStatus.Unresolved
}
});
}}
>
<AlertTriangleIcon />
{unresolvedFindings} Secret{unresolvedFindings > 1 ? "s" : ""} Detected
</span>
</button>
</Badge>
) : lastScanStatus === SecretScanningScanStatus.Failed ? (
<span className="text-mineshaft-400">No findings</span>
) : (
<Badge
variant="success"
className="flex h-5 w-min items-center gap-1.5 whitespace-nowrap"
>
<Badge variant="success">
<FontAwesomeIcon icon={faCheck} />
No Secrets Detected
</Badge>
@@ -206,12 +197,10 @@ export const SecretScanningDataSourceRow = ({
className="text-xs"
content={`Auto-Scan is disabled. Scans will not be automatically triggered when a ${autoScanDescription.verb} occurs to ${autoScanDescription.pluralNoun} associated with this data source`}
>
<div className="ml-auto">
<Badge className="flex h-5 w-min items-center gap-1.5 bg-mineshaft-400/50 whitespace-nowrap text-bunker-300">
<FontAwesomeIcon icon={faBan} />
<span>Auto-Scan Disabled</span>
</Badge>
</div>
<Badge className="ml-auto" variant="neutral">
<BanIcon />
Auto-Scan Disabled
</Badge>
</Tooltip>
)}
{isDisconnected && (
@@ -1,10 +1,11 @@
import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
import { ProjectPermissionCan } from "@app/components/permissions";
import { CreateSecretScanningDataSourceModal } from "@app/components/secret-scanning";
import { Button, Spinner } from "@app/components/v2";
import { DocumentationLinkBadge } from "@app/components/v3";
import { ProjectPermissionSub, useProject, useSubscription } from "@app/context";
import { ProjectPermissionSecretScanningDataSourceActions } from "@app/context/ProjectPermissionContext/types";
import { usePopUp } from "@app/hooks";
@@ -40,22 +41,9 @@ export const SecretScanningDataSourcesSection = () => {
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div>
<div className="flex items-center gap-1">
<div className="flex items-center gap-x-2">
<p className="text-xl font-medium text-mineshaft-100">Data Sources</p>
<a
href="https://infisical.com/docs/documentation/platform/secret-scanning/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="mt-[0.32rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/secret-scanning/overview" />
</div>
<p className="text-sm text-bunker-300">
Configure Data Sources to scan for secret leaks from third-party services.
@@ -7,7 +7,6 @@ import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import {
Badge,
Button,
Checkbox,
DropdownMenu,
@@ -20,19 +19,17 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { Badge } from "@app/components/v3";
import {
ProjectPermissionSecretScanningFindingActions,
ProjectPermissionSub
} from "@app/context/ProjectPermissionContext/types";
import {
SECRET_SCANNING_DATA_SOURCE_MAP,
SECRET_SCANNING_FINDING_STATUS_ICON_MAP
SECRET_SCANNING_FINDING_STATUS_MAP
} from "@app/helpers/secretScanningV2";
import { useToggle } from "@app/hooks";
import {
SecretScanningFindingStatus,
TSecretScanningFinding
} from "@app/hooks/api/secretScanningV2";
import { TSecretScanningFinding } from "@app/hooks/api/secretScanningV2";
type Props = {
isSelected: boolean;
@@ -83,6 +80,8 @@ export const SecretScanningFindingRow = ({
const [isExpanded, setIsExpanded] = useToggle(false);
const StatusIcon = SECRET_SCANNING_FINDING_STATUS_MAP[status].Icon;
return (
<>
<Tr
@@ -127,20 +126,10 @@ export const SecretScanningFindingRow = ({
<Td className="whitespace-nowrap">{rule}</Td>
<Td className="whitespace-nowrap">
<Tooltip position="left" content={remarks}>
<div className="w-min">
<Badge
variant={status === SecretScanningFindingStatus.Resolved ? "success" : "primary"}
className={twMerge(
"flex h-5 w-min items-center gap-1.5 whitespace-nowrap",
(status === SecretScanningFindingStatus.FalsePositive ||
status === SecretScanningFindingStatus.Ignore) &&
"bg-mineshaft-400/50 text-bunker-300"
)}
>
<FontAwesomeIcon icon={SECRET_SCANNING_FINDING_STATUS_ICON_MAP[status].icon} />
<span className="capitalize">{status.replace("-", " ")}</span>
</Badge>
</div>
<Badge variant={SECRET_SCANNING_FINDING_STATUS_MAP[status].variant}>
<StatusIcon />
<span className="capitalize">{status.replace("-", " ")}</span>
</Badge>
</Tooltip>
</Td>
<Td>
@@ -172,7 +161,7 @@ export const SecretScanningFindingRow = ({
</Td>
</Tr>
<Tr>
<Td colSpan={6} className="border-none! p-0">
<Td colSpan={7} className="border-none! p-0">
<div
className={`w-full overflow-hidden bg-mineshaft-900/75 transition-all duration-500 ${
isExpanded ? "max-h-200 opacity-100" : "max-h-0"
@@ -225,9 +214,11 @@ export const SecretScanningFindingRow = ({
colorSchema="secondary"
isDisabled={!isAllowed}
leftIcon={
<FontAwesomeIcon
className={SECRET_SCANNING_FINDING_STATUS_ICON_MAP[status].className}
icon={SECRET_SCANNING_FINDING_STATUS_ICON_MAP[status].icon}
<StatusIcon
className={twMerge(
"size-4",
SECRET_SCANNING_FINDING_STATUS_MAP[status].className
)}
/>
}
>
@@ -1,7 +1,5 @@
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ContentLoader } from "@app/components/v2";
import { DocumentationLinkBadge } from "@app/components/v3";
import { useProject } from "@app/context";
import { useListSecretScanningFindings } from "@app/hooks/api/secretScanningV2";
@@ -23,22 +21,9 @@ export const SecretScanningFindingsSection = () => {
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div>
<div className="flex items-center gap-1">
<div className="flex items-center gap-x-2">
<p className="text-xl font-medium text-mineshaft-100">Findings</p>
<a
href="https://infisical.com/docs/documentation/platform/secret-scanning/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="mt-[0.32rem] ml-1 inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/secret-scanning/usage#findings" />
</div>
<p className="text-sm text-bunker-300">
Secret leaks discovered across your data sources
@@ -38,7 +38,7 @@ import {
} from "@app/context/ProjectPermissionContext/types";
import {
SECRET_SCANNING_DATA_SOURCE_MAP,
SECRET_SCANNING_FINDING_STATUS_ICON_MAP
SECRET_SCANNING_FINDING_STATUS_MAP
} from "@app/helpers/secretScanningV2";
import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
import { OrderByDirection } from "@app/hooks/api/generic/types";
@@ -219,34 +219,40 @@ export const SecretScanningFindingsTable = ({ findings }: Props) => {
</DropdownMenuTrigger>
<DropdownMenuContent className="max-h-[70vh] thin-scrollbar overflow-y-auto" align="end">
<DropdownMenuLabel>Status</DropdownMenuLabel>
{Object.values(SecretScanningFindingStatus).map((status) => (
<DropdownMenuItem
onClick={(e) => {
e.preventDefault();
setFilters((prev) => ({
...prev,
status: prev.status.includes(status)
? prev.status.filter((s) => s !== status)
: [...prev.status, status]
}));
}}
key={status}
icon={
filters.status.includes(status) && (
<FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
)
}
iconPos="right"
>
<div className="flex items-center gap-2">
<FontAwesomeIcon
icon={SECRET_SCANNING_FINDING_STATUS_ICON_MAP[status].icon}
className={SECRET_SCANNING_FINDING_STATUS_ICON_MAP[status].className}
/>
<span className="capitalize">{status.replace("-", " ")}</span>
</div>
</DropdownMenuItem>
))}
{Object.values(SecretScanningFindingStatus).map((status) => {
const { Icon } = SECRET_SCANNING_FINDING_STATUS_MAP[status];
return (
<DropdownMenuItem
onClick={(e) => {
e.preventDefault();
setFilters((prev) => ({
...prev,
status: prev.status.includes(status)
? prev.status.filter((s) => s !== status)
: [...prev.status, status]
}));
}}
key={status}
icon={
filters.status.includes(status) && (
<FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
)
}
iconPos="right"
>
<div className="flex items-center gap-2">
<Icon
className={twMerge(
SECRET_SCANNING_FINDING_STATUS_MAP[status].className,
"size-3.5"
)}
/>
<span className="capitalize">{status.replace("-", " ")}</span>
</div>
</DropdownMenuItem>
);
})}
<DropdownMenuLabel>Platform</DropdownMenuLabel>
{findings.length ? (
[...new Set(findings.map(({ dataSourceType: type }) => type))].map((type) => {
@@ -13,7 +13,7 @@ import {
SelectItem,
TextArea
} from "@app/components/v2";
import { SECRET_SCANNING_FINDING_STATUS_ICON_MAP } from "@app/helpers/secretScanningV2";
import { SECRET_SCANNING_FINDING_STATUS_MAP } from "@app/helpers/secretScanningV2";
import {
SecretScanningFindingStatus,
TSecretScanningFinding,
@@ -105,9 +105,9 @@ const Content = ({ findings, onComplete }: ContentProps) => {
className="w-full border border-mineshaft-500 capitalize"
position="popper"
dropdownContainerClassName="max-w-none"
icon={value ? SECRET_SCANNING_FINDING_STATUS_ICON_MAP[value].icon : undefined}
LucideIcon={value ? SECRET_SCANNING_FINDING_STATUS_MAP[value].Icon : undefined}
iconClassName={
value ? SECRET_SCANNING_FINDING_STATUS_ICON_MAP[value].className : undefined
value ? SECRET_SCANNING_FINDING_STATUS_MAP[value].className : undefined
}
>
{Object.values(SecretScanningFindingStatus).map((status) => {
@@ -1,12 +1,11 @@
import { Controller, useForm } from "react-hook-form";
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import { Button, FormControl, TextArea } from "@app/components/v2";
import { DocumentationLinkBadge } from "@app/components/v3";
import { ProjectPermissionSub } from "@app/context";
import { ProjectPermissionSecretScanningConfigActions } from "@app/context/ProjectPermissionContext/types";
import {
@@ -62,21 +61,7 @@ export const SecretScanningConfigForm = ({ config }: Props) => {
<div className="mb-4">
<div className="flex items-center gap-2">
<h2 className="text-xl font-medium text-mineshaft-100">Project Configuration</h2>
<a
target="_blank"
href="https://infisical.com/docs/documentation/platform/secret-scanning/overview#configuration"
className="mt-[0.02rem]"
rel="noopener noreferrer"
>
<div className="inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1 mb-[0.03rem] text-[12px]" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1 text-[10px]"
/>
</div>
</a>
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/secret-scanning/usage#configuration" />
</div>
<p className="leading-5 text-mineshaft-400">
Configure rules and exceptions to customize scanning