Skip to content

Commit

Permalink
Merge pull request #1102 from openameba/chore/code-connect
Browse files Browse the repository at this point in the history
Initial Setup for Figma Connect
  • Loading branch information
herablog authored Sep 18, 2024
2 parents 2570367 + a73822b commit 1a73dfe
Show file tree
Hide file tree
Showing 18 changed files with 3,483 additions and 45 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-icon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
- name: Update Icons
env:
FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
FIGMA_ACCESS_TOKEN: ${{ secrets.FIGMA_TOKEN_CODE_CONNECT }} # This is for Figma Code Connect in spindle-ui
FILE_KEY: ${{ secrets.FIGMA_ICON_FILE_KEY }}
NODE_ID: ${{ secrets.FIGMA_ICON_NODE_ID }}
ICON_NAMES: ${{ github.event.inputs.modified_components }}
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/figma-code-connect.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Publish Figma Code Connect

on:
push:
paths:
- packages/spindle-ui/src/**/*.figma.tsx
branches:
- main

jobs:
code-connect:
name: Code Connect
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm i -g @figma/code-connect
- run: figma connect publish
env:
FIGMA_ACCESS_TOKEN: ${{ secrets.FIGMA_TOKEN_CODE_CONNECT }}
working-directory: packages/spindle-ui
1 change: 1 addition & 0 deletions packages/spindle-ui/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ regconfig.json
tsconfig.json
design-doc.md
setup-tests.ts
*.figma.tsx
6 changes: 6 additions & 0 deletions packages/spindle-ui/figma.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"codeConnect": {
"parser": "react",
"include": ["src/**/*.tsx"]
}
}
7 changes: 6 additions & 1 deletion packages/spindle-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
"build:script:esm:rename": "npx renamer --find js --replace mjs 'dist/**'",
"build:style": "postcss src/**/*.css src/*.css --base src -d dist/",
"preicon": "npx rimraf 'src/Icon/!(*.stories).tsx' && npx cpx '../spindle-icons/dist/svg/!(sprite).svg' icon-tmp",
"icon": "svgr --out-dir src/Icon icon-tmp",
"icon": "run-s icon:react icon:connect",
"posticon": "npx rimraf icon-tmp",
"icon:react": "svgr --out-dir src/Icon icon-tmp",
"icon:connect": "npx tsx scripts/figma-connect-icons.ts",
"prepublishOnly": "yarn build && yarn cp"
},
"license": "MIT",
Expand All @@ -61,6 +63,7 @@
"react-merge-refs": "^1.1.0"
},
"devDependencies": {
"@figma/code-connect": "^1.1.3",
"@mdx-js/react": "^1.6.22",
"@storybook/addon-a11y": "^6.5.9",
"@storybook/addon-actions": "^6.5.9",
Expand All @@ -83,6 +86,8 @@
"bundlewatch": "^0.4.0",
"cssnano": "^7.0.0",
"dialog-polyfill": "^0.5.6",
"dotenv": "^16.4.5",
"figma-api": "^1.11.0",
"firebase-tools": "^13.0.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.0.0",
Expand Down
62 changes: 62 additions & 0 deletions packages/spindle-ui/scripts/figma-connect-icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import fs from 'fs';
import * as Figma from 'figma-api';
import dotenv from 'dotenv';

dotenv.config();

if (!process.env.FIGMA_ACCESS_TOKEN) {
throw new Error(
'Figma personal token should be set as an environment variable "FIGMA_ACCESS_TOKEN".',
);
}

export const figma = new Figma.Api({
personalAccessToken: process.env.FIGMA_ACCESS_TOKEN,
});

const fileKey = 'G445fTskctZn7y3gkmSp8xaT';
const nodeId = '991-0';
const fileName = 'icon';

async function connectIcons() {
const result = await figma.getFileNodes(fileKey, [nodeId]);
const components = Object.entries(
result.nodes[nodeId.replace('-', ':')]?.components || {},
).map(([key, value]) => {
return {
// Convert snake_case to PascalCase
name: value.name
.split('_')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(''),
figmaUrl: `https://www.figma.com/design/${fileKey}/${fileName}?node-id=${key.replace(
':',
'-',
)}`,
};
});

const uniqueNames = new Set([...components.map((c) => c.name)]);

fs.writeFileSync(
'src/icons.figma.tsx',
`\
import figma from '@figma/code-connect'
import {
${Array.from(uniqueNames)
.map((iconName) => `${iconName},`)
.join('\n')}
} from './Icon'
${components
.map(
(c) =>
`figma.connect(${c.name}, '${c.figmaUrl}', { imports: ["import { ${c.name} } from '@openameba/spindle-ui/Icon';"] })`,
)
.join('\n')}
`,
);
}

connectIcons();
53 changes: 53 additions & 0 deletions packages/spindle-ui/src/Button/Button.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import { Button } from './Button';
import figma from '@figma/code-connect';

figma.connect(
Button,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=1789-29120&t=5pAze6eM9wAFTPFz-0',
{
imports: ["import { Button } from '@openameba/spindle-ui';"],
props: {
size: figma.enum('size', {
large: 'large',
medium: 'medium',
small: 'small',
}),
variant: figma.enum('variant', {
contained: 'contained',
outlined: 'outlined',
neutral: 'neutral',
lighted: 'lighted',
danger: 'danger',
}),
layout: figma.enum('layout', {
intrinsic: 'intrinsic',
fullWidth: 'fullWidth',
}),
disabled: figma.boolean('disabled'),
content: figma.nestedProps('Instance / Content', {
iconPosition: figma.enum('iconPosition', {
start: 'start',
end: 'end',
}),
icon: figma.boolean('icon', {
true: figma.instance('└ iconName'),
false: undefined,
}),
label: figma.textContent('btn_txt'),
}),
},
example: ({ size, variant, layout, disabled, content }) => (
<Button
size={size}
variant={variant}
layout={layout}
disabled={disabled}
icon={content.icon}
iconPosition={content.iconPosition}
>
{content.label}
</Button>
),
},
);
48 changes: 48 additions & 0 deletions packages/spindle-ui/src/Dialog/Dialog.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { Dialog } from './Dialog';
import figma from '@figma/code-connect';
import { SubtleButton } from 'src/SubtleButton';
import { Button } from 'src/Button';

figma.connect(
Dialog,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=452-38043',
{
imports: ["import { Dialog } from '@openameba/spindle-ui';"],
props: {
title: figma.boolean('Title', {
true: <Dialog.Title></Dialog.Title>,
false: undefined,
}),
description: figma.boolean('Description', {
true: <Dialog.Body></Dialog.Body>,
false: undefined,
}),
closeButton: figma.boolean('Close Button', {
true: <SubtleButton size="medium">とじる</SubtleButton>,
false: undefined,
}),
content: figma.nestedProps('Button Layout', {
layout: figma.enum('Layout', {
Vertical: 'column',
Horizontal: 'row',
}),
secondaryButton: figma.boolean('Secondary Button2', {
true: <Button layout="fullWidth" size="medium"></Button>,
false: undefined,
}),
}),
},
example: ({ title, description, closeButton, content }) => (
<Dialog.Frame>
{title}
{description}
<Dialog.ButtonGroup direction={content.layout}>
<Button layout="fullWidth" size="medium" autoFocus></Button>
{content.secondaryButton}
{closeButton}
</Dialog.ButtonGroup>
</Dialog.Frame>
),
},
);
28 changes: 28 additions & 0 deletions packages/spindle-ui/src/Form/Checkbox.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { Checkbox } from './Checkbox';
import figma from '@figma/code-connect';

figma.connect(
Checkbox,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=473-33059&t=BiQUBKKifVQV5TbP-0',
{
imports: ["import { Checkbox } from '@openameba/spindle-ui/Form';"],
props: {
active: figma.boolean('Active'),
hover: figma.boolean('Focus Ring'),
label: figma.string('Label'),
name: figma.string('Name'),
id: figma.string('id'),
value: figma.string('value'),
},
example: ({ active, label, name, id, value }) => (
<Checkbox
id={id}
name={name}
value={value}
aria-label={label}
checked={active}
></Checkbox>
),
},
);
21 changes: 21 additions & 0 deletions packages/spindle-ui/src/Form/Radio.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { Radio } from './Radio';
import figma from '@figma/code-connect';

figma.connect(
Radio,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=473-33051&t=BiQUBKKifVQV5TbP-0',
{
imports: ["import { Radio } from '@openameba/spindle-ui/Form';"],
props: {
active: figma.boolean('Active'),
hover: figma.boolean('Focus Ring'),
label: figma.string('Label'),
name: figma.string('Name'),
id: figma.string('id'),
},
example: ({ active, label, name, id }) => (
<Radio id={id} name={name} aria-label={label} checked={active}></Radio>
),
},
);
19 changes: 19 additions & 0 deletions packages/spindle-ui/src/Form/ToggleSwitch.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { ToggleSwitch } from './ToggleSwitch';
import figma from '@figma/code-connect';

figma.connect(
ToggleSwitch,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=473-33067&t=BiQUBKKifVQV5TbP-0',
{
imports: ["import { ToggleSwitch } from '@openameba/spindle-ui/Form';"],
props: {
active: figma.boolean('Active'),
id: figma.string('id'),
label: figma.string('label'),
},
example: ({ active, id, label }) => (
<ToggleSwitch id={id} aria-label={label} checked={active}></ToggleSwitch>
),
},
);
38 changes: 38 additions & 0 deletions packages/spindle-ui/src/IconButton/IconButton.figma.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { IconButton } from './IconButton';
import figma from '@figma/code-connect';

figma.connect(
IconButton,
'https://www.figma.com/design/FSgvRthUiMMXWgrSE4RUgr/Spindle-UI?node-id=4042-25426&t=R8kIhRlvP5CmX9Qn-0',
{
imports: ["import { IconButton } from '@openameba/spindle-ui';"],
props: {
size: figma.enum('Size', {
Large: 'large',
Medium: 'medium',
Small: 'small',
'Ex Small': 'exSmall',
}),
style: figma.enum('Style', {
Contained: 'contained',
Outlined: 'outlined',
Neutral: 'neutral',
Lighted: 'lighted',
}),
disabled: figma.boolean('Disabled'),
children: figma.children('*'),
label: figma.string('Label'),
},
example: ({ size, style, disabled, children, label }) => (
<IconButton
size={size}
variant={style}
disabled={disabled}
aria-label={label}
>
{children}
</IconButton>
),
},
);
Loading

0 comments on commit 1a73dfe

Please sign in to comment.