Skip to content
Merged
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
3 changes: 3 additions & 0 deletions shadcn-components/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

*storybook.log
storybook-static
12 changes: 12 additions & 0 deletions shadcn-components/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { StorybookConfig } from "@storybook/nextjs";

const config: StorybookConfig = {
stories: ["../components/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [],
framework: {
name: "@storybook/nextjs",
options: {},
},
staticDirs: ["../public"],
};
export default config;
14 changes: 14 additions & 0 deletions shadcn-components/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Preview } from '@storybook/nextjs'

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};

export default preview;
2 changes: 0 additions & 2 deletions shadcn-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

A comprehensive collection of base [shadcn/ui](https://ui.shadcn.com/) components adapted for Webflow Code Components. These components can be dropped into any Webflow site and configured visually through the Webflow Designer.

![](./screenshots/shadcn-demo.png)

## Available Components

### Layout & Navigation
Expand Down
78 changes: 59 additions & 19 deletions shadcn-components/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/Button/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/Card/card";
import { Input } from "@/components/ui/Input/input";
import { Badge } from "@/components/ui/Badge/badge";
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/components/ui/Alert/alert";
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/Avatar/avatar";
import { AlertCircle } from "lucide-react";

export default function Home() {
Expand All @@ -12,15 +26,19 @@ export default function Home() {
<div className="container mx-auto px-4 py-8">
<header className="text-center mb-12">
<h1 className="text-4xl font-bold mb-4">Lightweight Design System</h1>
<p className="text-xl text-muted-foreground">Built with ShadCN/UI Components</p>
<p className="text-xl text-muted-foreground">
Built with ShadCN/UI Components
</p>
</header>

<div className="grid gap-8 max-w-4xl mx-auto">
{/* Button Components */}
<Card>
<CardHeader>
<CardTitle>Button Component</CardTitle>
<CardDescription>Various button styles and variants</CardDescription>
<CardDescription>
Various button styles and variants
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-4">
Expand All @@ -45,7 +63,9 @@ export default function Home() {
<Card>
<CardHeader>
<CardTitle>Sample Card 1</CardTitle>
<CardDescription>This is a sample card description</CardDescription>
<CardDescription>
This is a sample card description
</CardDescription>
</CardHeader>
<CardContent>
<p>Card content goes here with some example text.</p>
Expand Down Expand Up @@ -74,11 +94,19 @@ export default function Home() {
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<label htmlFor="email">Email</label>
<Input type="email" id="email" placeholder="Enter your email" />
<Input
type="email"
id="email"
placeholder="Enter your email"
/>
</div>
<div className="space-y-2">
<label htmlFor="password">Password</label>
<Input type="password" id="password" placeholder="Enter password" />
<Input
type="password"
id="password"
placeholder="Enter password"
/>
</div>
<div className="space-y-2">
<label htmlFor="search">Search</label>
Expand Down Expand Up @@ -120,24 +148,33 @@ export default function Home() {
<Card>
<CardHeader>
<CardTitle>Avatar Component</CardTitle>
<CardDescription>User profile pictures and fallbacks</CardDescription>
<CardDescription>
User profile pictures and fallbacks
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap items-center gap-6">
<div className="flex flex-col items-center gap-2">
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarImage
src="https://github.com/shadcn.png"
alt="@shadcn"
/>
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<span className="text-sm text-muted-foreground">With Image</span>
<span className="text-sm text-muted-foreground">
With Image
</span>
</div>

<div className="flex flex-col items-center gap-2">
<Avatar>
<AvatarImage src="/nonexistent.jpg" alt="Broken" />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<span className="text-sm text-muted-foreground">Fallback</span>
<span className="text-sm text-muted-foreground">
Fallback
</span>
</div>

<div className="flex flex-col items-center gap-2">
Expand All @@ -154,18 +191,21 @@ export default function Home() {
<Card>
<CardHeader>
<CardTitle>Alert Component</CardTitle>
<CardDescription>Notifications and important messages</CardDescription>
<CardDescription>
Notifications and important messages
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertTitle>Default Alert</AlertTitle>
<AlertDescription>
This is a default alert message with some important information.
This is a default alert message with some important
information.
</AlertDescription>
</Alert>

<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error Alert</AlertTitle>
Expand Down
43 changes: 43 additions & 0 deletions shadcn-components/components/ui/Alert/alert.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { Meta, StoryObj } from "@storybook/nextjs";
import { Alert, AlertDescription, AlertTitle } from "./alert";
import "../../../app/globals.css";

const meta: Meta<typeof Alert> = {
title: "UI/Alert",
component: Alert,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {
variant: {
control: { type: "select" },
options: ["default", "destructive"],
},
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => (
<Alert>
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components to your app using the cli.
</AlertDescription>
</Alert>
),
};

export const Destructive: Story = {
render: () => (
<Alert variant="destructive">
<AlertTitle>Error</AlertTitle>
<AlertDescription>
Your session has expired. Please log in again.
</AlertDescription>
</Alert>
),
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import { Alert, AlertTitle, AlertDescription } from "./alert";
import { props } from '@webflow/data-types';
import { props } from "@webflow/data-types";
import { declareComponent } from "@webflow/react";

import "../../app/globals.css";
import "../../../app/globals.css";

interface WebflowAlertProps {
className?: string;
Expand Down Expand Up @@ -50,7 +50,7 @@ export default declareComponent(WebflowAlert, {
defaultValue: "Alert Title",
}),
description: props.Text({
name: "Description",
name: "Description",
defaultValue: "Your alert description goes here.",
}),
showIcon: props.Visibility({
Expand Down
69 changes: 69 additions & 0 deletions shadcn-components/components/ui/Avatar/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import { cva, type VariantProps } from "class-variance-authority";
import React from "react";

import { cn } from "@/lib/utils";

const avatarVariants = cva(
"relative flex shrink-0 overflow-hidden rounded-full",
{
variants: {
size: {
default: "size-8",
sm: "size-6",
lg: "size-10",
xl: "size-12",
},
},
defaultVariants: {
size: "default",
},
}
);

export interface AvatarProps // Export AvatarProps
extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,
VariantProps<typeof avatarVariants> {}

function Avatar({ className, size, children, ...props }: AvatarProps) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
className={cn(avatarVariants({ size }), className)}
{...props}
>
{children}
</AvatarPrimitive.Root>
);
}

function AvatarImage({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
{...props}
/>
);
}

function AvatarFallback({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
className
)}
{...props}
/>
);
}

export { Avatar, AvatarImage, AvatarFallback };
55 changes: 55 additions & 0 deletions shadcn-components/components/ui/Avatar/avatar.webflow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from "react";
import { declareComponent } from "@webflow/react";
import { props } from "@webflow/data-types";
import { cn } from "@/lib/utils";
import { Avatar, AvatarProps } from "./avatar"; // Import AvatarProps

import "../../../app/globals.css";

interface WebflowAvatarProps {
className?: string;
children?: React.ReactNode;
size?: AvatarProps["size"]; // Re-adding size prop
}

const WebflowAvatar: React.FC<WebflowAvatarProps> = ({
className,
children,
size, // Re-adding size prop
}) => {
return (
<Avatar className={cn(className)} size={size} data-avatar-root>
{children}
</Avatar>
);
};

// Export for local testing
export { WebflowAvatar };

export default declareComponent(WebflowAvatar, {
name: "Avatar",
description:
"A ShadCN UI avatar component - use with AvatarImage and AvatarFallback",
group: "Display",
props: {
className: props.Text({
name: "Class Name",
defaultValue: "",
tooltip: "Optional: Add Additional Tailwind CSS classes",
}),
children: props.Slot({
name: "Content",
tooltip: "Add the Avatar Image Component here as a slot",
}),
size: props.Variant({
name: "Size",
options: ["default", "sm", "lg", "xl"],
defaultValue: "default",
tooltip: "Controls the size of the avatar.",
}),
},
options: {
ssr: false, // Force Client-Side Rendering
},
});
Loading