Skip to content

Commit 5ed151e

Browse files
Added @radix-ui/react-slot to react package and more examples to the website
1 parent 6f1b4e5 commit 5ed151e

11 files changed

+174
-80
lines changed

apps/web/app/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { LinksSection } from "./sections/LinksSection";
99
import { UsageSectionReactContent } from "./sections/UsageSectionReactContent";
1010
import { ExampleSectionConstantSizeExample } from "./sections/ExamplesSectionConstantSizeExample";
1111
import { ExamplesSectionDefaultSizeExample } from "./sections/ExamplesSectionDefaultSizeExample";
12+
import { ExamplesSectionAsChildExample } from "./sections/ExamplesSectionAsChildExample";
1213

1314
export default function Page() {
1415
return (
@@ -20,6 +21,7 @@ export default function Page() {
2021
<ExamplesSection
2122
constantSizeExample={<ExampleSectionConstantSizeExample />}
2223
defaultSizeExample={<ExamplesSectionDefaultSizeExample />}
24+
asChildPropExample={<ExamplesSectionAsChildExample />}
2325
/>
2426
{/* <HowItWorksSection /> */}
2527
<LicenseSection />

apps/web/app/sections/ExamplesSection.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import { useAtom } from "jotai";
77
export const ExamplesSection = ({
88
constantSizeExample,
99
defaultSizeExample,
10+
asChildPropExample,
1011
}: {
1112
constantSizeExample: JSX.Element;
1213
defaultSizeExample: JSX.Element;
14+
asChildPropExample: JSX.Element;
1315
}) => {
1416
const [language] = useAtom(LANGUAGE_SELECTOR_ATOM);
1517

@@ -24,11 +26,13 @@ export const ExamplesSection = ({
2426
<Tabs defaultValue="1" className="w-full flex flex-col items-center">
2527
<TabsList>
2628
<TabsTrigger value="1">Constant size</TabsTrigger>
27-
<TabsTrigger value="2">Default size</TabsTrigger>
29+
<TabsTrigger value="2">Default size (Image Example)</TabsTrigger>
30+
<TabsTrigger value="3">asChild prop</TabsTrigger>
2831
</TabsList>
2932

3033
<TabsContent value="1">{constantSizeExample}</TabsContent>
3134
<TabsContent value="2">{defaultSizeExample}</TabsContent>
35+
<TabsContent value="3">{asChildPropExample}</TabsContent>
3236
</Tabs>
3337
</div>
3438
);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Card, CardContent } from "@/components/ui/card";
2+
import { Code } from "@/components/ui/code";
3+
import { Squircle } from "@squircle-js/react";
4+
5+
import Prism from "prismjs";
6+
import "prismjs/components/prism-jsx";
7+
import type { PropsWithChildren } from "react";
8+
9+
const usage = `<Squircle
10+
asChild
11+
cornerRadius={10}
12+
cornerSmoothing={1}
13+
className="bg-black text-white px-2 py-1"
14+
>
15+
<span>Inline Squircle</span>
16+
</Squircle>`;
17+
18+
const highlightedUsage = Prism.highlight(
19+
["...", usage, "..."].join("\n"),
20+
Prism.languages.jsx,
21+
"jsx"
22+
);
23+
24+
export const ExamplesSectionAsChildExample = () => {
25+
return (
26+
<Card className="w-full max-w-[480px] sm:max-w-[508px]">
27+
<CardContent className="py-6 w-full space-y-4">
28+
<h3 className="font-semibold text-lg">Code:</h3>
29+
<p>
30+
You can use <Kode>asChild</Kode> prop to squircle any element. This is
31+
useful when you want to squircle some element that might change size.
32+
By default <Kode>Squircle</Kode> is a <Kode>div</Kode> element, but
33+
you can change it to any other element by nesting that element inside
34+
of <Kode>Squircle</Kode> component and adding <Kode>asChild</Kode>{" "}
35+
prop.
36+
</p>
37+
38+
<Code dangerousHTML={highlightedUsage} raw={usage} />
39+
<h3 className="font-semibold text-lg">Result:</h3>
40+
41+
<Squircle
42+
cornerRadius={10}
43+
cornerSmoothing={1}
44+
asChild
45+
className="bg-black text-white px-2 py-1"
46+
>
47+
<span>Inline Squircle</span>
48+
</Squircle>
49+
</CardContent>
50+
</Card>
51+
);
52+
};
53+
54+
const Kode = ({ children }: PropsWithChildren) => (
55+
<code className="bg-slate-200/50 px-1.5 text-sm py-0.5 rounded-md">
56+
{children}
57+
</code>
58+
);

apps/web/app/sections/ExamplesSectionConstantSizeExample.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Squircle } from "@squircle-js/react";
44

55
import Prism from "prismjs";
66
import "prismjs/components/prism-jsx";
7+
import { PropsWithChildren } from "react";
78

89
const usage = `<Squircle
910
cornerRadius={64}
@@ -29,6 +30,14 @@ export const ExampleSectionConstantSizeExample = () => {
2930
<Card className="w-full max-w-[480px] sm:max-w-[508px]">
3031
<CardContent className="py-6 w-full space-y-4">
3132
<h3 className="font-semibold text-lg">Code:</h3>
33+
34+
<p>
35+
When you know the exact size you want your squircle to be, you can use{" "}
36+
<Kode>width</Kode> and <Kode>height</Kode> props to specify it. This
37+
is especially useful when you Server Side Render your app, and you
38+
know the size of the image you want to squircle.
39+
</p>
40+
3241
<Code dangerousHTML={highlightedUsage} raw={usage} />
3342
<h3 className="font-semibold text-lg">Result:</h3>
3443

@@ -49,3 +58,9 @@ export const ExampleSectionConstantSizeExample = () => {
4958
</Card>
5059
);
5160
};
61+
62+
const Kode = ({ children }: PropsWithChildren) => (
63+
<code className="bg-slate-200/50 px-1.5 text-sm py-0.5 rounded-md">
64+
{children}
65+
</code>
66+
);

apps/web/app/sections/ExamplesSectionDefaultSizeExample.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@ import { Squircle } from "@squircle-js/react";
55
import Prism from "prismjs";
66
import "prismjs/components/prism-jsx";
77
import { ExamplesSectionDefaultSizeExampleClientComponent } from "./ExamplesSectionDefaultSizeExampleClientComponent";
8+
import { PropsWithChildren } from "react";
89

910
const usage = `<Squircle
10-
cornerRadius={64}
11+
cornerRadius={50}
1112
cornerSmoothing={1}
12-
defaultSize={256}
13-
defaultSize={256}
13+
defaultWidth={320}
14+
defaultHeight={214}
15+
className="bg-slate-100 w-fit h-fit"
16+
asChild
1417
>
15-
<div
16-
className="w-full h-full
17-
bg-gradient-to-br from-indigo-500
18-
via-purple-500 to-pink-500"
18+
<Image
19+
src="/antoni-silvestrovic-baS2vUSSGBY-unsplash.jpg"
20+
width={320}
21+
height={214}
22+
alt="D*ck"
1923
/>
2024
</Squircle>`;
2125

@@ -34,6 +38,12 @@ export const ExamplesSectionDefaultSizeExample = () => {
3438
For images to work you will need to provide either default size, or
3539
specific size you want the image to be.
3640
</p>
41+
<p>
42+
In this example, we&apos;re using <Kode>defaultWidth</Kode> and{" "}
43+
<Kode>defaultHeight</Kode> to tell Squircle what size we want the{" "}
44+
<Kode>clipPath</Kode> to be initially, afterwards if you resize the
45+
image it will be updated automatically.
46+
</p>
3747
<Code dangerousHTML={highlightedUsage} raw={usage} />
3848
<h3 className="font-semibold text-lg">Result:</h3>
3949

@@ -42,3 +52,9 @@ export const ExamplesSectionDefaultSizeExample = () => {
4252
</Card>
4353
);
4454
};
55+
56+
const Kode = ({ children }: PropsWithChildren) => (
57+
<code className="bg-slate-200/50 px-1.5 text-sm py-0.5 rounded-md">
58+
{children}
59+
</code>
60+
);

apps/web/app/sections/ExamplesSectionDefaultSizeExampleClientComponent.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { Button } from "@/components/ui/button";
44
import { Squircle } from "@squircle-js/react";
55
import { RotateCcwIcon } from "lucide-react";
6+
import Image from "next/image";
67
import { useEffect, useState } from "react";
78

89
export const ExamplesSectionDefaultSizeExampleClientComponent = () => {
@@ -30,20 +31,14 @@ export const ExamplesSectionDefaultSizeExampleClientComponent = () => {
3031
</Button>
3132
{src && (
3233
<Squircle
33-
cornerRadius={64}
34+
cornerRadius={50}
3435
cornerSmoothing={1}
35-
// width={256}
36-
// height={256}
37-
defaultWidth={256}
38-
defaultHeight={256}
36+
defaultWidth={320}
37+
defaultHeight={214}
3938
className="bg-slate-100 w-fit h-fit"
40-
style={{ paddingBottom: !src ? -1 : 0 }}
41-
as="img"
42-
src={src}
39+
asChild
4340
>
44-
{/* <a href="https://unsplash.com/@bring_shrubbery"> */}
45-
46-
{/* </a> */}
41+
<Image src={src} width={320} height={214} alt="" />
4742
</Squircle>
4843
)}
4944
</div>

apps/web/app/sections/SquircleDemoSection.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export const SquircleDemoSection = () => {
1616
Squircle
1717
</span>{" "}
1818
<Squircle
19-
as="span"
20-
className="bg-black pl-8 pr-8 pt-2 pb-2 text-6xl sm:text-inherit"
19+
asChild
2120
cornerRadius={cornerRadius}
2221
cornerSmoothing={cornerSmoothing}
22+
className="bg-black text-white pl-8 pr-8 pt-2 pb-2 text-6xl"
2323
>
24-
<span className="text-white">Element</span>
24+
<span>Element</span>
2525
</Squircle>
2626
<br />
2727
for{" "}
@@ -34,12 +34,12 @@ export const SquircleDemoSection = () => {
3434
<div className="text-center text-lg mb-6">
3535
Use{" "}
3636
<Squircle
37-
as="code"
37+
asChild
3838
className="bg-foreground text-white py-1 pl-2 pr-2"
3939
cornerRadius={10}
4040
cornerSmoothing={1}
4141
>
42-
{"<Squircle>"}
42+
<span>{"<Squircle>"}</span>
4343
</Squircle>{" "}
4444
to build your own components.
4545
<br />

packages/squircle-element-react/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"lint": "tsc"
1212
},
1313
"dependencies": {
14+
"@radix-ui/react-slot": "^1.0.2",
1415
"figma-squircle": "^0.3.0"
1516
},
1617
"peerDependencies": {

packages/squircle-element-react/src/index.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,25 @@ import { useMemo } from "react";
55

66
import { useElementSize } from "./use-element-size";
77
export { SquircleNoScript } from "./no-js";
8+
import { Slot } from "@radix-ui/react-slot";
89

910
interface SquircleProps<E extends React.ElementType> {
1011
cornerSmoothing?: number;
1112
cornerRadius?: number;
12-
as?: E;
13+
asChild?: boolean;
1314
children?: React.ReactNode;
1415

1516
width?: number;
1617
height?: number;
18+
1719
defaultWidth?: number;
1820
defaultHeight?: number;
1921
}
2022

2123
function Squircle<E extends React.ElementType = "div">({
2224
cornerRadius,
2325
cornerSmoothing = 0.6,
24-
as,
26+
asChild,
2527
style,
2628
width: w,
2729
height: h,
@@ -30,12 +32,12 @@ function Squircle<E extends React.ElementType = "div">({
3032
...props
3133
}: SquircleProps<E> &
3234
Omit<React.ComponentPropsWithoutRef<E>, keyof SquircleProps<E>>) {
33-
const Component = as || "div";
35+
const Component = asChild ? Slot : "div";
3436

3537
// Note: If you need to pass ref, wrap this component in another, and style to full-width/height.
3638
const [ref, { width, height }] = useElementSize<HTMLDivElement>({
37-
width: defaultWidth,
38-
height: defaultHeight,
39+
defaultWidth,
40+
defaultHeight,
3941
});
4042

4143
const actualWidth = w ?? width;
@@ -57,8 +59,8 @@ function Squircle<E extends React.ElementType = "div">({
5759
style={{
5860
...style,
5961
borderRadius: cornerRadius,
60-
// width: actualWidth,
61-
// height: actualHeight,
62+
width: w ?? defaultWidth,
63+
height: h ?? defaultHeight,
6264
clipPath: `path('${path}')`,
6365
}}
6466
data-squircle={cornerRadius}

packages/squircle-element-react/src/use-element-size.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ interface Size {
1111
export function useElementSize<
1212
T extends HTMLElement = HTMLDivElement
1313
>(defaultSize: {
14-
width?: number;
15-
height?: number;
14+
defaultWidth?: number;
15+
defaultHeight?: number;
1616
}): [(node: T | null) => void, Size] {
1717
// Mutable values like 'ref.current' aren't valid dependencies
1818
// because mutating them doesn't re-render the component.
1919
// Instead, we use a state as a ref to be reactive.
2020
const [ref, setRef] = useState<T | null>(null);
2121
const [size, setSize] = useState<Size>({
22-
width: defaultSize.width ?? 0,
23-
height: defaultSize.height ?? 0,
22+
width: defaultSize.defaultWidth ?? 0,
23+
height: defaultSize.defaultHeight ?? 0,
2424
});
2525

2626
// Prevent too many rendering using useCallback

0 commit comments

Comments
 (0)