Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,23 @@
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}
},
"overrides": [
{
"includes": [
"ui/src/components/ui/{button-group,carousel,input-group,input-otp,item,pagination}.tsx"
],
"linter": {
"rules": {
"a11y": {
"useSemanticElements": "off",
"useKeyWithClickEvents": "off",
"useFocusableInteractive": "off",
"useAriaPropsForRole": "off",
"noRedundantRoles": "off"
}
}
}
}
]
}
50 changes: 46 additions & 4 deletions bun.lock

Large diffs are not rendered by default.

42 changes: 39 additions & 3 deletions ui/.oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,44 @@
"correctness": "off"
},
"rules": {
"shadcn/no-raw-colors": ["error", { "allow": ["fill-none", "border-outset"] }],
"shadcn/no-unknown-classes": ["error", { "allow": ["toaster"] }],
"shadcn/no-raw-colors": [
"error",
{
"allow": ["fill-none", "border-outset"]
}
],
"shadcn/no-unknown-classes": [
"error",
{
"allow": ["toaster"]
}
],
"shadcn/no-arbitrary-values": "error"
}
},
"overrides": [
{
"files": [
"src/components/ui/accordion.tsx",
"src/components/ui/alert-dialog.tsx",
"src/components/ui/alert.tsx",
"src/components/ui/calendar.tsx",
"src/components/ui/combobox.tsx",
"src/components/ui/command.tsx",
"src/components/ui/context-menu.tsx",
"src/components/ui/drawer.tsx",
"src/components/ui/input-group.tsx",
"src/components/ui/input-otp.tsx",
"src/components/ui/item.tsx",
"src/components/ui/menubar.tsx",
"src/components/ui/native-select.tsx",
"src/components/ui/slider.tsx",
"src/components/ui/switch.tsx"
],
"rules": {
"shadcn/no-arbitrary-values": "off",
"shadcn/no-unknown-classes": "off",
"shadcn/no-raw-colors": "off"
}
}
]
}
16 changes: 12 additions & 4 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist/types"
},
"dependencies": {
"@base-ui/react": "^1.8.0",
"@better-auth/api-key": "catalog:",
"@better-auth/core": "catalog:",
"@better-auth/passkey": "catalog:",
"@everything-dev/builders-plugin": "workspace:*",
"@hot-labs/near-connect": "0.11.2",
"@orpc/client": "catalog:",
"@orpc/contract": "catalog:",
Expand Down Expand Up @@ -51,29 +54,34 @@
"better-near-auth": "catalog:",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.4.0",
"effect": "catalog:",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.37.0",
"input-otp": "^1.5.0",
"lucide-react": "^1.14.0",
"nanoid": "^5.1.11",
"nostr-tools": "^2.10.0",
"near-kit": "catalog:",
"near-social-js": "^2.0.4",
"next-themes": "^0.4.6",
"nostr-tools": "^2.10.0",
"radix-ui": "^1.4.3",
"react": "catalog:",
"react-day-picker": "^10.0.2",
"react-dom": "catalog:",
"react-markdown": "^10.1.0",
"react-resizable-panels": "^4",
"rehype-highlight": "^7.0.2",
"rehype-sanitize": "^6.0.0",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0",
"tw-animate-css": "^1.4.0",
"vaul": "^1.1.2",
"zod": "catalog:",
"zustand": "^5.0.9",
"@better-auth/core": "catalog:",
"@everything-dev/builders-plugin": "workspace:*"
"zustand": "^5.0.9"
},
"peerDependencies": {
"@tanstack/react-query": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/activity-card.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { CheckCircle2, ThumbsDown, ThumbsUp } from "lucide-react";
import { useMemo } from "react";
import { CatalogClaimActivity } from "@/components/catalog-claim-activity";
import { VoteButton } from "@/components/common/vote-button";
import { NearProfile } from "@/components/near-profile";
import { ProjectApprovalActivity } from "@/components/project-approval-activity";
import { Badge } from "@/components/ui/badge";
import { Skeleton } from "@/components/ui/skeleton";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { VoteButton } from "@/components/ui/vote-button";
import { readCatalogClaimActivityPayload } from "@/lib/catalog-activity";
import { readProjectApprovalActivityPayload } from "@/lib/project-activity";
import { type ActivityEvent, readActivityPayload } from "@/lib/queries/activity";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/builder-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { useStore } from "@tanstack/react-form";
import { useQuery } from "@tanstack/react-query";
import { useEffect, useMemo, useRef, useState } from "react";
import { useApiClient } from "@/app";
import { socialIcon } from "@/components/common/social-icons";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { socialIcon } from "@/components/ui/social-icons";
import { Textarea } from "@/components/ui/textarea";
import { SOCIAL_LINKS, validateHandle } from "@/lib/social-links";
import { cn } from "@/lib/utils";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-r
import { useState } from "react";

import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";

interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
Expand Down
23 changes: 23 additions & 0 deletions ui/src/components/common/info-row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ReactNode } from "react";

