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[] => {