Repository: thomas-lowry/figma-plugin-ds-svelte Branch: master Commit: 612afa98a79d Files: 28 Total size: 121.2 KB Directory structure: gitextract_z97jab7u/ ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── public/ │ └── index.html ├── rollup.config.js └── src/ ├── App.svelte ├── components/ │ ├── Button/ │ │ └── index.svelte │ ├── Checkbox/ │ │ └── index.svelte │ ├── Disclosure/ │ │ └── index.svelte │ ├── DisclosureItem/ │ │ └── index.svelte │ ├── Icon/ │ │ └── index.svelte │ ├── IconButton/ │ │ └── index.svelte │ ├── Input/ │ │ └── index.svelte │ ├── Label/ │ │ └── index.svelte │ ├── OnboardingTip/ │ │ └── index.svelte │ ├── Radio/ │ │ └── index.svelte │ ├── Section/ │ │ └── index.svelte │ ├── SelectDivider/ │ │ └── index.svelte │ ├── SelectItem/ │ │ └── index.svelte │ ├── SelectMenu/ │ │ └── index.svelte │ ├── Switch/ │ │ └── index.svelte │ ├── Textarea/ │ │ └── index.svelte │ └── Type/ │ └── index.svelte ├── global.css ├── index.js └── test.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization *.* linguist-language=JavaScript ================================================ FILE: .gitignore ================================================ public/components.js todo.md .DS_Store node_modules yarn.lock logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage *.lcov # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .env.test # parcel-bundler cache (https://parceljs.org/) .cache # next.js build output .next # nuxt.js build output .nuxt # vuepress build output .vuepress/dist # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 Thomas Lowry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Figma Plugin DS Svelte WORK IN PROGRESS—This is a Svelte version of the Figma Plugin DS specifically for use in creating Figma Plugins. I decided to create this because Svelte seems like a great lightweight approach well suited for creating Figma plugins, and also improves the developer experience when compared to my vanilla JS Figma Plugin DS due to simplified markup. You can also get started with [Figsvelte](https://github.com/thomas-lowry/figsvelte), a boilerplate for Figma plugins that already has this library setup as a dependency. ## Installation To install into your own Svelte project. `npm i -D figma-plugin-ds-svelte` ## To use ```javascript //import the global css which includes Figma color, spacing, and type vars //also includes a basic set of utility classes import { GlobalCSS } from 'figma-plugin-ds-svelte'; //import the desired components import { Button, Input, SelectMenu } from 'figma-plugin-ds-svelte'; ``` --- ## Components _All components can accept class props to add global or utility classes to each component_ * [Button](#Button) * [Checkbox](#Checkbox) * [Disclosure panel](#Disclosure) * [Icon](#Icon) * [Icon button](#Icon-button) * [Input](#Input) * [Labels and sections](#Labels-and-sections) * [Onboarding tip](#Onboarding-tip) * [Radio button](#Radio-button) * [Select menu](#Select-menu) * [Switch](#Switch) * [Textarea](#Textarea) * [Type](#Type) * [Tokens](#Tokens) --- ### Button ```javascript import { Button } from 'figma-plugin-ds-svelte'; ``` ```html ``` **Props** | Prop | Type | Options/notes | |:---------------|:--------|:----------------------------------------------------------------| | `on:click` | Func | Assign a function to execute on click. Ex: `on:click={funcName}`| | `variant` | String | Default: `"primary"`, Options: `"secondary"`, `"tertiary"` | | `disabled` | Boolean | Default: `false` | | `destructive` | Boolean | Default: `false` | --- ### Checkbox ```javascript import { Checkbox } from 'figma-plugin-ds-svelte'; ``` ```html Label Label Label ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:-----------------------------------------------------------------------------------------| | `on:change`| Func | Funtion to execute on change. Ex: `on:change={funcName}` | | `value` | Boolean | Default: `false`; | | `checked` | Boolean | Default: `false`; You can bind the value when checked to a var. `bind:checked={varName}` | | `disabled` | Boolean | Default: `false` | --- ### Disclosure ```javascript import { Disclosure, DisclosureItem } from 'figma-plugin-ds-svelte'; ``` ```html Content here Content here Content here ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:------------------------------------------------------------------| | `title` | String | Title of disclosure item | | `open` | Boolean | Default: `false`; Only one disclosure item can be opened at once | | `section` | Boolean | Default: `false`; Bold section header for disclosure title | --- ### Icon ```javascript //You need to import the icon component + whatever icons you want to use, //pass the names of your icon modules to the iconName prop in the Icon component import { Icon, IconName } from 'figma-plugin-ds-svelte'; //You can also import your own svg icon (32x32) and pass it to the icon component import SvgName from './src/directory/image.svg'; //Example import { Icon, IconVisible, IconSpinner } from 'figma-plugin-ds-svelte'; ``` ```html ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:---------------------------------------------------------------------------------------------| | `iconName` | Var | Pass an imported SVG to this prop. `iconName={IconImport}` | | `iconText` | String | Pass a text character to use instead of an icon. Ex: width and height inputs `iconText="W"` | | `color` | String | Pass the name of any Figma color var to this prop. `color="blue"` | | `spin` | Boolean | Default: `false`; This will rotate the icon in an endless loop. | **Icons** | Icon | Var | |----------------------------------------------------------------------------------------|-----------------------------------| | ![IconAdjust](src/icons/adjust.svg "icon") | `IconAdjust` | | ![IconAlert](src/icons/alert.svg "icon") | `IconAlert` | | ![IconAngle](src/icons/angle.svg "icon") | `IconAngle` | | ![IconArrowLeftRight](src/icons/arrow-left-right.svg "icon") | `IconArrowLeftRight` | | ![IconUpDown](src/icons/arrow-up-down.svg "icon") | `IconUpDown` | | ![IconAutoLayoutHorizontal](src/icons/auto-layout-horizontal.svg "icon") | `IconAutoLayoutHorizontal` | | ![IconAutoLayoutVertical](src/icons/auto-layout-vertical.svg "icon") | `IconAutoLayoutVertical` | | ![IconBack](src/icons/back.svg "icon") | `IconBack` | | ![IconBlendEmpty](src/icons/blend-empty.svg "icon") | `IconBlendEmpty` | | ![IconBlend](src/icons/blend.svg "icon") | `IconBlend` | | ![IconBreak](src/icons/break.svg "icon") | `IconBreak` | | ![IconCaretDown](src/icons/caret-down.svg "icon") | `IconCaretDown` | | ![IconCaretLeft](src/icons/caret-left.svg "icon") | `IconCaretLeft` | | ![IconCaretRight](src/icons/caret-right.svg "icon") | `IconCaretRight` | | ![IconCaretUp](src/icons/caret-up.svg "icon") | `IconCaretUp` | | ![IconCheck](src/icons/check.svg "icon") | `IconCheck` | | ![IconClose](src/icons/close.svg "icon") | `IconClose` | | ![IconComponent](src/icons/component.svg "icon") | `IconComponent` | | ![IconCornerRadius](src/icons/corner-radius.svg "icon") | `IconCornerRadius` | | ![IconCorners](src/icons/corners.svg "icon") | `IconCorners` | | ![IconDistributeHorizontalSpacing](src/icons/distribute-horizontal-spacing.svg "icon") | `IconDistributeHorizontalSpacing` | | ![IconDistributeVerticalSpacing](src/icons/distribute-vertical-spacing.svg "icon") | `IconDistributeVerticalSpacing` | | ![IconDraft](src/icons/draft.svg "icon") | `IconDraft` | | ![IconEffects](src/icons/effects.svg "icon") | `IconEffects` | | ![IconEllipses](src/icons/ellipses.svg "icon") | `IconEllipses` | | ![IconEyedropper](src/icons/eyedropper.svg "icon") | `IconEyedropper` | | ![IconForward](src/icons/forward.svg "icon") | `IconForward` | | ![IconFrame](src/icons/frame.svg "icon") | `IconFrame` | | ![IconGroup](src/icons/group.svg "icon") | `IconGroup` | | ![IconHidden](src/icons/hidden.svg "icon") | `IconHidden` | | ![IconHorizontalPadding](src/icons/horizontal-padding.svg "icon") | `IconHorizontalPadding` | | ![IconHyperlink](src/icons/hyperlink.svg "icon") | `IconHyperlink` | | ![IconImage](src/icons/image.svg "icon") | `IconImage` | | ![IconInstance](src/icons/instance.svg "icon") | `IconInstance` | | ![IconKey](src/icons/key.svg "icon") | `IconKey` | | ![IconLayoutAlignBottom](src/icons/layout-align-bottom.svg "icon") | `IconLayoutAlignBottom` | | ![IconAlignHorizontalCenters](src/icons/layout-align-horizontal-centers.svg "icon") | `IconAlignHorizontalCenters` | | ![IconAlignLeft](src/icons/layout-align-left.svg "icon") | `IconAlignLeft` | | ![IconAlignRight](src/icons/layout-align-right.svg "icon") | `IconAlignRight` | | ![IconAlignTop](src/icons/layout-align-top.svg "icon") | `IconAlignTop` | | ![IconAlignVerticalCenters](src/icons/layout-align-vertical-centers.svg "icon") | `IconAlignVerticalCenters` | | ![IconLayoutGridColumns](src/icons/layout-grid-columns.svg "icon") | `IconLayoutGridColumns` | | ![IconLayoutGridRows](src/icons/layout-grid-rows.svg "icon") | `IconLayoutGridRows` | | ![IconLayoutGridUniform](src/icons/layout-grid-uniform.svg "icon") | `IconLayoutGridUniform` | | ![IconLibrary](src/icons/library.svg "icon") | `IconLibrary` | | ![IconLinkBroken](src/icons/link-broken.svg "icon") | `IconLinkBroken` | | ![IconLinkConnected](src/icons/link-connected.svg "icon") | `IconLinkConnected` | | ![IconListDetailed](src/icons/list-detailed.svg "icon") | `IconListDetailed` | | ![IconListTile](src/icons/list-tile.svg "icon") | `IconListTile` | | ![IconList](src/icons/list.svg "icon") | `IconList` | | ![IconLockOff](src/icons/lock-off.svg "icon") | `IconLockOff` | | ![IconLockOn](src/icons/lock-on.svg "icon") | `IconLockOn` | | ![IconMinus](src/icons/minus.svg "icon") | `IconMinus` | | ![IconPlay](src/icons/play.svg "icon") | `IconPlay` | | ![IconPlus](src/icons/plus.svg "icon") | `IconPlus` | | ![IconRandom](src/icons/random.svg "icon") | `IconRandom` | | ![IconRecent](src/icons/recent.svg "icon") | `IconRecent` | | ![IconResizeToFit](src/icons/resize-to-fit.svg "icon") | `IconResizeToFit` | | ![IconResolveFilled](src/icons/resolve-filled.svg "icon") | `IconResolveFilled` | | ![IconResolve](src/icons/resolve.svg "icon") | `IconResolve` | | ![IconReverse](src/icons/reverse.svg "icon") | `IconReverse` | | ![IconSearchLarge](src/icons/search-large.svg "icon") | `IconSearchLarge` | | ![IconSearch](src/icons/search.svg "icon") | `IconSearch` | | ![IconSettings](src/icons/settings.svg "icon") | `IconSettings` | | ![IconShare](src/icons/share.svg "icon") | `IconShare` | | ![IconSmiley](src/icons/smiley.svg "icon") | `IconSmiley` | | ![IconSortAlphaAsc](src/icons/sort-alpha-asc.svg "icon") | `IconSortAlphaAsc` | | ![IconSortAlphaDsc](src/icons/sort-alpha-dsc.svg "icon") | `IconSortAlphaDsc` | | ![IconSortTopBottom](src/icons/sort-top-bottom.svg "icon") | `IconSortTopBottom` | | ![IconSpacing](src/icons/spacing.svg "icon") | `IconSpacing` | | ![IconSpinner](src/icons/spinner.svg "icon") | `IconSpinner` | | ![IconStarOff](src/icons/star-off.svg "icon") | `IconStarOff` | | ![IconStarOn](src/icons/star-on.svg "icon") | `IconStarOn` | | ![IconStrokeWeight](src/icons/stroke-weight.svg "icon") | `IconStrokeWeight` | | ![IconStyles](src/icons/styles.svg "icon") | `IconStyles` | | ![IconSwap](src/icons/swap.svg "icon") | `IconSwap` | | ![IconTheme](src/icons/theme.svg "icon") | `IconTheme` | | ![IconTidyUpGrid](src/icons/tidy-up-grid.svg "icon") | `IconTidyUpGrid` | | ![IconTidyUpListHorizontal](src/icons/tidy-up-list-horizontal.svg "icon") | `IconTidyUpListHorizontal` | | ![IconTidyUpListVertical](src/icons/tidy-up-list-vertical.svg "icon") | `IconTidyUpListVertical` | | ![IconTimer](src/icons/timer.svg "icon") | `IconTimer` | | ![IconTrash](src/icons/trash.svg "icon") | `IconTrash` | | ![IconVerticalPadding](src/icons/vertical-padding.svg "icon") | `IconVerticalPadding` | | ![IconVisible](src/icons/visible.svg "icon") | `IconVisible` | | ![IconWarningLarge](src/icons/warning-large.svg "icon") | `IconWarningLarge` | | ![IconWarning](src/icons/warning.svg "icon") | `IconWarning` | --- ### Icon button ```javascript //use this component as you would an Icon, it accepts the same props (except color) import { IconButton } from 'figma-plugin-ds-svelte'; ``` ```html ``` **Props** | Prop | Type | Options/notes | |------------|---------|------------------------------------------------------------------| | `on:click` | Func | Assign a function to execute on click. Ex: `on:click={funcName}` | | `selected` | Boolean | Default: `false` | | `iconName` | String | _See Icon component for usage._ | | `IconText` | String | _See Icon component for usage._ | | `spin` | Boolean | _See Icon component for usage._ | --- ### Input ```javascript import { Input } from 'figma-plugin-ds-svelte'; //var to define and store value var inputValue = 'Default value'; ``` ```html ``` **Props** | Prop | Type | Options/notes | |:--------------|:--------|:-------------------------------------------------------------------| | `on:change` | Func | Funtion to execute on change. Ex: `on:change={funcName}` | | `value` | String | Value that will get populated by user or specify predefined value. You can also bind this to a variable. | | `placeholder` | String | Placeholder text. | | `borders` | Boolean | Default: `false`; Force a border on the input field. | | `disabled` | Boolean | Default: `false` | | `iconName` | Var | _See Icon component for usage._ | | `iconText` | String | _See Icon component for usage._ | | `spin` | Boolean | _See Icon component for usage._ | --- ### Labels and sections ```javascript import { Label, SectionHeader } from 'figma-plugin-ds-svelte'; ``` ```html
Section name
``` --- ### Onboarding tip ```javascript import { OnboardingTip } from 'figma-plugin-ds-svelte'; ``` ```html Tip text goes here ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:--------------------------------| | `iconName` | Var | _See Icon component for usage._ | | `iconText` | String | _See Icon component for usage._ | | `spin` | Boolean | _See Icon component for usage._ | --- ### Radio button ```javascript import { Radio } from 'figma-plugin-ds-svelte'; //use bind:group, with a var to create a radio group and store the value of selected item //set value if this var to same value as radio item to set initial selection var radioValue; ``` ```html Label Label ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:----------------------------------------------------------| | `on:change`| Func | Funtion to execute on change. Ex: `on:change={funcName}` | | `group` | Var | Pass name of var to store selected item from radio group. | | `value` | String | Value of radio item. | | `disabled` | Boolean | Default: `false` | --- ### Select menu ```javascript import { SelectMenu } from 'figma-plugin-ds-svelte'; //You will need to pass and bind an array of menu items to this //Note: it is up to you to sort this array however you want let menuItemArray = [ { 'value': 'item1', 'label': 'Menu item 1', 'group': null, 'selected': false }, { 'value': 'item2', 'label': 'Menu item 2 ', 'group': null, 'selected': false } ]; //use bind:value, with a var bind the data of the selected item var selectedItem; ``` ```html ``` **Props** | Prop | Type | Options/notes | |-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------| | `on:change` | Func | Function to execute on change. Ex: `on:change={funcName}` | | `menuItems` | Var | Pass in array of menu item objects. See example above for format. If you want to use option groups, update the group keys to a string. | | `value` | Var | Bind the value of the selected item to a var. Ex: `bind:value={selectedItem}` | | `placeholder` | String | Override default placeholder text with a string when there is no item selected. | | `showGroupLabels` | Boolean | Default: `false`; If you are using option groups, this will show the group labels. | | `disabled` | Boolean | Default: `false` | | `macOSBlink` | Boolean | Default: `false`; Easter egg, old school Mac OS triple blink on select. | | `iconName` | Var | _See Icon component for usage._ | | `iconText` | String | _See Icon component for usage._ | --- ### Switch ```javascript import { Switch } from 'figma-plugin-ds-svelte'; //use bind:group, with a var to create a radio group and store the value of selected item //set value if this var to same value as radio item to set initial selection var switchValue; ``` ```html Label ``` **Props** | Prop | Type | Options/notes | |:-----------|:--------|:-----------------------------------------------------------------------------------------| | `on:change`| Func | Funtion to execute on change. Ex: `on:change={funcName}` | | `value` | Boolean | Default: `false`; | | `checked` | Boolean | Default: `false`; You can bind the value when checked to a var. `bind:checked={varName}` | | `disabled` | Boolean | Default: `false` | --- ### Textarea ```javascript import { Textarea } from 'figma-plugin-ds-svelte'; ``` ```html ``` **Props** | Prop | Type | Options/notes | |:--------------|:--------|:----------------------------------------------------------------------| | `on:change` | Func | Function to execute on change. Ex: `on:change={funcName}` | | `value` | String | Value of textarea. Can bind to a variable. Ex: `bind:value={someVar}` | | `placeholder` | String | Override default placeholder text with a string. | | `rows` | Int | Default: `2`; Number of rows (height) to display. | | `disabled` | Boolean | Default: `false` | --- ### Type ```javascript import { Type } from 'figma-plugin-ds-svelte'; ``` ```html Content here ``` **Props** | Prop | Type | Options/notes | |:----------|:--------|:---------------------------------------------------------------------------------------| | `size` | String | Default: `"small"`; Also accepts `"xsmall"`,`"large"`, `"xlarge"` | | `weight` | String | Default: `"normal"`; Also accepts `"medium"`,`"bold"` | | `color` | String | Default: `"black8"`; Pass the name of any Figma color var to this prop. `color="blue"`, Default color is white when inverse is `true` and no value specified | | `inverse` | Boolean | Default: `false`; Optimizes letter-spacing for light on dark applications. | --- ## Tokens **Color** | Name | Var | Type | Notes | |:--------------|:------------------|:-----------------|:--------------------------------------------------------------| | blue | `--blue` | Accent | Ex: primary button, hyperlinks, focus/selected states | | purple | `--purple` | Accent | Ex: components/instances | | hot-pink | `--hot-pink` | Accent | Ex: smart selection handles | | green | `--green` | Accent | Ex: Toolbar selections | | red | `--red` | Accent | Ex: Error | | yellow | `--yellow` | Accent | Ex: Caution/warning | | black | `--black` | Basic foreground | Ex: active states | | black8 | `--black8` | Basic foreground | 80% black, ex: most common black used in UI text and icons | | black8-opaque | `--black8-opaque` | Basic foreground | Opaque version of black8 | | black3 | `--black3` | Basic foreground | 30% black, ex: lower priority messages, disabled states | | black3-opaque | `--black3-opaque` | Basic foreground | Opaque version of black3 | | white | `--white` | Basic foreground | Used in same way as black8, but on dark backgrounds | | white8 | `--white8` | Basic foreground | Rarely used, only in toolbar | | white4 | `--white4` | Basic foreground | Used in same way as black3, Ex: option group headers in menus | | white | `--white` | Basic background | (Duplicate) White is also the most common background color | | grey | `--grey` | Basic background | Used behind controls in active state | | silver | `--silver` | Basic background | Ex: horizontal separators, default canvas background | | hud | `--hud` | Basic background | Ex: background for menus | | toolbar | `--toolbar` | Basic background | Ex: background for the toolbar | | black1 | `--black1` | Special | Ex: input placeholder underline, textarea border | | blue3 | `--blue3` | Special | Ex: text range selection in inputs | | purple4 | `--purple4` | Special | Ex: disabled components/instances | | hover-fill | `--hover-fill` | Special | Hover state for items without borders, ex: icon button | | selection-a | `--selection-a` | Special | Selected cells, ex: selected top level layer | | selection-b | `--selection-b` | Special | Selected cells, ex: selected child layers | | white2 | `--white2` | Special | Ex: menu separators | **Type** | Property | Var | Value | Notes | |:-----------------|:-----------------------------------|:--------------------|:-------------------------------------------------------------| | `font-family` | `--font-stack` | 'Inter', sans-serif | Default font everywhere | | `font-size` | `--font-size-xsmall` | 11px | Most common font size | | `font-size` | `--font-size-small` | 12px | Used in menus | | `font-size` | `--font-size-large` | 13px | Rarely used in editor | | `font-size` | `--font-size-xlarge` | 14px | Rarely used in editor | | `font-weight` | `--font-weight-normal` | 400 | | | `font-weight` | `--font-weight-medium` | 500 | | | `font-weight` | `--font-weight-bold` | 600 | | | `line-height` | `--font-line-height` | 16px | For use with xsmall and small font sizes | | `line-height` | `--font-line-height-large` | 24px | For use with large and xlarge font sizes | | `letter-spacing` | `--font-letter-spacing-pos-xsmall` | .005em | Optimized letter spacing for xsmall text on light background | | `letter-spacing` | `--font-letter-spacing-neg-xsmall` | .01em | Optimized letter spacing for xsmall text on dark background | | `letter-spacing` | `--font-letter-spacing-pos-small` | 0 | Optimized letter spacing for small text on light background | | `letter-spacing` | `--font-letter-spacing-neg-small` | .005em | Optimized letter spacing for small text on dark background | | `letter-spacing` | `--font-letter-spacing-pos-large` | -.0025em | Optimized letter spacing for large text on light background | | `letter-spacing` | `--font-letter-spacing-neg-large` | .0025em | Optimized letter spacing for large text on dark background | | `letter-spacing` | `--font-letter-spacing-pos-xlarge` | -.001em | Optimized letter spacing for xlarge text on light background | | `letter-spacing` | `--font-letter-spacing-neg-xlarge` | -.001em | Optimized letter spacing for xlarge text on dark background | **Border Radius** | Var | Value | Notes | |:------------------------|:------|:--------------------------------------| | `--border-radius-small` | 2px | Ex: menus, input borders, icon button | | `--border-radius-med` | 5px | Ex: visual bell, toasts | | `--border-radius-large` | 6px | Ex: buttons | **Shadows** | Var | Notes | |:----------------------------|:----------------------------| | `--shadow-hud` | Ex: menus, tooltips, toasts | | `--shadow-floating-window:` | Ex: modal, dialog | **Sizes** | Var | Value | |:------------------|:------| | `--size-xxxsmall` | 4px | | `--size-xxsmall` | 8px | | `--size-xsmall` | 16px | | `--size-small` | 24px | | `--size-medium` | 32px | | `--size-large` | 40px | | `--size-xlarge` | 48px | | `--size-xxlarge` | 64px | | `--size-huge` | 80px | ================================================ FILE: package.json ================================================ { "name": "figma-plugin-ds-svelte", "version": "1.3.8", "description": "A collection of Svelte components that match the Figma UI for building plugins.", "svelte": "./src/index.js", "dependencies": { "svelte-click-outside": "^1.0.0" }, "devDependencies": { "npm-run-all": "^4.1.5", "rollup": "^1.32.1", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-livereload": "^1.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-postcss": "^2.9.0", "rollup-plugin-serve": "^1.0.1", "rollup-plugin-svelte": "^5.1.1", "rollup-plugin-svg": "^2.0.0", "svelte": "^3.20.1" }, "scripts": { "build": "rollup -c", "autobuild": "rollup -c -w", "dev": "rollup -c -w", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/thomas-lowry/figma-plugin-ds-svelte.git" }, "keywords": [ "figma", "plugin", "ds", "design", "system", "ui", "svelte", "components" ], "files": [ "src" ], "author": "Thomas Lowry", "license": "MIT", "bugs": { "url": "https://github.com/thomas-lowry/figma-plugin-ds-svelte/issues" }, "homepage": "https://github.com/thomas-lowry/figma-plugin-ds-svelte#readme", "main": "./src/index.js" } ================================================ FILE: public/index.html ================================================ Figma Plugin DS Svelte components ================================================ FILE: rollup.config.js ================================================ import svelte from 'rollup-plugin-svelte'; import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; import serve from 'rollup-plugin-serve'; import livereload from 'rollup-plugin-livereload'; import svg from 'rollup-plugin-svg'; import postcss from 'rollup-plugin-postcss'; const production = !process.env.ROLLUP_WATCH export default { input: 'src/test.js', output: { file: `public/components.js`, format: 'iife', name: 'components', }, plugins: [ svelte({ include: ['src/**/*.svelte', 'node_modules/**/src/*.svelte'], dev: true, }), resolve(), commonjs(), svg(), postcss({ plugins: [] }), !production && serve('public'), !production && livereload('public'), ], watch: { clearScreen: false } } ================================================ FILE: src/App.svelte ================================================

