@@ -257,90 +390,30 @@ export function ImageCardShell({ image, text }: { image: React.ReactNode; text:
```
```tsx
-// ImageCard/ImageCardRoot.tsx — Good — Root owns logic; Shell receives region nodes as props
+// ImageCard/ImageCardRoot.tsx — Root owns logic; Shell receives region nodes as props
import { Image, Text } from "@probo/ui";
import { ImageCardShell } from "./ImageCardShell";
-function ImageCardRoot({ image, text }: { image: React.ReactNode; text: React.ReactNode }) {
- const id = useId();
+export function ImageCardRoot({ image, text }: { image: ReactNode; text: ReactNode }) {
// state, effects, data wiring …
- return (
-
{image}}
- text={{text}}
- />
- );
+ return {image}} text={{text}} />;
}
// Bad — Shell takes regions as children instead of image / text props
-//
-// …
-// …
-//
-
-// Bad — data hooks or state live on Shell
-function ImageCardShellWithData({ image, text }: { image: React.ReactNode; text: React.ReactNode }) {
- const data = useQuery(/* … */); // move to Root (or above)
- return (
-
- {image}
- {text}
-
- );
-}
+// Bad — data hooks or state live on Shell (move to Root or above)
```
-(The snippets above are illustrative; names and props should match the real component.)
-
-## Skeleton placement and composition
-
-For compound components, export **`ImageCardSkeleton`** as a **separate named export** (e.g. `ImageCardSkeleton.tsx` or the folder barrel) so routes can depend on **loading UI + shell layout** without importing the full `ImageCardRoot` graph—smaller initial bundles for skeleton-first views. That also avoids pulling in **Radix UI** and other dependencies that are **not needed at load time** for the skeleton-only path.
-
-**Implementation:** `ImageCardSkeleton` should **reuse the same layout as the real card** by rendering **`ImageCardShell`** with the same **`image` / `text` props** as **`ImageCardRoot`**, but passing **skeleton primitives** instead of **`Image`** / **`Text`**:
-
-- **`image`** → **`ImageSkeleton`**
-- **`text`** → **`TextSkeleton`**
-
-**`ImageCardRoot`** composes real content with **`Image`** and **`Text`** (same imports as elsewhere in the app). The skeleton passes **`ImageSkeleton`** and **`TextSkeleton`** directly into **`ImageCardShell`** so loading views avoid **`Image`** / **`Text`** when that keeps bundles or behavior simpler.
-
-Reuse existing **`ImageSkeleton`** / **`TextSkeleton`** from typography or media primitives when available; avoid duplicate one-off pulse blocks.
-
-### Do / don't: skeleton imports and composition
-
-```tsx
-// Bad — skeleton nested on a namespace object (pulls full card module into the route)
-import { ImageCard } from "@probo/ui";
-
-
-// Good — each sub-component is a standalone named export
-import { ImageCardShell, ImageCardSkeleton } from "@probo/ui";
-
-// Inside ImageCardSkeleton.tsx (conceptually):
-export function ImageCardSkeleton() {
- return (
- }
- text={}
- />
- );
-}
-```
-
-The important part is **separate `ImageCardSkeleton` export**, **one `ImageCardShell` API** (`image` / `text` props), **shared shell layout**, and **reused `ImageSkeleton` / `TextSkeleton`**.
-
## Variants file
-Keep the **`tv({ slots: { … } })` definition** (and derived slot functions) in a **standalone file**, conventionally **`variants.ts`** next to the component folder. Import it from **`ImageCardShell`** and **skeleton** modules so skeleton entry points can pull **variants + shell** without the rest of the compound component's business logic.
-
-### Do / don't: colocating `tv` with the heavy module
+Keep the `tv({ slots: { … } })` definition (and derived slot functions) in a standalone **`variants.ts`** next to the component folder. Import it from the shell and skeleton modules so skeleton entry points can pull **variants + shell** without the rest of the compound component's business logic (and without Base UI).
```tsx
-// Bad — variants defined only inside ImageCardRoot.tsx; ImageCardSkeleton imports it and drags Root / hooks
+// Bad — variants defined inside ImageCardRoot.tsx; the skeleton importing it drags Root + hooks (+ Base UI)
// ImageCardRoot.tsx
const imageCard = tv({ slots: { shell: "...", image: "...", text: "..." } });
// Good — shared variants module imported by ImageCardShell and ImageCardSkeleton only
-// variants.ts — export imageCard (or slot helpers)
+// variants.ts — export imageCard (or slot helpers)
// ImageCardShell.tsx — import { imageCard } from "./variants"
// ImageCardSkeleton.tsx — import { imageCard } from "./variants"
```