├── .gitignore ├── src ├── ui │ ├── style.module.css │ ├── ui.html │ └── index.tsx └── figma │ └── index.ts ├── .prettierrc ├── .vscode └── settings.json ├── shims-css.d.ts ├── manifest.json ├── babel.config.json ├── tsconfig.json ├── README.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | dist -------------------------------------------------------------------------------- /src/ui/style.module.css: -------------------------------------------------------------------------------- 1 | .foo { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 80, 5 | "trailingComma": "none" 6 | } -------------------------------------------------------------------------------- /src/ui/ui.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true 4 | } 5 | -------------------------------------------------------------------------------- /shims-css.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' { 2 | const content: { [className: string]: string } 3 | export default content 4 | } 5 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "your-plugin-name", 3 | "id": "your-plugin-id", 4 | "api": "1.0.0", 5 | "main": "dist/js/figma.js", 6 | "ui": "dist/ui.html" 7 | } 8 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/env", 5 | { 6 | "useBuiltIns": "usage", 7 | "corejs": 3 8 | } 9 | ] 10 | ], 11 | "plugins": [ 12 | [ 13 | "@hcysunyang/vue-next-jsx", 14 | { 15 | "source": "vue" 16 | } 17 | ] 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "dist", 5 | "sourceMap": false, 6 | "target": "ESNext", 7 | "module": "ESNext", 8 | "moduleResolution": "node", 9 | "allowJs": false, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "resolveJsonModule": true, 13 | "esModuleInterop": true, 14 | "removeComments": false, 15 | "jsx": "preserve", 16 | "lib": ["esnext", "dom"], 17 | "rootDir": ".", 18 | "typeRoots": ["./node_modules/@types", "./node_modules/@figma"] 19 | }, 20 | "include": ["src", "shims-css.d.ts"] 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue3 Figma Plugin Starter 2 | 3 | Use Vue3 to build figma plugin 4 | 5 | - Use `webpack` to develop and build 6 | - Integrate [vue-next-jsx](https://github.com/HcySunYang/vue-next-jsx) for Vue3 `jsx/tsx` 7 | - Everything is out of the box 8 | 9 | ## Setup 10 | 11 | - clone this repo 12 | 13 | - install dependencies 14 | 15 | ```sh 16 | yarn 17 | # or 18 | yarn install 19 | ``` 20 | 21 | - Run dev 22 | 23 | ```sh 24 | yarn dev 25 | ``` 26 | 27 | - Run your plugin 28 | 29 | ![Run](https://user-images.githubusercontent.com/14146560/86773592-61602e80-c088-11ea-8ffc-feeba20803e5.png) 30 | 31 | ![vue3 figma plugin starter](https://user-images.githubusercontent.com/14146560/86773310-19d9a280-c088-11ea-863c-4d9ff113bcc5.png) 32 | 33 | ## Note 34 | 35 | Remember to modify the `name` and `id` in the `manifest.json` file 36 | -------------------------------------------------------------------------------- /src/ui/index.tsx: -------------------------------------------------------------------------------- 1 | import { createApp, ref } from 'vue' 2 | import style from './style.module.css' 3 | 4 | createApp({ 5 | setup() { 6 | const refCount = ref(5) 7 | function handler() { 8 | parent.postMessage( 9 | { pluginMessage: { type: 'create-rectangles', count: refCount.value } }, 10 | '*' 11 | ) 12 | } 13 | 14 | function cancel() { 15 | parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*') 16 | } 17 | 18 | return () => ( 19 |
20 |

Byted Motion

21 |

22 | Count: 23 |

24 | 27 | 30 |
31 | ) 32 | } 33 | }).mount('#app') 34 | -------------------------------------------------------------------------------- /src/figma/index.ts: -------------------------------------------------------------------------------- 1 | // This shows the HTML page in "ui.html". 2 | figma.showUI(__html__, { 3 | width: 640, 4 | height: 540 5 | }) 6 | 7 | figma.currentPage.findAll() 8 | // Calls to "parent.postMessage" from within the HTML page will trigger this 9 | // callback. The callback will be passed the "pluginMessage" property of the 10 | // posted message. 11 | figma.ui.onmessage = async (msg) => { 12 | // One way of distinguishing between different types of messages sent from 13 | // your HTML page is to use an object with a "type" property like this. 14 | if (msg.type === 'create-rectangles') { 15 | const nodes: SceneNode[] = [] 16 | for (let i = 0; i < msg.count; i++) { 17 | const rect = figma.createRectangle() 18 | rect.x = i * 150 19 | rect.fills = [{ type: 'SOLID', color: { r: 1, g: 0.5, b: 0 } }] 20 | figma.currentPage.appendChild(rect) 21 | nodes.push(rect) 22 | } 23 | figma.currentPage.selection = nodes 24 | figma.viewport.scrollAndZoomIntoView(nodes) 25 | } 26 | 27 | // Make sure to close the plugin when you're done. Otherwise the plugin will 28 | // keep running, which shows the cancel button at the bottom of the screen. 29 | figma.closePlugin() 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3-figma-plugin-starter", 3 | "version": "0.1.0", 4 | "main": "index.js", 5 | "repository": "https://github.com/HcySunYang/vue3-figma-plugin-starter.git", 6 | "author": "HcySunYang ", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "NODE_ENV=development webpack --config build/base.js --watch", 10 | "build": "NODE_ENV=development webpack --config build/base.js", 11 | "commit": "git-cz", 12 | "format": "prettier --write --parser typescript \"src/**/*.ts?(x)\"", 13 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 14 | "postpublish": "git add CHANGELOG.md && git commit -m 'chore: changelog [ci skip]' && git push" 15 | }, 16 | "dependencies": { 17 | "core-js": "^3.6.5", 18 | "vue": "^3.0.0-beta.18" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.10.4", 22 | "@babel/preset-env": "^7.10.4", 23 | "@figma/plugin-typings": "^1.15.0", 24 | "@hcysunyang/babel-plugin-vue-next-jsx": "^0.2.0", 25 | "@intervolga/optimize-cssnano-plugin": "^1.0.6", 26 | "babel-loader": "^8.1.0", 27 | "clean-webpack-plugin": "^3.0.0", 28 | "commitizen": "^4.1.2", 29 | "conventional-changelog-cli": "^2.0.34", 30 | "css-loader": "^3.6.0", 31 | "cz-conventional-changelog": "^3.2.0", 32 | "file-loader": "^6.0.0", 33 | "html-webpack-plugin": "^4.3.0", 34 | "husky": "^4.2.5", 35 | "lint-staged": "^10.2.11", 36 | "mini-css-extract-plugin": "^0.9.0", 37 | "postcss-loader": "^3.0.0", 38 | "prettier": "^2.0.5", 39 | "style-loader": "^1.2.1", 40 | "ts-loader": "^7.0.5", 41 | "typescript": "^3.9.6", 42 | "webpack": "^4.43.0", 43 | "webpack-chain": "^6.5.0", 44 | "webpack-cli": "^3.3.12" 45 | }, 46 | "husky": { 47 | "hooks": { 48 | "pre-commit": "lint-staged" 49 | } 50 | }, 51 | "lint-staged": { 52 | "*.js": [ 53 | "npm run format", 54 | "git add" 55 | ] 56 | }, 57 | "config": { 58 | "commitizen": { 59 | "path": "cz-conventional-changelog" 60 | } 61 | } 62 | } 63 | --------------------------------------------------------------------------------