Figma Plugin UI Svelte

Buttons

Primary

Secondary

Teritary

Checkboxes

Label Label Label Label

Switches

Label Label Label Label

Radio buttons

Label Label with really long text content Label with really really really really long text content Label with really long text content Label with really long text content Label Label

Disclosure panels

Content here Content here Content here

Icon

Icons and props

You can import and pass an SVG string to the iconName prop, or you can display text inside an icon by passing a string including a character to the iconText prop. You can pass the name of any color from the Figma DS to the color prop (ex: color="red", color="purple4"). Icons can also accept the spin prop. The IconButton, Input, and OnboardingTip all make use of the Icon component and can accept its props.

Icons

Icon Button

Input

Labels and sections

Section header goes here

Onboarding Tip

To create a style, select a layer and click on the style icon in the inspector panel

Select Menu

Textarea

================================================ FILE: src/components/Type/index.svelte ================================================
================================================ FILE: src/global.css ================================================ /* Vars */ :root { /* COLORS */ /* This has been updated to work with Figma's color tokens. The following variables are included for legacy support, where they may be referenced in your own custom components. All of these variables (where possible) will now map to Figma's color variables. Components part of this package will directly consume Figma's variables to support light and dark mode. */ /* Accent */ --blue: var(--figma-color-bg-brand); --purple: var(--figma-color-bg-component); --hot-pink: #ff00ff; --green: #1bc47d; --red: var(--figma-color-bg-danger); --yellow: var(--figma-color-bg-warning); /* Basic foreground */ --black: #000000; --black8: var(--figma-color-text); --black8-opaque: #333333; --black3: var(--figma-color-text-secondary); --black3-opaque: #7A7A7A; --white: var(--figma-color-bg); --white8: var(--figma-color-text-onbrand-secondary); --white4: var(--figma-color-text-onbrand-tertiary); /* Basic background */ --grey: #f0f0f0; --silver: var(--figma-color-border); --hud: #222222; --toolbar: var(--figma-color-bg-inverse); /* Special */ --black1: rgba(0, 0, 0, .1); --blue3: rgba(24, 145, 251, .3); --purple4: var(--figma-color-text-component-secondary); --hover-fill: var(--figma-color-bg-hover); --selection-a: var(--figma-color-bg-selected); --selection-b: var(--figma-color-bg-selected-secondary); --white2: var(--figma-color-text-onbrand-tertiary); /* SHIM */ --color-bg-menu: #1e1e1e; /* to update */ --color-text-menu-text: #FFFFFF; --color-text-menu-secondary: rgba(255, 255, 255, 0.7); --color-border-menu: #383838; --text-highlight: rgba(13, 153, 255, 0.4); /* TYPOGRAPHY */ /* Pos = positive applications (black on white) */ /* Neg = negative applications (white on black) */ /* Font stack */ --font-stack: 'Inter', sans-serif; /* Font sizes */ --font-size-xsmall: 11px; --font-size-small: 12px; --font-size-large: 13px; --font-size-xlarge: 14px; /* Font weights */ --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-bold: 600; /* Lineheight */ --font-line-height: 16px; /* Use For xsmall, small font sizes */ --font-line-height-large: 24px; /* Use For large, xlarge font sizes */ /* Letterspacing */ --font-letter-spacing-pos-xsmall: .005em; --font-letter-spacing-neg-xsmall: .01em; --font-letter-spacing-pos-small: 0; --font-letter-spacing-neg-small: .005em; --font-letter-spacing-pos-large: -.0025em; --font-letter-spacing-neg-large: .0025em; --font-letter-spacing-pos-xlarge: -.001em; --font-letter-spacing-neg-xlarge: -.001em; /* BORDER RADIUS */ --border-radius-small: 2px; --border-radius-med: 5px; --border-radius-large: 6px; /* SHADOWS */ --shadow-hud: 0 5px 17px rgba(0, 0, 0, .2), 0 2px 7px rgba(0, 0, 0, .15); --shadow-floating-window: 0 2px 14px rgba(0, 0, 0, .15); /* SPACING + SIZING */ --size-xxxsmall: 4px; --size-xxsmall: 8px; --size-xsmall: 16px; --size-small: 24px; --size-medium: 32px; --size-large: 40px; --size-xlarge: 48px; --size-xxlarge: 64px; --size-huge: 80px; } /* Global styles */ * { box-sizing: border-box; } body { position: relative; box-sizing: border-box; font-family: 'Inter', sans-serif; margin: 0; padding: 0; } /* FONTS */ @font-face { font-family: 'Inter'; font-weight: 400; font-style: normal; src: url('https://rsms.me/inter/font-files/Inter-Regular.woff2?v=3.7') format('woff2'), url('https://rsms.me/inter/font-files/Inter-Regular.woff?v=3.7') format('woff'); } @font-face { font-family: 'Inter'; font-weight: 500; font-style: normal; src: url('https://rsms.me/inter/font-files/Inter-Medium.woff2?v=3.7') format('woff2'), url('https://rsms.me/inter/font-files/Inter-Medium.woff2?v=3.7') format('woff'); } @font-face { font-family: 'Inter'; font-weight: 600; font-style: normal; src: url('https://rsms.me/inter/font-files/Inter-SemiBold.woff2?v=3.7') format('woff2'), url('https://rsms.me/inter/font-files/Inter-SemiBold.woff2?v=3.7') format('woff'); } /* Hyperlink styling */ a { color: var(--blue); text-decoration: none; cursor: pointer; } a:hover { color: var(--blue); } a:active { color: var(--blue); } a:focus { text-decoration: underline; } /* UTILITIES */ /* padding */ .p-xxxsmall { padding: var(--size-xxxsmall); } .p-xxsmall { padding: var(--size-xxsmall); } .p-xsmall { padding: var(--size-xsmall); } .p-small { padding: var(--size-small); } .p-medium { padding: var(--size-medium); } .p-large { padding: var(--size-large); } .p-xlarge { padding: var(--size-xlarge); } .p-xxlarge { padding: var(--size-xxlarge); } .p-huge { padding: var(--size-huge); } /* padding top */ .pt-xxxsmall { padding-top: var(--size-xxxsmall); } .pt-xxsmall { padding-top: var(--size-xxsmall); } .pt-xsmall { padding-top: var(--size-xsmall); } .pt-small { padding-top: var(--size-small); } .pt-medium { padding-top: var(--size-medium); } .pt-large { padding-top: var(--size-large); } .pt-xlarge { padding-top: var(--size-xlarge); } .pt-xxlarge { padding-top: var(--size-xxlarge); } .pt-huge { padding-top: var(--size-huge); } /* padding right */ .pr-xxxsmall { padding-right: var(--size-xxxsmall); } .pr-xxsmall { padding-right: var(--size-xxsmall); } .pr-xsmall { padding-right: var(--size-xsmall); } .pr-small { padding-right: var(--size-small); } .pr-medium { padding-right: var(--size-medium); } .pr-large { padding-right: var(--size-large); } .pr-xlarge { padding-right: var(--size-xlarge); } .pr-xxlarge { padding-right: var(--size-xxlarge); } .pr-huge { padding-right: var(--size-huge); } /* padding bottom */ .pb-xxxsmall { padding-bottom: var(--size-xxxsmall); } .pb-xxsmall { padding-bottom: var(--size-xxsmall); } .pb-xsmall { padding-bottom: var(--size-xsmall); } .pb-small { padding-bottom: var(--size-small); } .pb-medium { padding-bottom: var(--size-medium); } .pb-large { padding-bottom: var(--size-large); } .pb-xlarge { padding-bottom: var(--size-xlarge); } .pb-xxlarge { padding-bottom: var(--size-xxlarge); } .pb-huge { padding-bottom: var(--size-huge); } /* padding left */ .pl-xxxsmall { padding-left: var(--size-xxxsmall); } .pl-xxsmall { padding-left: var(--size-xxsmall); } .pl-xsmall { padding-left: var(--size-xsmall); } .pl-small { padding-left: var(--size-small); } .pl-medium { padding-left: var(--size-medium); } .pl-large { padding-left: var(--size-large); } .pl-xlarge { padding-left: var(--size-xlarge); } .pl-xxlarge { padding-left: var(--size-xxlarge); } .pl-huge { padding-left: var(--size-huge); } /* margin */ .m-xxxsmall { margin: var(--size-xxxsmall); } .m-xxsmall { margin: var(--size-xxsmall); } .m-xsmall { margin: var(--size-xsmall); } .m-small { margin: var(--size-small); } .m-medium { margin: var(--size-medium); } .m-large { margin: var(--size-large); } .m-xlarge { margin: var(--size-xlarge); } .m-xxlarge { margin: var(--size-xxlarge); } .m-huge { margin: var(--size-huge); } /* margin top */ .mt-xxxsmall { margin-top: var(--size-xxxsmall); } .mt-xxsmall { margin-top: var(--size-xxsmall); } .mt-xsmall { margin-top: var(--size-xsmall); } .mt-small { margin-top: var(--size-small); } .mt-medium { margin-top: var(--size-medium); } .mt-large { margin-top: var(--size-large); } .mt-xlarge { margin-top: var(--size-xlarge); } .mt-xxlarge { margin-top: var(--size-xxlarge); } .mt-huge { margin-top: var(--size-huge); } /* margin right */ .mr-xxxsmall { margin-right: var(--size-xxxsmall); } .mr-xxsmall { margin-right: var(--size-xxsmall); } .mr-xsmall { margin-right: var(--size-xsmall); } .mr-small { margin-right: var(--size-small); } .mr-medium { margin-right: var(--size-medium); } .mr-large { margin-right: var(--size-large); } .mr-xlarge { margin-right: var(--size-xlarge); } .mr-xxlarge { margin-right: var(--size-xxlarge); } .mr-huge { margin-right: var(--size-huge); } /* margin bottom */ .mb-xxxsmall { margin-bottom: var(--size-xxxsmall); } .mb-xxsmall { margin-bottom: var(--size-xxsmall); } .mb-xsmall { margin-bottom: var(--size-xsmall); } .mb-small { margin-bottom: var(--size-small); } .mb-medium { margin-bottom: var(--size-medium); } .mb-large { margin-bottom: var(--size-large); } .mb-xlarge { margin-bottom: var(--size-xlarge); } .mb-xxlarge { margin-bottom: var(--size-xxlarge); } .mb-huge { margin-bottom: var(--size-huge); } /* margin left */ .ml-xxxsmall { margin-left: var(--size-xxxsmall); } .ml-xxsmall { margin-left: var(--size-xxsmall); } .ml-xsmall { margin-left: var(--size-xsmall); } .ml-small { margin-left: var(--size-small); } .ml-medium { margin-left: var(--size-medium); } .ml-large { margin-left: var(--size-large); } .ml-xlarge { margin-left: var(--size-xlarge); } .ml-xxlarge { margin-left: var(--size-xxlarge); } .ml-huge { margin-left: var(--size-huge); } /* layout utilities */ .hidden { display: none; } .inline { display: inline; } .block { display: block; } .inline-block { display: inline-block; } .flex { display: flex; } .inline-flex {display: inline-flex; } .column { flex-direction: column;} .column-reverse { flex-direction: column-reverse; } .row { flex-direction: row; } .row-reverse { flex-direction: row-reverse; } .flex-wrap { flex-wrap: wrap; } .flex-wrap-reverse { flex-wrap: wrap-reverse; } .flex-no-wrap { flex-wrap: nowrap } .flex-shrink { flex-shrink: 1; } .flex-no-shrink { flex-shrink: 0; } .flex-grow { flex-grow: 1; } .flex-no-grow { flex-grow: 0; } .justify-content-start { justify-content: flex-start; } .justify-content-end { justify-content: flex-end; } .justify-content-center { justify-content: center; } .justify-content-between { justify-content: space-between; } .justify-content-around { justify-content: space-around; } .align-items-start { align-items: flex-start; } .align-items-end { align-items: flex-end; } .align-items-center { align-items: center; } .align-items-stretch { align-items: stretch; } .align-content-start { align-content: flex-start; } .align-content-end { align-content: flex-end; } .align-content-center { align-content: center; } .align-content-stretch { align-content: stretch; } .align-self-start { align-self: flex-start; } .align-self-end { align-self: flex-end; } .align-self-center { align-self: center; } .align-self-stretch { align-self: stretch; } ================================================ FILE: src/index.js ================================================ //Global CSS import GlobalCSS from './global.css'; //Components import Button from './components/Button/index.svelte'; import Checkbox from './components/Checkbox/index.svelte'; import Disclosure from './components/Disclosure/index.svelte'; import DisclosureItem from './components/DisclosureItem/index.svelte'; import Icon from './components/Icon/index.svelte'; import IconButton from './components/IconButton/index.svelte'; import Input from './components/Input/index.svelte'; import Label from './components/Label/index.svelte'; import OnboardingTip from './components/OnboardingTip/index.svelte'; import Radio from './components/Radio/index.svelte'; import Section from './components/Section/index.svelte'; import SelectDivider from './components/SelectDivider/index.svelte'; import SelectItem from './components/SelectItem/index.svelte'; import SelectMenu from './components/SelectMenu/index.svelte'; import Switch from './components/Switch/index.svelte'; import Textarea from './components/Textarea/index.svelte'; import Type from './components/Type/index.svelte'; //Icons import IconAdjust from './icons/adjust.svg'; import IconAlert from './icons/alert.svg'; import IconAngle from './icons/angle.svg'; import IconArrowLeftRight from './icons/arrow-left-right.svg'; import IconUpDown from './icons/arrow-up-down.svg'; import IconAutoLayoutHorizontal from './icons/auto-layout-horizontal.svg'; import IconAutoLayoutVertical from './icons/auto-layout-vertical.svg'; import IconBack from './icons/back.svg'; import IconBlendEmpty from './icons/blend-empty.svg'; import IconBlend from './icons/blend.svg'; import IconBreak from './icons/break.svg'; import IconCaretDown from './icons/caret-down.svg'; import IconCaretLeft from './icons/caret-left.svg'; import IconCaretRight from './icons/caret-right.svg'; import IconCaretUp from './icons/caret-up.svg'; import IconCheck from './icons/check.svg'; import IconClose from './icons/close.svg'; import IconComponent from './icons/component.svg'; import IconCornerRadius from './icons/corner-radius.svg'; import IconCorners from './icons/corners.svg'; import IconDistributeHorizontalSpacing from './icons/distribute-horizontal-spacing.svg'; import IconDistributeVerticalSpacing from './icons/distribute-vertical-spacing.svg'; import IconDraft from './icons/draft.svg'; import IconEffects from './icons/effects.svg'; import IconEllipses from './icons/ellipses.svg'; import IconEyedropper from './icons/eyedropper.svg'; import IconForward from './icons/forward.svg'; import IconFrame from './icons/frame.svg'; import IconGroup from './icons/group.svg'; import IconHidden from './icons/hidden.svg'; import IconHorizontalPadding from './icons/horizontal-padding.svg'; import IconHyperlink from './icons/hyperlink.svg'; import IconImage from './icons/image.svg'; import IconInstance from './icons/instance.svg'; import IconKey from './icons/key.svg'; import IconLayoutAlignBottom from './icons/layout-align-bottom.svg'; import IconAlignHorizontalCenters from './icons/layout-align-horizontal-centers.svg'; import IconAlignLeft from './icons/layout-align-left.svg'; import IconAlignRight from './icons/layout-align-right.svg'; import IconAlignTop from './icons/layout-align-top.svg'; import IconAlignVerticalCenters from './icons/layout-align-vertical-centers.svg'; import IconLayoutGridColumns from './icons/layout-grid-columns.svg'; import IconLayoutGridRows from './icons/layout-grid-rows.svg'; import IconLayoutGridUniform from './icons/layout-grid-uniform.svg'; import IconLibrary from './icons/library.svg'; import IconLinkBroken from './icons/link-broken.svg'; import IconLinkConnected from './icons/link-connected.svg'; import IconListDetailed from './icons/list-detailed.svg'; import IconListTile from './icons/list-tile.svg'; import IconList from './icons/list.svg'; import IconLockOff from './icons/lock-off.svg'; import IconLockOn from './icons/lock-on.svg'; import IconMinus from './icons/minus.svg'; import IconPlay from './icons/play.svg'; import IconPlus from './icons/plus.svg'; import IconRandom from './icons/random.svg'; import IconRecent from './icons/recent.svg'; import IconResizeToFit from './icons/resize-to-fit.svg'; import IconResolveFilled from './icons/resolve-filled.svg'; import IconResolve from './icons/resolve.svg'; import IconReverse from './icons/reverse.svg'; import IconSearchLarge from './icons/search-large.svg'; import IconSearch from './icons/search.svg'; import IconSettings from './icons/settings.svg'; import IconShare from './icons/share.svg'; import IconSmiley from './icons/smiley.svg'; import IconSortAlphaAsc from './icons/sort-alpha-asc.svg'; import IconSortAlphaDsc from './icons/sort-alpha-dsc.svg'; import IconSortTopBottom from './icons/sort-top-bottom.svg'; import IconSpacing from './icons/spacing.svg'; import IconSpinner from './icons/spinner.svg'; import IconStarOff from './icons/star-off.svg'; import IconStarOn from './icons/star-on.svg'; import IconStrokeWeight from './icons/stroke-weight.svg'; import IconStyles from './icons/styles.svg'; import IconSwap from './icons/swap.svg'; import IconTheme from './icons/theme.svg'; import IconTidyUpGrid from './icons/tidy-up-grid.svg'; import IconTidyUpListHorizontal from './icons/tidy-up-list-horizontal.svg'; import IconTidyUpListVertical from './icons/tidy-up-list-vertical.svg'; import IconTimer from './icons/timer.svg'; import IconTrash from './icons/trash.svg'; import IconVerticalPadding from './icons/vertical-padding.svg'; import IconVisible from './icons/visible.svg'; import IconWarningLarge from './icons/warning-large.svg'; import IconWarning from './icons/warning.svg'; export { GlobalCSS, Button, Checkbox, Disclosure, DisclosureItem, Icon, IconButton, Input, Label, OnboardingTip, Radio, Section, SelectDivider, SelectItem, SelectMenu, Switch, Textarea, Type, IconAdjust, IconAlert, IconAngle, IconArrowLeftRight, IconUpDown, IconAutoLayoutHorizontal, IconAutoLayoutVertical, IconBack, IconBlendEmpty, IconBlend, IconBreak, IconCaretDown, IconCaretLeft, IconCaretRight, IconCaretUp, IconCheck, IconClose, IconComponent, IconCornerRadius, IconCorners, IconDistributeHorizontalSpacing, IconDistributeVerticalSpacing, IconDraft, IconEffects, IconEllipses, IconEyedropper, IconForward, IconFrame, IconGroup, IconHidden, IconHorizontalPadding, IconHyperlink, IconImage, IconInstance, IconKey, IconLayoutAlignBottom, IconAlignHorizontalCenters, IconAlignLeft, IconAlignRight, IconAlignTop, IconAlignVerticalCenters, IconLayoutGridColumns, IconLayoutGridRows, IconLayoutGridUniform, IconLibrary, IconLinkBroken, IconLinkConnected, IconListDetailed, IconListTile, IconList, IconLockOff, IconLockOn, IconMinus, IconPlay, IconPlus, IconRandom, IconRecent, IconResizeToFit, IconResolveFilled, IconResolve, IconReverse, IconSearchLarge, IconSearch, IconSettings, IconShare, IconSmiley, IconSortAlphaAsc, IconSortAlphaDsc, IconSortTopBottom, IconSpacing, IconSpinner, IconStarOff, IconStarOn, IconStrokeWeight, IconStyles, IconSwap, IconTheme, IconTidyUpGrid, IconTidyUpListHorizontal, IconTidyUpListVertical, IconTimer, IconTrash, IconVerticalPadding, IconVisible, IconWarningLarge, IconWarning }; ================================================ FILE: src/test.js ================================================ // for testing import App from './App.svelte'; const app = new App({ target: document.body, }); export default app;