History

Add shadcn UI components, fix Tailwind monorepo scanning, improve secret selector UX

- 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

Rhys Sullivan committed 7 months ago

Commit 05b2c841 parent 3fea5fb46 files · +1905 −792Browse files

Showing the changes to plugins/openapi (1 of 46 files). Show all

Unified · Split

plugins/openapi/react/components.tsx+69−61
@@ -13,8 +13,14 @@ import { · 12 unmodified lines
1313 useWorkspaceRequestContext,
1414 } from "@executor/react";
1515 import {
16+ Alert,
17+ Button,
18+ Card,
1619 DocumentPanel,
1720 IconPencil,
21+ Input,
22+ Label,
23+ Select,
1824 SourceToolDetailPanel,
1925 SourceToolExplorer,
2026 parseSourceToolExplorerSearch,
@@ -381,63 +387,61 @@ function OpenApiSourceForm(props: { · 360 unmodified lines
381387 };
382388
383389 return (
384− <div className="space-y-6 rounded-xl border border-border p-6">
390+ <Card className="space-y-6 p-6">
385391 <Section title="Connection">
386392 <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
390396 value={name}
391397 onChange={(event) => {
392398 setNameEdited(true);
393399 setName(event.target.value);
394400 }}
395401 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"
397402 />
398− </label>
403+ </div>
399404
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
403408 value={specUrl}
404409 onChange={(event) => setSpecUrl(event.target.value)}
405410 onBlur={() => {
406411 void runPreview({ mode: "manual" });
407412 }}
408413 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"
410415 />
411− </label>
416+ </div>
412417
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
416421 value={baseUrl}
417422 onChange={(event) => {
418423 setBaseUrlEdited(true);
419424 setBaseUrl(event.target.value);
420425 }}
421426 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"
423428 />
424− </label>
429+ </div>
425430
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
429434 value={authKind}
430435 onChange={(event) =>
431436 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"
433437 >
434438 <option value="none">None</option>
435439 <option value="bearer">Bearer Secret</option>
436− </select>
437− </label>
440+ </Select>
441+ </div>
438442
439443 {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">
441445 <SecretReferenceField
442446 label="Secret"
443447 value={tokenSecretRef}
@@ -448,25 +452,25 @@ function OpenApiSourceForm(props: { · 4 unmodified lines
448452 />
449453
450454 <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
454458 value={authHeaderName}
455459 onChange={(event) => setAuthHeaderName(event.target.value)}
456460 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"
458462 />
459− </label>
463+ </div>
460464
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
464468 value={authPrefix}
465469 onChange={(event) => setAuthPrefix(event.target.value)}
466470 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"
468472 />
469− </label>
473+ </div>
470474 </div>
471475 </div>
472476 )}
@@ -475,16 +479,16 @@ function OpenApiSourceForm(props: { · 2 unmodified lines
475479
476480 <Section title="Preview">
477481 <div className="flex items-center gap-3">
478− <button
482+ <Button
483+ variant="outline"
479484 type="button"
480485 onClick={() => {
481486 void runPreview({ mode: "manual" });
482487 }}
483488 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"
485489 >
486490 {previewMutation.status === "pending" ? "Previewing..." : "Preview Spec"}
487− </button>
491+ </Button>
488492 {preview && (
489493 <div className="text-xs text-muted-foreground">
490494 {preview.operationCount} operations
@@ -519,33 +523,32 @@ function OpenApiSourceForm(props: { · 28 unmodified lines
519523 )}
520524 </dl>
521525 {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">
523527 {preview.warnings.join(" ")}
524− </div>
528+ </Alert>
525529 )}
526530 </div>
527531 )}
528532 </Section>
529533
530534 {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">
532536 {error}
533− </div>
537+ </Alert>
534538 )}
535539
536540 <div className="flex items-center justify-end">
537− <button
541+ <Button
538542 type="button"
539543 onClick={() => {
540544 void handleSubmit();
541545 }}
542546 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"
544547 >
545548 {submitMutation.status === "pending" ? props.busyLabel : props.submitLabel}
546− </button>
549+ </Button>
547550 </div>
548− </div>
551+ </Card>
549552 );
550553 }
551554
@@ -641,9 +644,9 @@ function OpenApiEditSourcePageReady(props: { · 89 unmodified lines
641644 if (Result.isFailure(configResult)) {
642645 return (
643646 <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">
645648 Failed loading source configuration.
646− </div>
649+ </Alert>
647650 </Section>
648651 );
649652 }
@@ -778,38 +781,43 @@ function OpenApiSourceDetailPageReady(props: { · 128 unmodified lines
778781 })}
779782 actions={(
780783 <>
781− <button
784+ <Button
785+ variant="outline"
786+ size="sm"
782787 type="button"
783788 onClick={() => {
784789 void refreshMutation.mutateAsync(props.source.id);
785790 }}
786791 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"
788792 >
789793 {refreshMutation.status === "pending" ? "Refreshing..." : "Refresh"}
790− </button>
791− <button
794+ </Button>
795+ <Button
796+ variant="outline"
797+ size="sm"
792798 type="button"
793799 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"
795800 >
796801 <IconPencil className="size-3" />
797802 Edit
798− </button>
803+ </Button>
799804 {confirmDelete ? (
800805 <div className="flex items-center gap-2">
801806 <span className="text-[11px] font-medium text-destructive">
802807 Confirm delete?
803808 </span>
804− <button
809+ <Button
810+ variant="outline"
811+ size="sm"
805812 type="button"
806813 onClick={() => setConfirmDelete(false)}
807814 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"
809815 >
810816 Cancel
811− </button>
812− <button
817+ </Button>
818+ <Button
819+ variant="destructive-outline"
820+ size="sm"
813821 type="button"
814822 onClick={() => {
815823 void removeMutation.mutateAsync(props.source.id).then(() => {
@@ -821,20 +829,20 @@ function OpenApiSourceDetailPageReady(props: { · 5 unmodified lines
821829 });
822830 }}
823831 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"
825832 >
826833 {removeMutation.status === "pending" ? "Deleting..." : "Delete"}
827− </button>
834+ </Button>
828835 </div>
829836 ) : (
830− <button
837+ <Button
838+ variant="destructive-outline"
839+ size="sm"
831840 type="button"
832841 onClick={() => setConfirmDelete(true)}
833842 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"
835843 >
836844 Delete
837− </button>
845+ </Button>
838846 )}
839847 </>
840848 )}