Skip to content
Draft
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
13 changes: 13 additions & 0 deletions public/registry/care-ui/care-filly-classic/care-filly-classic.json

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions public/registry/care-ui/care-filly/care-filly.json

Large diffs are not rendered by default.

21 changes: 14 additions & 7 deletions public/registry/care-ui/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,20 @@
"registry/care-ui/carousel/carousel.tsx"
]
},
{
"name": "care-filly",
"type": "registry:ui",
"files": [
"registry/care-ui/care-filly/care-filly.tsx"
]
},
{
"name": "care-filly-classic",
"type": "registry:ui",
"files": [
"registry/care-ui/care-filly-classic/care-filly-classic.tsx"
]
},
{
"name": "card",
"type": "registry:ui",
Expand Down Expand Up @@ -737,13 +751,6 @@
"registry/care-ui/aspect-ratio/aspect-ratio.tsx"
]
},
{
"name": "animated-character",
"type": "registry:ui",
"files": [
"registry/care-ui/animated-character/animated-character.tsx"
]
},
{
"name": "alert",
"type": "registry:ui",
Expand Down
4 changes: 1 addition & 3 deletions src/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ import {
} from "@/components/ui/studio-sidebar";
import { X } from "lucide-react";

const TOOL_ONLY_COMPONENT_IDS = new Set([
"animated-character",
]);
const TOOL_ONLY_COMPONENT_IDS = new Set(["animated-character"]);

// Navigation data
const data = {
Expand Down
50 changes: 39 additions & 11 deletions src/components/dynamic-main-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,52 @@ const componentNavOrder = Object.keys(componentNames).filter(
function PropsTable({
props,
}: {
props: Array<{ name: string; type: string; description: string; default?: string }>;
props: Array<{
name: string;
type: string;
description: string;
default?: string;
}>;
}) {
return (
<div className="border-border rounded-lg border">
<table className="w-full">
<thead>
<tr className="border-border bg-muted/50 border-b">
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">Prop</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">Type</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">Default</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">Description</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">
Prop
</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">
Type
</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">
Default
</th>
<th className="text-foreground px-4 py-3 text-left text-sm font-medium">
Description
</th>
</tr>
</thead>
<tbody>
{props.map((prop, index) => (
<tr key={prop.name} className={index !== props.length - 1 ? "border-border border-b" : ""}>
<td className="text-foreground px-4 py-3 font-mono text-sm">{prop.name}</td>
<td className="text-muted-foreground px-4 py-3 font-mono text-sm">{prop.type}</td>
<td className="text-muted-foreground px-4 py-3 font-mono text-sm">{prop.default || "—"}</td>
<td className="text-muted-foreground px-4 py-3 text-sm">{prop.description}</td>
<tr
key={prop.name}
className={
index !== props.length - 1 ? "border-border border-b" : ""
}
>
<td className="text-foreground px-4 py-3 font-mono text-sm">
{prop.name}
</td>
<td className="text-muted-foreground px-4 py-3 font-mono text-sm">
{prop.type}
</td>
<td className="text-muted-foreground px-4 py-3 font-mono text-sm">
{prop.default || "—"}
</td>
<td className="text-muted-foreground px-4 py-3 text-sm">
{prop.description}
</td>
</tr>
))}
</tbody>
Expand Down Expand Up @@ -180,7 +206,9 @@ function ExampleItem({ example }: { example: ComponentExample }) {
{example.trailingProps && (
<div className="mt-8 space-y-3">
<SubsectionTitle>{example.trailingProps.title}</SubsectionTitle>
{example.trailingProps.description && <Muted>{example.trailingProps.description}</Muted>}
{example.trailingProps.description && (
<Muted>{example.trailingProps.description}</Muted>
)}
<PropsTable props={example.trailingProps.props} />
</div>
)}
Expand Down
4 changes: 1 addition & 3 deletions src/components/search-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ import { getComponentIds } from "@/lib/component-registry";
import { documentationPages } from "@/lib/documentation";
import { ERROR_PAGES } from "@/components/error-pages/registry";

const TOOL_ONLY_COMPONENT_IDS = new Set([
"animated-character",
]);
const TOOL_ONLY_COMPONENT_IDS = new Set(["animated-character"]);

const navSections = [
{
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/attachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
<div
data-slot="attachment-group"
className={cn(
"scroll-fade-x flex min-w-0 snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
"scroll-fade-x scrollbar-none flex min-w-0 snap-x snap-mandatory scroll-px-1 gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
className
)}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ function SheetBody({ className, ...props }: React.ComponentProps<"div">) {
<div
data-slot="sheet-body"
className={cn(
"min-h-0 flex-1 [scrollbar-gutter:stable] overflow-y-auto overscroll-contain py-4",
"min-h-0 flex-1 overflow-y-auto overscroll-contain py-4 [scrollbar-gutter:stable]",
className
)}
onScroll={(e) =>
Expand Down
103 changes: 87 additions & 16 deletions src/lib/registry/care-filly-classic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,17 @@ export const animatedCharacterDoc: ComponentDoc = {
description: (
<ul className="mt-2 space-y-2 text-sm">
<li>
<strong>CareFilly</strong>{" "}(<code>care-filly</code>) — layered face-plate character. The face-plate translates independently, creating a parallax depth illusion on every nod. Use for prominent roles: onboarding, empty states, loading screens, full-page assistants.
<strong>CareFilly</strong> (<code>care-filly</code>) — layered
face-plate character. The face-plate translates independently, creating
a parallax depth illusion on every nod. Use for prominent roles:
onboarding, empty states, loading screens, full-page assistants.
</li>
<li>
<strong>CareFillyClassic</strong>{" "}(<code>care-filly-classic</code>) — classic pixel-head character. The entire head rotates as one rigid unit. Use for compact, inline contexts: chat bubbles, search bars, status indicators. Available in <code>light</code> and <code>dark</code> variants.
<strong>CareFillyClassic</strong> (<code>care-filly-classic</code>) —
classic pixel-head character. The entire head rotates as one rigid unit.
Use for compact, inline contexts: chat bubbles, search bars, status
indicators. Available in <code>light</code> and <code>dark</code>{" "}
variants.
</li>
</ul>
),
Expand Down Expand Up @@ -403,12 +410,41 @@ ref.current?.noShake() // Decaying left-right shake with blinks`,
title: "CareFilly props",
description: 'import { CareFilly } from "@/components/ui/care-filly"',
props: [
{ name: "state", type: `"idle" | "listening" | "talking" | "writing" | "thinking" | "loading" | "happy" | "sad" | "surprised" | "confused" | "excited" | "sleepy"`, description: "Behavioral state preset. Transitions blend from the current pose." },
{ name: "mouseTracking", type: "boolean", description: "Eyes smoothly follow the pointer when true; return to the state gaze when false." },
{ name: "size", type: "string | number", description: 'CSS width for the SVG (e.g. "32px", "2rem"). Overrides the default 6rem.' },
{ name: "color", type: "string", description: 'CSS color tinting the entire character via currentColor (e.g. "#3b82f6").' },
{ name: "ref", type: "CareFillyHandle", description: "Imperative API: setState, nod, yesNod, noShake, shakeHead, blink, eyeRoll, startTalking, stopTalking, setGazeTarget, setMouseTracking, reset." },
{ name: "className", type: "string", description: "Additional CSS classes on the wrapper." },
{
name: "state",
type: `"idle" | "listening" | "talking" | "writing" | "thinking" | "loading" | "happy" | "sad" | "surprised" | "confused" | "excited" | "sleepy"`,
description:
"Behavioral state preset. Transitions blend from the current pose.",
},
{
name: "mouseTracking",
type: "boolean",
description:
"Eyes smoothly follow the pointer when true; return to the state gaze when false.",
},
{
name: "size",
type: "string | number",
description:
'CSS width for the SVG (e.g. "32px", "2rem"). Overrides the default 6rem.',
},
{
name: "color",
type: "string",
description:
'CSS color tinting the entire character via currentColor (e.g. "#3b82f6").',
},
{
name: "ref",
type: "CareFillyHandle",
description:
"Imperative API: setState, nod, yesNod, noShake, shakeHead, blink, eyeRoll, startTalking, stopTalking, setGazeTarget, setMouseTracking, reset.",
},
{
name: "className",
type: "string",
description: "Additional CSS classes on the wrapper.",
},
],
},
},
Expand Down Expand Up @@ -474,15 +510,50 @@ useEffect(() => {
</div>`,
trailingProps: {
title: "CareFillyClassic props",
description: 'import { CareFillyClassic } from "@/components/ui/care-filly-classic"',
description:
'import { CareFillyClassic } from "@/components/ui/care-filly-classic"',
props: [
{ name: "state", type: `"idle" | "listening" | "talking" | "writing" | "thinking" | "loading" | "happy" | "sad" | "surprised" | "confused" | "excited" | "sleepy"`, description: "Behavioral state preset. Transitions blend from the current pose." },
{ name: "mouseTracking", type: "boolean", description: "Eyes smoothly follow the pointer when true; return to the state gaze when false." },
{ name: "variant", type: '"light" | "dark"', description: "Selects the visual shell. light — pixel head on light background; dark — white shell with dark pixel features." },
{ name: "size", type: "string | number", description: 'CSS width for the SVG (e.g. "32px", "2rem"). Overrides the default.' },
{ name: "color", type: "string", description: 'CSS color tinting the entire character via currentColor (e.g. "#3b82f6").' },
{ name: "ref", type: "CareFillyClassicHandle", description: "Imperative API: setState, nod, shakeHead, blink, eyeRoll, startTalking, stopTalking, setGazeTarget, setMouseTracking, reset." },
{ name: "className", type: "string", description: "Additional CSS classes on the wrapper." },
{
name: "state",
type: `"idle" | "listening" | "talking" | "writing" | "thinking" | "loading" | "happy" | "sad" | "surprised" | "confused" | "excited" | "sleepy"`,
description:
"Behavioral state preset. Transitions blend from the current pose.",
},
{
name: "mouseTracking",
type: "boolean",
description:
"Eyes smoothly follow the pointer when true; return to the state gaze when false.",
},
{
name: "variant",
type: '"light" | "dark"',
description:
"Selects the visual shell. light — pixel head on light background; dark — white shell with dark pixel features.",
},
{
name: "size",
type: "string | number",
description:
'CSS width for the SVG (e.g. "32px", "2rem"). Overrides the default.',
},
{
name: "color",
type: "string",
description:
'CSS color tinting the entire character via currentColor (e.g. "#3b82f6").',
},
{
name: "ref",
type: "CareFillyClassicHandle",
description:
"Imperative API: setState, nod, shakeHead, blink, eyeRoll, startTalking, stopTalking, setGazeTarget, setMouseTracking, reset.",
},
{
name: "className",
type: "string",
description: "Additional CSS classes on the wrapper.",
},
],
},
},
Expand Down
18 changes: 16 additions & 2 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ export interface ComponentExample {
code?: string;
preview?: React.ReactNode;
/** Optional props table rendered below this example, scoped to this component/variant. */
trailingProps?: { title: string; description?: string; props: Array<{ name: string; type: string; description: string; default?: string }> };
trailingProps?: {
title: string;
description?: string;
props: Array<{
name: string;
type: string;
description: string;
default?: string;
}>;
};
}

export interface DocumentationPage {
Expand Down Expand Up @@ -46,7 +55,12 @@ export interface ComponentDoc {
propSections?: Array<{
title: string;
description?: string;
props: Array<{ name: string; type: string; description: string; default?: string }>;
props: Array<{
name: string;
type: string;
description: string;
default?: string;
}>;
}>;
}

Expand Down