- Add shadcn/ui component library (button, card, input, popover, command, dialog, etc.) - Fix Tailwind CSS not scanning workspace packages by adding correct @source directives in globals.css (root cause: paths needed ../../../ not ../../ from apps/web/src/) - Improve secret selector: replace trigger button + separate search with single search input that expands into results on focus - Update auth sections across plugins to use rounded bordered containers
Showing the changes to plugins/openapi (1 of 46 files). Show all
Unified · Split
| @@ -13,8 +13,14 @@ import { · 12 unmodified lines | ||
| 13 | 13 | useWorkspaceRequestContext, |
| 14 | 14 | } from "@executor/react"; |
| 15 | 15 | import { |
| 16 | + Alert, | |
| 17 | + Button, | |
| 18 | + Card, | |
| 16 | 19 | DocumentPanel, |
| 17 | 20 | IconPencil, |
| 21 | + Input, | |
| 22 | + Label, | |
| 23 | + Select, | |
| 18 | 24 | SourceToolDetailPanel, |
| 19 | 25 | SourceToolExplorer, |
| 20 | 26 | parseSourceToolExplorerSearch, |
| @@ -381,63 +387,61 @@ function OpenApiSourceForm(props: { · 360 unmodified lines | ||
| 381 | 387 | }; |
| 382 | 388 | |
| 383 | 389 | return ( |
| 384 | − <div className="space-y-6 rounded-xl border border-border p-6"> | |
| 390 | + <Card className="space-y-6 p-6"> | |
| 385 | 391 | <Section title="Connection"> |
| 386 | 392 | <div className="grid gap-4"> |
| 387 | − <label className="grid gap-2"> | |
| 388 | − <span className="text-xs font-medium text-foreground">Name</span> | |
| 389 | − <input | |
| 393 | + <div className="grid gap-2"> | |
| 394 | + <Label>Name</Label> | |
| 395 | + <Input | |
| 390 | 396 | value={name} |
| 391 | 397 | onChange={(event) => { |
| 392 | 398 | setNameEdited(true); |
| 393 | 399 | setName(event.target.value); |
| 394 | 400 | }} |
| 395 | 401 | placeholder="GitHub REST" |
| 396 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground/40 focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 397 | 402 | /> |
| 398 | − </label> | |
| 403 | + </div> | |
| 399 | 404 | |
| 400 | − <label className="grid gap-2"> | |
| 401 | − <span className="text-xs font-medium text-foreground">Spec URL</span> | |
| 402 | − <input | |
| 405 | + <div className="grid gap-2"> | |
| 406 | + <Label>Spec URL</Label> | |
| 407 | + <Input | |
| 403 | 408 | value={specUrl} |
| 404 | 409 | onChange={(event) => setSpecUrl(event.target.value)} |
| 405 | 410 | onBlur={() => { |
| 406 | 411 | void runPreview({ mode: "manual" }); |
| 407 | 412 | }} |
| 408 | 413 | placeholder="https://example.com/openapi.json" |
| 409 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 font-mono text-xs text-foreground outline-none transition-colors placeholder:text-muted-foreground/40 focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 414 | + className="font-mono text-xs" | |
| 410 | 415 | /> |
| 411 | − </label> | |
| 416 | + </div> | |
| 412 | 417 | |
| 413 | − <label className="grid gap-2"> | |
| 414 | − <span className="text-xs font-medium text-foreground">Base URL</span> | |
| 415 | − <input | |
| 418 | + <div className="grid gap-2"> | |
| 419 | + <Label>Base URL</Label> | |
| 420 | + <Input | |
| 416 | 421 | value={baseUrl} |
| 417 | 422 | onChange={(event) => { |
| 418 | 423 | setBaseUrlEdited(true); |
| 419 | 424 | setBaseUrl(event.target.value); |
| 420 | 425 | }} |
| 421 | 426 | placeholder="https://api.example.com" |
| 422 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 font-mono text-xs text-foreground outline-none transition-colors placeholder:text-muted-foreground/40 focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 427 | + className="font-mono text-xs" | |
| 423 | 428 | /> |
| 424 | − </label> | |
| 429 | + </div> | |
| 425 | 430 | |
| 426 | − <label className="grid gap-2"> | |
| 427 | − <span className="text-xs font-medium text-foreground">Auth</span> | |
| 428 | − <select | |
| 431 | + <div className="grid gap-2"> | |
| 432 | + <Label>Auth</Label> | |
| 433 | + <Select | |
| 429 | 434 | value={authKind} |
| 430 | 435 | onChange={(event) => |
| 431 | 436 | setAuthKind(event.target.value as OpenApiConnectInput["auth"]["kind"])} |
| 432 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 text-sm text-foreground outline-none transition-colors focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 433 | 437 | > |
| 434 | 438 | <option value="none">None</option> |
| 435 | 439 | <option value="bearer">Bearer Secret</option> |
| 436 | − </select> | |
| 437 | − </label> | |
| 440 | + </Select> | |
| 441 | + </div> | |
| 438 | 442 | |
| 439 | 443 | {authKind === "bearer" && ( |
| 440 | − <div className="space-y-4 border-l-2 border-border pl-4"> | |
| 444 | + <div className="space-y-4 rounded-lg border border-border bg-muted/20 p-4"> | |
| 441 | 445 | <SecretReferenceField |
| 442 | 446 | label="Secret" |
| 443 | 447 | value={tokenSecretRef} |
| @@ -448,25 +452,25 @@ function OpenApiSourceForm(props: { · 4 unmodified lines | ||
| 448 | 452 | /> |
| 449 | 453 | |
| 450 | 454 | <div className="grid gap-4 sm:grid-cols-2"> |
| 451 | − <label className="grid gap-2"> | |
| 452 | − <span className="text-xs font-medium text-foreground">Header Name</span> | |
| 453 | − <input | |
| 455 | + <div className="grid gap-2"> | |
| 456 | + <Label>Header Name</Label> | |
| 457 | + <Input | |
| 454 | 458 | value={authHeaderName} |
| 455 | 459 | onChange={(event) => setAuthHeaderName(event.target.value)} |
| 456 | 460 | placeholder={DEFAULT_BEARER_HEADER_NAME} |
| 457 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 font-mono text-xs text-foreground outline-none transition-colors placeholder:text-muted-foreground/40 focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 461 | + className="font-mono text-xs" | |
| 458 | 462 | /> |
| 459 | − </label> | |
| 463 | + </div> | |
| 460 | 464 | |
| 461 | − <label className="grid gap-2"> | |
| 462 | − <span className="text-xs font-medium text-foreground">Prefix</span> | |
| 463 | − <input | |
| 465 | + <div className="grid gap-2"> | |
| 466 | + <Label>Prefix</Label> | |
| 467 | + <Input | |
| 464 | 468 | value={authPrefix} |
| 465 | 469 | onChange={(event) => setAuthPrefix(event.target.value)} |
| 466 | 470 | placeholder={DEFAULT_BEARER_PREFIX} |
| 467 | − className="h-9 w-full rounded-lg border border-input bg-background px-3 font-mono text-xs text-foreground outline-none transition-colors placeholder:text-muted-foreground/40 focus:border-ring focus:ring-1 focus:ring-ring/25" | |
| 471 | + className="font-mono text-xs" | |
| 468 | 472 | /> |
| 469 | − </label> | |
| 473 | + </div> | |
| 470 | 474 | </div> |
| 471 | 475 | </div> |
| 472 | 476 | )} |
| @@ -475,16 +479,16 @@ function OpenApiSourceForm(props: { · 2 unmodified lines | ||
| 475 | 479 | |
| 476 | 480 | <Section title="Preview"> |
| 477 | 481 | <div className="flex items-center gap-3"> |
| 478 | − <button | |
| 482 | + <Button | |
| 483 | + variant="outline" | |
| 479 | 484 | type="button" |
| 480 | 485 | onClick={() => { |
| 481 | 486 | void runPreview({ mode: "manual" }); |
| 482 | 487 | }} |
| 483 | 488 | disabled={previewMutation.status === "pending" || submitMutation.status === "pending"} |
| 484 | − className="inline-flex h-9 items-center justify-center rounded-lg border border-input bg-card px-3 text-sm font-medium text-foreground transition-colors hover:bg-accent/50 disabled:pointer-events-none disabled:opacity-50" | |
| 485 | 489 | > |
| 486 | 490 | {previewMutation.status === "pending" ? "Previewing..." : "Preview Spec"} |
| 487 | − </button> | |
| 491 | + </Button> | |
| 488 | 492 | {preview && ( |
| 489 | 493 | <div className="text-xs text-muted-foreground"> |
| 490 | 494 | {preview.operationCount} operations |
| @@ -519,33 +523,32 @@ function OpenApiSourceForm(props: { · 28 unmodified lines | ||
| 519 | 523 | )} |
| 520 | 524 | </dl> |
| 521 | 525 | {preview.warnings.length > 0 && ( |
| 522 | − <div className="mt-3 rounded-md border border-amber-300/40 bg-amber-100/20 px-3 py-2 text-xs text-amber-800"> | |
| 526 | + <Alert variant="warning" className="mt-3 text-xs"> | |
| 523 | 527 | {preview.warnings.join(" ")} |
| 524 | − </div> | |
| 528 | + </Alert> | |
| 525 | 529 | )} |
| 526 | 530 | </div> |
| 527 | 531 | )} |
| 528 | 532 | </Section> |
| 529 | 533 | |
| 530 | 534 | {error && ( |
| 531 | − <div className="rounded-lg border border-destructive/30 bg-destructive/8 px-4 py-2.5 text-sm text-destructive"> | |
| 535 | + <Alert variant="destructive"> | |
| 532 | 536 | {error} |
| 533 | − </div> | |
| 537 | + </Alert> | |
| 534 | 538 | )} |
| 535 | 539 | |
| 536 | 540 | <div className="flex items-center justify-end"> |
| 537 | − <button | |
| 541 | + <Button | |
| 538 | 542 | type="button" |
| 539 | 543 | onClick={() => { |
| 540 | 544 | void handleSubmit(); |
| 541 | 545 | }} |
| 542 | 546 | disabled={submitMutation.status === "pending"} |
| 543 | − className="inline-flex h-9 items-center justify-center rounded-lg bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 disabled:pointer-events-none disabled:opacity-50" | |
| 544 | 547 | > |
| 545 | 548 | {submitMutation.status === "pending" ? props.busyLabel : props.submitLabel} |
| 546 | − </button> | |
| 549 | + </Button> | |
| 547 | 550 | </div> |
| 548 | − </div> | |
| 551 | + </Card> | |
| 549 | 552 | ); |
| 550 | 553 | } |
| 551 | 554 | |
| @@ -641,9 +644,9 @@ function OpenApiEditSourcePageReady(props: { · 89 unmodified lines | ||
| 641 | 644 | if (Result.isFailure(configResult)) { |
| 642 | 645 | return ( |
| 643 | 646 | <Section title="Edit Source"> |
| 644 | − <div className="rounded-lg border border-destructive/30 bg-destructive/8 p-4 text-sm text-destructive"> | |
| 647 | + <Alert variant="destructive"> | |
| 645 | 648 | Failed loading source configuration. |
| 646 | − </div> | |
| 649 | + </Alert> | |
| 647 | 650 | </Section> |
| 648 | 651 | ); |
| 649 | 652 | } |
| @@ -778,38 +781,43 @@ function OpenApiSourceDetailPageReady(props: { · 128 unmodified lines | ||
| 778 | 781 | })} |
| 779 | 782 | actions={( |
| 780 | 783 | <> |
| 781 | − <button | |
| 784 | + <Button | |
| 785 | + variant="outline" | |
| 786 | + size="sm" | |
| 782 | 787 | type="button" |
| 783 | 788 | onClick={() => { |
| 784 | 789 | void refreshMutation.mutateAsync(props.source.id); |
| 785 | 790 | }} |
| 786 | 791 | disabled={refreshMutation.status === "pending"} |
| 787 | − className="inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground disabled:pointer-events-none disabled:opacity-50" | |
| 788 | 792 | > |
| 789 | 793 | {refreshMutation.status === "pending" ? "Refreshing..." : "Refresh"} |
| 790 | − </button> | |
| 791 | − <button | |
| 794 | + </Button> | |
| 795 | + <Button | |
| 796 | + variant="outline" | |
| 797 | + size="sm" | |
| 792 | 798 | type="button" |
| 793 | 799 | onClick={() => void navigation.edit(props.source.id)} |
| 794 | − className="inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground" | |
| 795 | 800 | > |
| 796 | 801 | <IconPencil className="size-3" /> |
| 797 | 802 | Edit |
| 798 | − </button> | |
| 803 | + </Button> | |
| 799 | 804 | {confirmDelete ? ( |
| 800 | 805 | <div className="flex items-center gap-2"> |
| 801 | 806 | <span className="text-[11px] font-medium text-destructive"> |
| 802 | 807 | Confirm delete? |
| 803 | 808 | </span> |
| 804 | − <button | |
| 809 | + <Button | |
| 810 | + variant="outline" | |
| 811 | + size="sm" | |
| 805 | 812 | type="button" |
| 806 | 813 | onClick={() => setConfirmDelete(false)} |
| 807 | 814 | disabled={removeMutation.status === "pending"} |
| 808 | − className="inline-flex items-center rounded-md border border-border bg-card px-2.5 py-1 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground disabled:pointer-events-none disabled:opacity-50" | |
| 809 | 815 | > |
| 810 | 816 | Cancel |
| 811 | − </button> | |
| 812 | − <button | |
| 817 | + </Button> | |
| 818 | + <Button | |
| 819 | + variant="destructive-outline" | |
| 820 | + size="sm" | |
| 813 | 821 | type="button" |
| 814 | 822 | onClick={() => { |
| 815 | 823 | void removeMutation.mutateAsync(props.source.id).then(() => { |
| @@ -821,20 +829,20 @@ function OpenApiSourceDetailPageReady(props: { · 5 unmodified lines | ||
| 821 | 829 | }); |
| 822 | 830 | }} |
| 823 | 831 | disabled={removeMutation.status === "pending"} |
| 824 | − className="inline-flex items-center rounded-md border border-destructive/25 bg-destructive/5 px-2.5 py-1 text-[12px] font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:pointer-events-none disabled:opacity-50" | |
| 825 | 832 | > |
| 826 | 833 | {removeMutation.status === "pending" ? "Deleting..." : "Delete"} |
| 827 | − </button> | |
| 834 | + </Button> | |
| 828 | 835 | </div> |
| 829 | 836 | ) : ( |
| 830 | − <button | |
| 837 | + <Button | |
| 838 | + variant="destructive-outline" | |
| 839 | + size="sm" | |
| 831 | 840 | type="button" |
| 832 | 841 | onClick={() => setConfirmDelete(true)} |
| 833 | 842 | disabled={removeMutation.status === "pending"} |
| 834 | − className="inline-flex items-center rounded-md border border-destructive/25 bg-destructive/5 px-2.5 py-1 text-[12px] font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:pointer-events-none disabled:opacity-50" | |
| 835 | 843 | > |
| 836 | 844 | Delete |
| 837 | − </button> | |
| 845 | + </Button> | |
| 838 | 846 | )} |
| 839 | 847 | </> |
| 840 | 848 | )} |