diff --git a/packages/icons/icons/chevron-down.svg b/packages/icons/icons/chevron-down.svg
new file mode 100644
index 0000000000..0863c3a77c
--- /dev/null
+++ b/packages/icons/icons/chevron-down.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/icons/chevron-left.svg b/packages/icons/icons/chevron-left.svg
new file mode 100644
index 0000000000..ed786c595a
--- /dev/null
+++ b/packages/icons/icons/chevron-left.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/icons/chevron-right.svg b/packages/icons/icons/chevron-right.svg
new file mode 100644
index 0000000000..3ec167769b
--- /dev/null
+++ b/packages/icons/icons/chevron-right.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/icons/chevron-up.svg b/packages/icons/icons/chevron-up.svg
new file mode 100644
index 0000000000..afa1d3b57e
--- /dev/null
+++ b/packages/icons/icons/chevron-up.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/icons/package.json b/packages/icons/package.json
index 7b14826f15..052dec24c1 100644
--- a/packages/icons/package.json
+++ b/packages/icons/package.json
@@ -9,7 +9,7 @@
"dev": "build-package --watch",
"build": "build-package",
"dts": "tsc --declarationDir lib/types",
- "generate": "rm -fr src/__generated__ && NODE_OPTIONS='--loader=tsx' svgo-jsx svgo-jsx.config.ts && tsx svg-string.ts && prettier --write ./",
+ "generate": "rm -fr src/__generated__ && NODE_OPTIONS='--loader=tsx' svgo-jsx svgo-jsx.config.ts && tsx svg-string.ts && prettier --write src/__generated__",
"typecheck": "tsc",
"checks": "pnpm typecheck",
"storybook:dev": "storybook dev -p 6006",
diff --git a/packages/icons/src/__generated__/chevron-down.tsx b/packages/icons/src/__generated__/chevron-down.tsx
new file mode 100644
index 0000000000..3cf7490604
--- /dev/null
+++ b/packages/icons/src/__generated__/chevron-down.tsx
@@ -0,0 +1,15 @@
+// Generated from icons/chevron-down.svg
+
+import { forwardRef } from "react";
+import type { IconProps } from "../types";
+
+// prettier-ignore
+export const ChevronDownIcon = forwardRef(
+ ({ color = "currentColor", size = 16, ...props }, forwardedRef) => {
+ return (
+
+ );
+ }
+);
+
+ChevronDownIcon.displayName = "ChevronDownIcon";
diff --git a/packages/icons/src/__generated__/chevron-left.tsx b/packages/icons/src/__generated__/chevron-left.tsx
new file mode 100644
index 0000000000..8763512267
--- /dev/null
+++ b/packages/icons/src/__generated__/chevron-left.tsx
@@ -0,0 +1,15 @@
+// Generated from icons/chevron-left.svg
+
+import { forwardRef } from "react";
+import type { IconProps } from "../types";
+
+// prettier-ignore
+export const ChevronLeftIcon = forwardRef(
+ ({ color = "currentColor", size = 16, ...props }, forwardedRef) => {
+ return (
+
+ );
+ }
+);
+
+ChevronLeftIcon.displayName = "ChevronLeftIcon";
diff --git a/packages/icons/src/__generated__/chevron-right.tsx b/packages/icons/src/__generated__/chevron-right.tsx
new file mode 100644
index 0000000000..9bd040fc28
--- /dev/null
+++ b/packages/icons/src/__generated__/chevron-right.tsx
@@ -0,0 +1,15 @@
+// Generated from icons/chevron-right.svg
+
+import { forwardRef } from "react";
+import type { IconProps } from "../types";
+
+// prettier-ignore
+export const ChevronRightIcon = forwardRef(
+ ({ color = "currentColor", size = 16, ...props }, forwardedRef) => {
+ return (
+
+ );
+ }
+);
+
+ChevronRightIcon.displayName = "ChevronRightIcon";
diff --git a/packages/icons/src/__generated__/chevron-up.tsx b/packages/icons/src/__generated__/chevron-up.tsx
new file mode 100644
index 0000000000..636bcce542
--- /dev/null
+++ b/packages/icons/src/__generated__/chevron-up.tsx
@@ -0,0 +1,15 @@
+// Generated from icons/chevron-up.svg
+
+import { forwardRef } from "react";
+import type { IconProps } from "../types";
+
+// prettier-ignore
+export const ChevronUpIcon = forwardRef(
+ ({ color = "currentColor", size = 16, ...props }, forwardedRef) => {
+ return (
+
+ );
+ }
+);
+
+ChevronUpIcon.displayName = "ChevronUpIcon";
diff --git a/packages/icons/src/__generated__/index.ts b/packages/icons/src/__generated__/index.ts
index cb00c45321..13c6448f41 100644
--- a/packages/icons/src/__generated__/index.ts
+++ b/packages/icons/src/__generated__/index.ts
@@ -50,10 +50,14 @@ export * from "./chevron-big-down";
export * from "./chevron-big-left";
export * from "./chevron-big-right";
export * from "./chevron-big-up";
+export * from "./chevron-down";
export * from "./chevron-filled-down";
export * from "./chevron-filled-left";
export * from "./chevron-filled-right";
export * from "./chevron-filled-up";
+export * from "./chevron-left";
+export * from "./chevron-right";
+export * from "./chevron-up";
export * from "./code-text";
export * from "./collapsible";
export * from "./commit";
diff --git a/packages/icons/src/__generated__/svg/chevron-down.ts b/packages/icons/src/__generated__/svg/chevron-down.ts
new file mode 100644
index 0000000000..5d67649729
--- /dev/null
+++ b/packages/icons/src/__generated__/svg/chevron-down.ts
@@ -0,0 +1 @@
+export const ChevronDownIcon = ``;
diff --git a/packages/icons/src/__generated__/svg/chevron-left.ts b/packages/icons/src/__generated__/svg/chevron-left.ts
new file mode 100644
index 0000000000..c20d4fd3f9
--- /dev/null
+++ b/packages/icons/src/__generated__/svg/chevron-left.ts
@@ -0,0 +1 @@
+export const ChevronLeftIcon = ``;
diff --git a/packages/icons/src/__generated__/svg/chevron-right.ts b/packages/icons/src/__generated__/svg/chevron-right.ts
new file mode 100644
index 0000000000..17848f0ec3
--- /dev/null
+++ b/packages/icons/src/__generated__/svg/chevron-right.ts
@@ -0,0 +1 @@
+export const ChevronRightIcon = ``;
diff --git a/packages/icons/src/__generated__/svg/chevron-up.ts b/packages/icons/src/__generated__/svg/chevron-up.ts
new file mode 100644
index 0000000000..984f96b5ba
--- /dev/null
+++ b/packages/icons/src/__generated__/svg/chevron-up.ts
@@ -0,0 +1 @@
+export const ChevronUpIcon = ``;
diff --git a/packages/icons/src/__generated__/svg/index.ts b/packages/icons/src/__generated__/svg/index.ts
index 7eaf3d16c2..9f0c5324a6 100644
--- a/packages/icons/src/__generated__/svg/index.ts
+++ b/packages/icons/src/__generated__/svg/index.ts
@@ -50,10 +50,14 @@ export { ChevronBigDownIcon } from "./chevron-big-down";
export { ChevronBigLeftIcon } from "./chevron-big-left";
export { ChevronBigRightIcon } from "./chevron-big-right";
export { ChevronBigUpIcon } from "./chevron-big-up";
+export { ChevronDownIcon } from "./chevron-down";
export { ChevronFilledDownIcon } from "./chevron-filled-down";
export { ChevronFilledLeftIcon } from "./chevron-filled-left";
export { ChevronFilledRightIcon } from "./chevron-filled-right";
export { ChevronFilledUpIcon } from "./chevron-filled-up";
+export { ChevronLeftIcon } from "./chevron-left";
+export { ChevronRightIcon } from "./chevron-right";
+export { ChevronUpIcon } from "./chevron-up";
export { CodeTextIcon } from "./code-text";
export { CollapsibleIcon } from "./collapsible";
export { CommitIcon } from "./commit";
diff --git a/packages/icons/src/chevron-down.tsx b/packages/icons/src/chevron-down.tsx
deleted file mode 100644
index f69bfcc3df..0000000000
--- a/packages/icons/src/chevron-down.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import * as React from "react";
-import type { IconProps } from "./types";
-
-export const ChevronDownIcon = React.forwardRef(
- ({ color = "currentColor", ...props }, forwardedRef) => {
- return (
-
- );
- }
-);
-
-ChevronDownIcon.displayName = "ChevronDownIcon";
diff --git a/packages/icons/src/chevron-left.tsx b/packages/icons/src/chevron-left.tsx
deleted file mode 100644
index 5c82c0ed9f..0000000000
--- a/packages/icons/src/chevron-left.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as React from "react";
-import type { IconProps } from "./types";
-
-export const ChevronLeftIcon = React.forwardRef(
- ({ color = "currentColor", ...props }, forwardedRef) => {
- return (
-
- );
- }
-);
-
-ChevronLeftIcon.displayName = "ChevronLeftIcon";
diff --git a/packages/icons/src/chevron-right.tsx b/packages/icons/src/chevron-right.tsx
deleted file mode 100644
index 5e8cb37d76..0000000000
--- a/packages/icons/src/chevron-right.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as React from "react";
-import type { IconProps } from "./types";
-
-export const ChevronRightIcon = React.forwardRef(
- ({ color = "currentColor", ...props }, forwardedRef) => {
- return (
-
- );
- }
-);
-
-ChevronRightIcon.displayName = "ChevronRightIcon";
diff --git a/packages/icons/src/chevron-up.tsx b/packages/icons/src/chevron-up.tsx
deleted file mode 100644
index 800090a5bc..0000000000
--- a/packages/icons/src/chevron-up.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as React from "react";
-import type { IconProps } from "./types";
-
-export const ChevronUpIcon = React.forwardRef(
- ({ color = "currentColor", ...props }, forwardedRef) => {
- return (
-
- );
- }
-);
-
-ChevronUpIcon.displayName = "ChevronUpIcon";
diff --git a/packages/icons/src/index.ts b/packages/icons/src/index.ts
index a683c3d0c4..2ec1632236 100644
--- a/packages/icons/src/index.ts
+++ b/packages/icons/src/index.ts
@@ -21,10 +21,6 @@ export * from "./chevron-double-up";
export * from "./chevron-double-down";
export * from "./chevron-double-left";
export * from "./chevron-double-right";
-export * from "./chevron-up";
-export * from "./chevron-down";
-export * from "./chevron-left";
-export * from "./chevron-right";
export * from "./cross-circled-filled";
export * from "./cross";
export * from "./magnifying-glass";
diff --git a/packages/sdk-components-react-radix/src/accordion.ws.ts b/packages/sdk-components-react-radix/src/accordion.ws.ts
index f5657b96ef..cd64ea7303 100644
--- a/packages/sdk-components-react-radix/src/accordion.ws.ts
+++ b/packages/sdk-components-react-radix/src/accordion.ws.ts
@@ -4,12 +4,14 @@ import {
HeaderIcon,
TriggerIcon,
ContentIcon,
+ ChevronDownIcon,
} from "@webstudio-is/icons/svg";
import type {
EmbedTemplateStyleDecl,
PresetStyle,
WsComponentMeta,
WsComponentPropsMeta,
+ WsEmbedTemplate,
} from "@webstudio-is/react-sdk";
import { div, h3, button } from "@webstudio-is/react-sdk/css-normalize";
import * as tc from "./theme/tailwind-classes";
@@ -37,20 +39,68 @@ const presetStyle = {
// border-b
const accordionItemStyles: EmbedTemplateStyleDecl[] = [tc.borderB()].flat();
-// flex
-const accordionHeaderStyles: EmbedTemplateStyleDecl[] = [tc.flex()].flat();
-
-// flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180
-const accordionTriggerStyles: EmbedTemplateStyleDecl[] = [
- tc.flex(),
- tc.flex(1),
- tc.items("center"),
- tc.justify("between"),
- tc.py(4),
- tc.font("medium"),
- tc.transition("all"),
- tc.hover([tc.underline()].flat()),
-].flat();
+const createAccordionTrigger = ({
+ children,
+}: {
+ children: WsEmbedTemplate;
+}): WsEmbedTemplate[number] => ({
+ type: "instance",
+ component: "AccordionHeader",
+ // flex
+ styles: [tc.flex()].flat(),
+ children: [
+ {
+ type: "instance",
+ component: "AccordionTrigger",
+ // flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180
+ styles: [
+ tc.flex(),
+ tc.flex(1),
+ tc.items("center"),
+ tc.justify("between"),
+ tc.py(4),
+ tc.font("medium"),
+ tc.hover([tc.underline()].flat()),
+ tc.property("--accordion-trigger-icon-transform", "0deg"),
+ tc.state(
+ [tc.property("--accordion-trigger-icon-transform", "180deg")],
+ "[data-state=open]"
+ ),
+ ].flat(),
+ children: [
+ ...children,
+ {
+ type: "instance",
+ component: "Box",
+ // h-4 w-4 shrink-0 transition-transform duration-200
+ styles: [
+ tc.property("rotate", "--accordion-trigger-icon-transform"),
+ tc.h(4),
+ tc.w(4),
+ tc.shrink(0),
+ tc.transition("all"),
+ tc.duration(200),
+ ].flat(),
+ children: [
+ {
+ type: "instance",
+ component: "HtmlEmbed",
+ label: "Chevron Icon",
+ props: [
+ {
+ type: "string",
+ name: "code",
+ value: ChevronDownIcon,
+ },
+ ],
+ children: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+});
// overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down
// pb-4 pt-0
@@ -95,19 +145,9 @@ export const metaAccordion: WsComponentMeta = {
component: "AccordionItem",
styles: accordionItemStyles,
children: [
- {
- type: "instance",
- component: "AccordionHeader",
- styles: accordionHeaderStyles,
- children: [
- {
- type: "instance",
- component: "AccordionTrigger",
- styles: accordionTriggerStyles,
- children: [{ type: "text", value: "Is it accessible?" }],
- },
- ],
- },
+ createAccordionTrigger({
+ children: [{ type: "text", value: "Is it accessible?" }],
+ }),
{
type: "instance",
component: "AccordionContent",
@@ -127,19 +167,9 @@ export const metaAccordion: WsComponentMeta = {
component: "AccordionItem",
styles: accordionItemStyles,
children: [
- {
- type: "instance",
- component: "AccordionHeader",
- styles: accordionHeaderStyles,
- children: [
- {
- type: "instance",
- component: "AccordionTrigger",
- styles: accordionTriggerStyles,
- children: [{ type: "text", value: "Is it styled?" }],
- },
- ],
- },
+ createAccordionTrigger({
+ children: [{ type: "text", value: "Is it styled?" }],
+ }),
{
type: "instance",
component: "AccordionContent",
@@ -160,19 +190,9 @@ export const metaAccordion: WsComponentMeta = {
component: "AccordionItem",
styles: accordionItemStyles,
children: [
- {
- type: "instance",
- component: "AccordionHeader",
- styles: accordionHeaderStyles,
- children: [
- {
- type: "instance",
- component: "AccordionTrigger",
- styles: accordionTriggerStyles,
- children: [{ type: "text", value: "Is it animated?" }],
- },
- ],
- },
+ createAccordionTrigger({
+ children: [{ type: "text", value: "Is it animated?" }],
+ }),
{
type: "instance",
component: "AccordionContent",
diff --git a/packages/sdk-components-react-radix/src/theme/tailwind-classes.ts b/packages/sdk-components-react-radix/src/theme/tailwind-classes.ts
index 081f9c99bc..be717a1bf5 100644
--- a/packages/sdk-components-react-radix/src/theme/tailwind-classes.ts
+++ b/packages/sdk-components-react-radix/src/theme/tailwind-classes.ts
@@ -7,9 +7,26 @@ import {
parseCssValue,
parseBoxShadow,
StyleValue,
+ type StyleProperty,
} from "@webstudio-is/css-data";
import type { EvaluatedDefaultTheme } from "./radix-common-types";
+export const property = (
+ property: StyleProperty,
+ value: string
+): EmbedTemplateStyleDecl => {
+ if (value.startsWith("--")) {
+ return {
+ property,
+ value: { type: "var", value: value.slice(2), fallbacks: [] },
+ };
+ }
+ return {
+ property,
+ value: { type: "unparsed", value },
+ };
+};
+
// https://github.com/tailwindlabs/tailwindcss/blob/master/src/css/preflight.css
const preflight = (): EmbedTemplateStyleDecl[] => {
const borderColorValue = parseCssValue("color", theme("colors")["border"]);
@@ -585,11 +602,16 @@ export const grow = (): EmbedTemplateStyleDecl[] => {
return [
{
property: "flexGrow",
- value: {
- type: "unit",
- value: 1,
- unit: "number",
- },
+ value: { type: "unit", value: 1, unit: "number" },
+ },
+ ];
+};
+
+export const shrink = (value: number): EmbedTemplateStyleDecl[] => {
+ return [
+ {
+ property: "flexGrow",
+ value: { type: "unit", value, unit: "number" },
},
];
};
@@ -818,7 +840,9 @@ export const pointerEvents = (
return [{ property: "pointerEvents", value: { type: "keyword", value } }];
};
-export const transition = (value: "none" | "all"): EmbedTemplateStyleDecl[] => {
+export const transition = (
+ value: "none" | "all" | "transform"
+): EmbedTemplateStyleDecl[] => {
if (value === "none") {
return [
{
@@ -830,7 +854,7 @@ export const transition = (value: "none" | "all"): EmbedTemplateStyleDecl[] => {
return [
{
property: "transitionProperty",
- value: { type: "keyword", value: "all" },
+ value: { type: "keyword", value },
},
{
property: "transitionTimingFunction",
@@ -843,6 +867,15 @@ export const transition = (value: "none" | "all"): EmbedTemplateStyleDecl[] => {
];
};
+export const duration = (ms: number): EmbedTemplateStyleDecl[] => {
+ return [
+ {
+ property: "transitionDuration",
+ value: { type: "unit", value: ms, unit: "ms" },
+ },
+ ];
+};
+
export const hover = (
value: EmbedTemplateStyleDecl[]
): EmbedTemplateStyleDecl[] => {