Add docs button to the API-key connect dialog

The Add Source card links to a connector's docs, but the API-key
connect dialog did not, so a user filling in an API key had no path
to the setup instructions. Add a "Documentation" button to the dialog
footer, styled like Cancel and on the left of the Cancel/Connect row,
shown only when the provider has a docs page.

Extract the rendering into a shared ConnectorDocumentationLink
component with a link/button variant (the card keeps the quiet link,
the dialog uses the button) and give DialogFooter an optional start
slot for left-aligned footer content.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
Aurélien Sibiril
2026-07-24 14:27:48 +02:00
parent b1a67aba00
commit fa3b7dc2b3
4 changed files with 95 additions and 18 deletions

View File

@@ -29,7 +29,6 @@ import {
DialogContent,
DialogFooter,
DropdownItem,
IconArrowLink,
Input,
ThirdPartyLogo,
useDialogRef,
@@ -42,6 +41,7 @@ import type { AddAccessReviewSourceDialogConnectorProviderInfoFragment$data } fr
import { APIKeyConnectorDialog } from "./_components/APIKeyConnectorDialog";
import { ClientCredentialsConnectorDialog } from "./_components/ClientCredentialsConnectorDialog";
import { ConnectorDocumentationLink } from "./_components/ConnectorDocumentationLink";
import {
DatadogConnectDialog,
ZendeskConnectDialog,
@@ -162,17 +162,7 @@ export function AddAccessReviewSourceDialog({
<ThirdPartyLogo thirdParty={info.provider} tint className="size-6 shrink-0" />
<div className="mr-auto">
<h3 className="font-medium">{info.displayName}</h3>
{info.documentationUrl && (
<a
href={info.documentationUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-xs text-txt-tertiary underline hover:no-underline"
>
{__("Documentation")}
<IconArrowLink size={12} />
</a>
)}
<ConnectorDocumentationLink url={info.documentationUrl} />
</div>
{isConnected
? (

View File

@@ -48,6 +48,8 @@ import {
PostHogDeploymentField,
} from "../PostHogDeploymentField";
import { ConnectorDocumentationLink } from "./ConnectorDocumentationLink";
const createAPIKeyConnectorMutation = graphql`
mutation APIKeyConnectorDialogCreateAPIKeyConnectorMutation(
$input: CreateAPIKeyConnectorInput!
@@ -415,7 +417,18 @@ export function APIKeyConnectorDialog({
</div>
)}
</DialogContent>
<DialogFooter>
<DialogFooter
start={
provider?.documentationUrl
? (
<ConnectorDocumentationLink
url={provider.documentationUrl}
variant="button"
/>
)
: undefined
}
>
<Button
type="submit"
disabled={

View File

@@ -0,0 +1,66 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import { useTranslate } from "@probo/i18n";
import { Button, IconArrowLink } from "@probo/ui";
type Props = {
url?: string | null;
// "link" (default) is a quiet inline text link for the provider card;
// "button" is a secondary button that sits next to Cancel/Connect in a
// connect dialog footer. Both open the docs page in a new tab.
variant?: "link" | "button";
};
// A "Documentation" link to a connector's probo.com docs page, or nothing when
// the provider has no documentation URL. Shared by the provider card and the
// connect dialogs so the URL/label/target markup lives in one place.
export function ConnectorDocumentationLink({ url, variant = "link" }: Props) {
const { __ } = useTranslate();
if (!url) {
return null;
}
if (variant === "button") {
// asChild styles the anchor as a secondary button (matching Cancel); the
// button base supplies the flex + gap that spaces the label and icon.
return (
<Button variant="secondary" asChild>
<a href={url} target="_blank" rel="noopener noreferrer">
{__("Documentation")}
<IconArrowLink size={16} />
</a>
</Button>
);
}
return (
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-xs text-txt-tertiary underline hover:no-underline"
>
{__("Documentation")}
<IconArrowLink size={12} />
</a>
);
}

View File

@@ -195,19 +195,27 @@ export function DialogFooter({
children,
exitLabel,
className,
start,
}: {
children?: ReactNode;
exitLabel?: string;
className?: string;
// Optional content aligned to the footer's left edge (e.g. a documentation
// link), on the same line as the Cancel/confirm buttons. When set, the footer
// switches to justify-between; otherwise it keeps the default right alignment.
start?: ReactNode;
}) {
const { __ } = useTranslate();
const { footer } = dialog();
return (
<footer className={footer({ className })}>
<Close asChild>
<Button variant="secondary">{exitLabel ?? __("Cancel")}</Button>
</Close>
{children}
<footer className={footer({ className: clsx(start != null && "justify-between", className) })}>
{start != null && <div className="flex items-center gap-2">{start}</div>}
<div className="flex items-center gap-2">
<Close asChild>
<Button variant="secondary">{exitLabel ?? __("Cancel")}</Button>
</Close>
{children}
</div>
</footer>
);
}