export function InfoRow({
label,
value,
mono,
}: {
label: string;
value: ReactNode;
mono?: boolean;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove anything from /ui that isn't a shadcn component

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Append any shadcn components here that feedback app needs -- this may mean doing a full shadcn init to grab all components

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elliotBraem done in 8140f68: the non-shadcn components (info-row, back-button, data-table, markdown, stepper, etc.) moved out of ui/ into components/common/, and the barrel and all imports are updated. PR: #262

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elliotBraem added the missing shadcn components (accordion, alert, alert-dialog, calendar, command, drawer, popover, switch, slider, pagination, input-group, combobox and more) and exported them from the barrel in 8140f68. PR: #262

}) {
return (
// oxlint-disable-next-line shadcn/no-arbitrary-values -- fixed label column beside flexible value; grid-template-columns has no scale equivalent
<div className="grid grid-cols-[100px_1fr] gap-4 rounded-sm border border-border bg-muted px-3.5 py-2.5 items-center">
<span className="text-muted-foreground text-2xs font-bold uppercase tracking-wider">
{label}
</span>
<span className={`text-foreground text-13 break-all ${mono ? "font-mono text-xs" : ""}`}>
{value}
</span>
</div>
);
}
86 changes: 86 additions & 0 deletions ui/src/components/common/stepper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Check, Circle, XCircle } from "lucide-react";
import { useCallback, useState } from "react";
import { Spinner } from "@/components/ui/spinner";

export type StepState = "pending" | "running" | "success" | "failed";

export interface Step {
label: string;
state: StepState;
error?: string;
blocking?: boolean;
}

export function StepIcon({ state }: { state: StepState }) {
switch (state) {
case "running":
return <Spinner className="h-3.5 w-3.5 text-muted-foreground shrink-0 mt-px" />;
case "success":
return <Check className="h-3.5 w-3.5 text-brand-cyan shrink-0 mt-px" />;
case "failed":
return <XCircle className="h-3.5 w-3.5 text-destructive shrink-0 mt-px" />;
default:
return <Circle className="h-3.5 w-3.5 text-border shrink-0 mt-px" />;
}
}

export function StepList({ steps }: { steps: Step[] }) {
return (
<>
{steps.map((step, i) => (
<div key={i} className="flex items-start gap-3">
<StepIcon state={step.state} />
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<span
className={`text-xs ${step.state === "failed" ? "text-destructive" : "text-foreground"}`}
>
{step.label}
</span>
{step.blocking === false && (
<span className="text-3xs text-muted-foreground uppercase tracking-wide">
non-blocking
</span>
)}
</div>
{step.error && (
<p className="text-xs text-destructive mt-0.5 break-all">{step.error}</p>
)}
</div>
</div>
))}
</>
);
}

export function useStepper(stepLabels: readonly { label: string; blocking?: boolean }[]) {
const [steps, setSteps] = useState<Step[]>(
stepLabels.map((s) => ({ ...s, state: "pending" as StepState })),
);

const updateStep = useCallback((index: number, state: StepState, error?: string) => {
setSteps((prev) => prev.map((s, i) => (i === index ? { ...s, state, error } : s)));
}, []);

const resetSteps = useCallback(() => {
setSteps(stepLabels.map((s) => ({ ...s, state: "pending" as StepState })));
}, [stepLabels]);

const runStep = useCallback(
async <T,>(index: number, fn: () => Promise<T>): Promise<T | undefined> => {
updateStep(index, "running");
try {
const value = await fn();
updateStep(index, "success");
return value;
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
updateStep(index, "failed", msg);
return undefined;
}
},
[updateStep],
);

return { steps, updateStep, resetSteps, runStep };
}
Loading
Loading