diff --git a/eslint.config.mjs b/eslint.config.mjs index 46a4208721..a2fac97a39 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,6 +25,7 @@ export default defineConfig([ 'semcore/icon/**/*.mjs', 'semcore/icon/**/*.js', 'semcore/icon/**/*.d.ts', + 'figma/*.figma.jsx', ]), { files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], plugins: { js }, extends: ['js/recommended'] }, pluginReact.configs.flat.recommended, diff --git a/figma-custom.config.json b/figma-custom.config.json new file mode 100644 index 0000000000..413a9acc4c --- /dev/null +++ b/figma-custom.config.json @@ -0,0 +1,12 @@ +{ + "codeConnect": { + "include": ["figma/*.figma.template.js"], + "exclude": ["Example.figma.template.js"], + "label": "React", + "parser": "custom", + "parserCommand": "pnpm tsm figma/utils/parser.ts", + "paths": { + "@semcore/ui/*": ["semcore/*/src"] + } + } +} \ No newline at end of file diff --git a/figma.config.json b/figma.config.json new file mode 100644 index 0000000000..2d864dfa67 --- /dev/null +++ b/figma.config.json @@ -0,0 +1,10 @@ +{ + "codeConnect": { + "include": ["figma/*.figma.jsx"], + "label": "React", + "paths": { + "@semcore/ui/*": ["semcore/*/src"] + }, + "interactiveSetupFigmaFileUrl": "https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring--%E2%9D%96-Core-Components" + } +} \ No newline at end of file diff --git a/figma/Accordion.figma.jsx b/figma/Accordion.figma.jsx new file mode 100644 index 0000000000..26fa7e7393 --- /dev/null +++ b/figma/Accordion.figma.jsx @@ -0,0 +1,68 @@ +import figma from 'figma-api'; +import Accordion from '@semcore/ui/accordion'; +import { Box } from '@semcore/ui/base-components'; + +figma.connect( + Accordion.Item.Toggle, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=10085-55594&t=wmeCZaspBw4PtpTZ-11', { + props: { + use: figma.enum('use', { + 'primary': 'primary', + 'secondary': 'secondary', + }), + + }, + example: () => ( + + + + /* Add text ${index + 1} */ + + + ) +}); + +figma.connect( + Accordion.Item.Collapse, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=13079-111795&t=wmeCZaspBw4PtpTZ-11', { + + example: () => ( + + {/* Add text ${index + 1} */} + + ) +}); + +figma.connect( + Accordion.Item, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=13079-111805&t=wmeCZaspBw4PtpTZ-11', { + props: { + toggle: figma.children('Accordion.Item.Toggle'), + collapse: figma.children('Accordion.Item.Collapse'), + }, + example: ({ toggle, collapse }) => ( + + {collapse} + {toggle} + + ), +}); + +figma.connect( + Accordion, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=13079-111971&t=wmeCZaspBw4PtpTZ-11', { + props: { + children: figma.children('Accordion.Item'), + use: figma.nestedProps('Accordion.Item.Toggle', { + use: figma.enum('use', { + 'primary': 'primary', + 'secondary': 'secondary', + }), + }), + }, + example: ({ children, use }) => ( + + {children} + + ) +}); \ No newline at end of file diff --git a/figma/Badge.figma.jsx b/figma/Badge.figma.jsx new file mode 100644 index 0000000000..43037f66b3 --- /dev/null +++ b/figma/Badge.figma.jsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect/react'; +import Badge from '@semcore/ui/badge'; + +figma.connect( + Badge, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/%E2%9D%96-Core-Components-(Refactoring)?node-id=10059-44175&t=hkjybGSILqRb6bQU-4', + { + props: { + label: figma.textContent('↳ text'), + bg: figma.enum('type', { + '🔵 admin': figma.boolean('invert', { false: 'blue-400', true: 'white' }), + '🔴 alpha': figma.boolean('invert', { false: 'red-400', true: 'white' }), + '🟠 beta': figma.boolean('invert', { false: 'orange-400', true: 'white' }), + '🟢 new': figma.boolean('invert', { false: 'green-400', true: 'white' }), + '🟣 for you': figma.boolean('invert', { false: 'violet-400', true: 'white' }), + '⚫️ soon': figma.boolean('invert', { false: 'gray-400', true: 'white' }), + }), + color: figma.boolean('invert', { + true: 'text-primary', + }), + }, + example: (props) => {props.label}, + }, +); diff --git a/figma/BaseTrigger.figma.jsx b/figma/BaseTrigger.figma.jsx new file mode 100644 index 0000000000..3b163a6256 --- /dev/null +++ b/figma/BaseTrigger.figma.jsx @@ -0,0 +1,123 @@ +import figma from '@figma/code-connect'; +import { LinkTrigger } from '@semcore/ui/base-trigger'; +import Select from '@semcore/ui/select'; + +figma.connect( + LinkTrigger, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=10733-114376&t=TXEgCxM6iJO0FYiJ-11', + { + variant: { '← addon': 'false', 'addon →': 'false', 'icon only': 'false' }, + props: { + size: figma.enum('size', { + M: 'm', + L: 'l', + }), + placeholder: figma.textContent('↳ text'), + state: figma.enum('state', { + active: 'active', + invalid: 'invalid', + valid: 'valid', + }), + disabled: figma.enum('state', { + disabled: true, + }), + loading: figma.boolean('loading'), + }, + example: (props) => + + {addonLeft} + {content} + {addonRight} + + + + {/* option */} + + + ; + }, + }, +); + +figma.connect( + LinkTrigger, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=10733-114376&t=TXEgCxM6iJO0FYiJ-11', + { + variant: { 'icon only': 'true' }, + props: { + size: figma.enum('size', { + M: 'm', + L: 'l', + }), + addonLeft: figma.children('← - - addon properties'), + state: figma.enum('state', { + active: 'active', + invalid: 'invalid', + valid: 'valid', + }), + disabled: figma.enum('state', { + disabled: true, + }), + loading: figma.boolean('loading'), + title: figma.textContent('↳ title'), + }, + example: ({ size, addonLeft, state, loading, disabled, title }) => ( + + ), + }, +); diff --git a/figma/Breadcrumbs.figma.jsx b/figma/Breadcrumbs.figma.jsx new file mode 100644 index 0000000000..09557abc6a --- /dev/null +++ b/figma/Breadcrumbs.figma.jsx @@ -0,0 +1,50 @@ +import figma from '@figma/code-connect/react'; +import Breadcrumbs from '@semcore/ui/breadcrumbs'; + +figma.connect( + Breadcrumbs, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=11878-115146&t=Q0bSsRErIQ7IEZAU-11', + { + variant: { 'folder': 'true' }, + props: { + homeLink: figma.nestedProps('Home link', { + label: figma.textContent('↳ text'), + }), + folderLink: figma.nestedProps('Folder link', { + label: figma.textContent('↳ text'), + }), + productLink: figma.nestedProps('Product link', { + label: figma.textContent('↳ text'), + }), + }, + example: ({ homeLink, folderLink, productLink }) => ( + + {homeLink.label} + {folderLink.label} + {productLink.label} + + ), + }, +); + +figma.connect( + Breadcrumbs, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=11878-115146&t=Q0bSsRErIQ7IEZAU-11', + { + variant: { 'folder': 'false' }, + props: { + homeLink: figma.nestedProps('Home link', { + label: figma.textContent('↳ text'), + }), + productLink: figma.nestedProps('Product link', { + label: figma.textContent('↳ text'), + }), + }, + example: ({ homeLink, productLink }) => ( + + {homeLink.label} + {productLink.label} + + ), + }, +); \ No newline at end of file diff --git a/figma/BulkTextarea.figma.jsx b/figma/BulkTextarea.figma.jsx new file mode 100644 index 0000000000..b4d9303909 --- /dev/null +++ b/figma/BulkTextarea.figma.jsx @@ -0,0 +1,48 @@ +import figma from '@figma/code-connect/react'; +import BulkTextarea from '@semcore/ui/bulk-textarea'; +import { Text } from '@semcore/ui/typography'; +import { Flex } from '@semcore/ui/base-components'; + +// add placeholder somehow, for now Figma Code Connect doesn't see placeholder + +figma.connect( + BulkTextarea, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=48599-7546&t=tjfdRa8KRbX0lwpz-11', + { + props: { + // placeholder: figma.textContent('↳ text'), + label: figma.textContent('↳ label'), + size: figma.enum('size', { + M: 'm', + L: 'l', + }), + state: figma.enum('state', { + normal: 'normal', + invalid: 'invalid', + }), + readonly: figma.enum('state', { + 'read-only': true, + }), + }, + + example: ({ size, readonly, label }) => + + + {label} + + + + + + + + + , + }, +); \ No newline at end of file diff --git a/figma/Button.figma.jsx b/figma/Button.figma.jsx new file mode 100644 index 0000000000..905f5f9055 --- /dev/null +++ b/figma/Button.figma.jsx @@ -0,0 +1,134 @@ +import figma from '@figma/code-connect/react'; +import Button from '@semcore/ui/button'; +import { Text } from '@semcore/ui/typography'; + +// Need to add a variant for cases when dot is enabled + +figma.connect( + Button, + 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=10043-43724&t=nVbIFrY5EvgteOqk-11', + { + variant: { 'icon only': 'false' }, + props: { + size: figma.enum('size', { + L: 'l', + M: 'm', + }), + use: figma.enum('use', { + primary: 'primary', + secondary: 'secondary', + tertiary: 'tertiary', + }), + theme: figma.enum('theme', { + '🔵 info': 'info', + '🟢 success': 'success', + '🔴 danger': 'danger', + '⚫️ muted': 'muted', + '⚪️ invert': 'invert', + }), + active: figma.enum('state', { + active: true, + }), + loading: figma.boolean('loading'), + disabled: figma.enum('state', { + disabled: true, + }), + + // Cannot be used with the current structure. + // These mappings show instances and text content, but they are not working with conditional rendering for now. So I'm leaving them for possible future updates from Code Connect. + // label: figma.textContent('↳ text'), + // labelAddon: figma.textContent('↳ textAddon'), + + // addonLeft: figma.boolean('← addon', { + // true: figma.instance('← - - - addon'), + // false: undefined, + // }), + + // addonRight: figma.boolean('addon →', { + // true: figma.instance('addon properties - - →'), + // false: undefined, + // }), + + // addonLeft: figma.boolean('← addon', { + // true: {/* addon */}, + // }), + + // addonRight: figma.boolean('addon →', { + // true: {/* addon */}, + // }), + + addonLeft: figma.enum('icon only', { + false: figma.boolean('← addon', { + true: {/* addon */}, + }), + }), + addonRight: figma.enum('icon only', { + false: figma.boolean('addon →', { + true: {/* addon */}, + }), + }), + + content: figma.enum('icon only', { + false: figma.boolean('← addon', { + true: {/* button label */}, + false: figma.boolean('addon →', { + true: {/* button label */}, + false: '{/* button label */}', + }), + }), + }), + + // For now, textAddon shows placeholder. Need to figure out how to show value from labelAddon here, and how to expand the component. + textAddon: figma.boolean('textAddon →', { + true: {/* text addon */}, + }), + }, + + example: ({ size, use, theme, disabled, active, loading, addonLeft, content, textAddon, addonRight }) => ( + + ), + }, +); + +figma.connect(Button, 'https://www.figma.com/design/RLic9ruqNNm6qgARKFk5Ae/-Refactoring-WIP--%E2%9D%96-Core-Components?node-id=10043-43724&t=nVbIFrY5EvgteOqk-11', { + variant: { 'icon only': 'true' }, + props: { + size: figma.enum('size', { + L: 'l', + }), + use: figma.enum('use', { + primary: 'primary', + tertiary: 'tertiary', + }), + theme: figma.enum('theme', { + '🔵 info': 'info', + '�� success': 'success', + '🔴 danger': 'danger', + '⚫️ muted': 'muted', + '⚪️ invert': 'invert', + }), + active: figma.enum('state', { + active: true, + }), + loading: figma.boolean('loading'), + disabled: figma.enum('state', { + disabled: true, + }), + title: figma.textContent('↳ title'), + }, + example: (props) => ( +