├── .eslintrc.js
├── .gitignore
├── .husky
└── pre-commit
├── .npmignore
├── .prettierrc
├── .storybook
├── main.js
└── preview.js
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── __mocks__
├── figmaPluginMock.ts
└── styleMock.ts
├── __tests__
├── Button.test.tsx
├── Checkbox.test.tsx
├── Disclosure.test.tsx
├── Icon.test.tsx
├── IconButton.test.tsx
├── Input.test.tsx
├── Label.test.tsx
├── OnboardingTip.test.tsx
├── Radio.test.tsx
├── SectionTitle.test.tsx
├── SelectMenu.test.tsx
├── Switch.test.tsx
├── Textarea.test.tsx
├── Type.test.tsx
└── __snapshots__
│ ├── Button.test.tsx.snap
│ ├── Checkbox.test.tsx.snap
│ ├── Disclosure.test.tsx.snap
│ ├── Icon.test.tsx.snap
│ ├── IconButton.test.tsx.snap
│ ├── Input.test.tsx.snap
│ ├── Label.test.tsx.snap
│ ├── OnboardingTip.test.tsx.snap
│ ├── Radio.test.tsx.snap
│ ├── SectionTitle.test.tsx.snap
│ ├── SelectMenu.test.tsx.snap
│ ├── Switch.test.tsx.snap
│ ├── Textarea.test.tsx.snap
│ └── Type.test.tsx.snap
├── global.d.ts
├── package.json
├── rollup.config.js
├── setupTests.ts
├── src
├── components
│ ├── Button.tsx
│ ├── Checkbox.tsx
│ ├── Disclosure.tsx
│ ├── Icon.tsx
│ ├── IconButton.tsx
│ ├── Input.tsx
│ ├── Label.tsx
│ ├── OnboardingTip.tsx
│ ├── Radio.tsx
│ ├── SectionTitle.tsx
│ ├── SelectMenu.tsx
│ ├── Switch.tsx
│ ├── Textarea.tsx
│ ├── Type.tsx
│ └── index.ts
├── constants
│ ├── colorNames.ts
│ ├── iconNames.ts
│ ├── index.ts
│ ├── sizes.ts
│ ├── tints.ts
│ └── weights.ts
├── index.ts
└── types.ts
├── stories
├── Button.stories.tsx
├── Checkbox.stories.tsx
├── Disclosure.stories.tsx
├── Icon.stories.tsx
├── IconButton.stories.tsx
├── Input.stories.tsx
├── Label.stories.tsx
├── OnboardingTip.stories.tsx
├── Radio.stories.tsx
├── SectionTitle.stories.tsx
├── SelectMenu.stories.tsx
├── Switch.stories.tsx
├── Textarea.stories.tsx
└── Type.stories.tsx
├── tsconfig.json
└── yarn.lock
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | extends: [
4 | 'eslint:recommended',
5 | 'plugin:prettier/recommended',
6 | 'plugin:react/recommended',
7 | ],
8 | plugins: ['prettier', 'react-hooks'],
9 | env: {
10 | browser: true,
11 | node: true,
12 | jest: true,
13 | },
14 | parserOptions: {
15 | ecmaVersion: 6,
16 | sourceType: 'module',
17 | ecmaFeatures: {
18 | jsx: true,
19 | },
20 | },
21 | rules: {
22 | 'react/prop-types': 'off',
23 | 'react-hooks/rules-of-hooks': 'error',
24 | 'react-hooks/exhaustive-deps': 'warn',
25 | 'react/display-name': 'off',
26 | 'no-unused-vars': 'off',
27 | },
28 | settings: {
29 | react: {
30 | version: 'detect',
31 | },
32 | },
33 | };
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | yarn-error.log
4 | .rpt2_cache
5 | storybook-static
6 | coverage
7 | lib
8 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn pre-commit
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | stories
3 | storybook-static
4 | .storybook
5 | __tests__
6 | __mocks__
7 | coverage
8 | .husky
9 | tsconfig.json
10 | .travis.yml
11 | .prettierrc
12 | .eslintrc.js
13 | global.d.ts
14 | setupTests.ts
15 | rollup.config.js
16 | yarn-error.log
17 | .rpt2_cache
18 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | stories: ['../stories/**/*.stories.tsx'],
3 | addons: [
4 | '@storybook/addon-docs',
5 | '@storybook/addon-controls',
6 | '@storybook/addon-storysource',
7 | '@storybook/addon-backgrounds',
8 | ],
9 | };
10 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { addDecorator } from '@storybook/react';
3 |
4 | export const parameters = {
5 | previewTabs: {
6 | 'storybook/docs/panel': {
7 | hidden: true,
8 | },
9 | },
10 | backgrounds: {
11 | disable: true,
12 | },
13 | docs: { page: null },
14 | };
15 |
16 | addDecorator((Story) => (
17 |
28 |
29 |
30 | ));
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js: node
4 |
5 | cache:
6 | directories:
7 | - node_modules
8 |
9 | script:
10 | - yarn install
11 | - yarn test
12 | - bash <(curl -s https://codecov.io/bash)
13 | - yarn build
14 | - yarn build-storybook
15 |
16 | jobs:
17 | include:
18 | - stage: release
19 | node_js: lts/*
20 | deploy:
21 | - provider: script
22 | script: yarn semantic-release
23 |
24 | - provider: pages
25 | github_token: $GH_TOKEN
26 | local_dir: storybook-static
27 | on:
28 | branch: main
29 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # React Figma UI Changelog
2 |
3 | ## 1.1.0 (2021-05-17)
4 |
5 | ### Breaking Changes
6 |
7 | - updated `figma-plugin-ds` to v1
8 |
9 | ### Bug Fix
10 |
11 | - fixed incorrect icon names
12 | - fixed incorrect types for `onChange` event
13 |
14 | ## 1.0.1 (2020-12-02)
15 |
16 | ### Bug Fix
17 |
18 | - added missing `patch-package` & `postinstall-postinstall` to dependencies
19 |
20 | ## 1.0.0 beta 12 / 1.0.0 (2020-08-26)
21 |
22 | ### Bug Fix
23 |
24 | - fixed incorrect tint type ([#13](https://github.com/JB1905/react-figma-ui/issues/13))
25 |
26 | ### Repository Changes
27 |
28 | - added badges in README.md
29 | - updated CI config
30 | - updated docs
31 | - added coverage logs
32 |
33 | ## 1.0.0 beta 4 / 1.0.0 beta 5 / 1.0.0 beta 6 (2020-06-22)
34 |
35 | ### Internal
36 |
37 | - added `sTrimmer` to remove whitespaces in class names
38 | - cleaned up
39 |
40 | ### Repository Changes
41 |
42 | - updated types for stories
43 |
44 | ## 1.0.0 beta 3 (2020-05-24)
45 |
46 | ### Breaking Changes
47 |
48 | - renamed `DisclosureItem` to `DisclosureTip`
49 |
50 | ### Repository Changes
51 |
52 | - updated stories
53 | - updated tests
54 |
55 | ### Docs
56 |
57 | - updated examples in README.md
58 |
59 | ## 1.0.0 beta 1 / 1.0.0 beta 2 (2020-05-23)
60 |
61 | ### New Feature
62 |
63 | #### Components
64 |
65 | - Button
66 | - Checkbox
67 | - Disclosure
68 | - Icon
69 | - IconButton
70 | - Input
71 | - Label
72 | - Onboarding
73 | - Radio
74 | - SectionTitle
75 | - SelectMenu
76 | - Switch
77 | - Textarea
78 | - Type
79 |
80 | #### Repository
81 |
82 | - added Storybook preview
83 | - added snapshot tests with Jest
84 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-present Jakub Biesiada
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [React Figma UI](https://github.com/JB1905/react-figma-ui)
2 |
3 | [](https://www.npmjs.com/package/react-figma-ui)
4 | [](https://www.npmjs.com/package/react-figma-ui)
5 | [](https://www.npmjs.com/package/react-figma-ui)
6 | [](https://codecov.io/gh/JB1905/react-figma-ui)
7 | [](https://app.travis-ci.com/github/JB1905/react-figma-ui)
8 | [](https://bundlephobia.com/result?p=react-figma-ui)
9 |
10 | ## About
11 |
12 | React implementation for [figma-plugin-ds](https://github.com/thomas-lowry/figma-plugin-ds/) by [Tom Lowry](https://github.com/thomas-lowry/)
13 |
14 | ### Demo
15 |
16 | [**Playground – play with the library in Storybook**](https://jb1905.github.io/react-figma-ui/)
17 |
18 | ### Alternatives
19 |
20 | - [react-figma-plugin-ds](https://github.com/alexandrtovmach/react-figma-plugin-ds/) by [Alexandr Tovmach](https://github.com/alexandrtovmach/)
21 | - [Figma Styled Components](https://github.com/jhardy/figma-styled-components/) by [Jared](https://github.com/jhardy/)
22 | - [figma-ui-components](https://github.com/lessmess-dev/figma-ui-components/) by [lessmess](https://github.com/lessmess-dev/)
23 | - [Figma React UI Kit](https://github.com/LiamMartens/figma-react-ui-kit/) by [Liam Martens](https://github.com/LiamMartens/)
24 |
25 | ## Contents
26 |
27 | - [How to Install](#how-to-install)
28 | - [Components](#components)
29 | - [Button](#button)
30 | - [Checkbox](#checkbox)
31 | - [Disclosure](#disclosure)
32 | - [Icon](#icon)
33 | - [Icon button](#icon-button)
34 | - [Input](#input)
35 | - [Labels and sections](#labels-and-sections)
36 | - [Onboarding tip](#onboarding-tip)
37 | - [Radio button](#radio-button)
38 | - [Select menu](#select-menu)
39 | - [Switch](#switch)
40 | - [Textarea](#textarea)
41 | - [Type](#type)
42 |
43 | ## How to Install
44 |
45 | First, install the library in your project by npm:
46 |
47 | ```sh
48 | $ npm install react-figma-ui
49 | ```
50 |
51 | Or Yarn:
52 |
53 | ```sh
54 | $ yarn add react-figma-ui
55 | ```
56 |
57 | ## Components
58 |
59 | ### Button
60 |
61 | To use the button, use the following component. Each button has a destructive option. Tertiary buttons are styled like hyperlinks.
62 |
63 | ```jsx
64 | import { Button } from 'react-figma-ui';
65 |
66 | // Primary
67 |
68 |
69 |
70 |
71 | // Secondary
72 |
73 |
74 |
75 |
76 | // Tertiary (Hyperlink style button)
77 |
78 |
79 |
80 | ```
81 |
82 | #### Available options
83 |
84 | [HTML button element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes) and dedicated params
85 |
86 | | Param | Description |
87 | | ------------- | -------------------------------------------------------------------------------------- |
88 | | `tint` | Display style for button: primary (filled), secondary (outlined), tertiary (hyperlink) |
89 | | `destructive` | Add red destructive variant for actions such as deleting something |
90 |
91 | ---
92 |
93 | ### Checkbox
94 |
95 | To use the checkbox, use the following component. Remember each checkbox should get a unique ID.
96 |
97 | ```jsx
98 | import { Checkbox } from 'react-figma-ui';
99 |
100 | // Checkbox unchecked
101 | Label
102 |
103 | // Checkbox checked
104 | Label
105 |
106 | // Checkbox disabled
107 | Label
108 | ```
109 |
110 | #### Available options
111 |
112 | [HTML input element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes) and dedicated params
113 |
114 | | Param | Description |
115 | | ----------------------------------------------------------------------------------------------------------------- | ---------------------------- |
116 | | [`containerProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for checkbox container |
117 | | [`labelProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attributes) | Props for label element |
118 |
119 | ---
120 |
121 | ### Disclosure
122 |
123 | To use a disclosure panel, you must use the following component.
124 |
125 | ```jsx
126 | import { Disclosure, DisclosureItem } from 'react-figma-ui';
127 |
128 | // Example items
129 | const items = [
130 | { heading: 'Heading 1', content: 'Content 1', id: 1 },
131 | { heading: 'Heading 2', content: 'Content 2', id: 2 },
132 | { heading: 'Heading 3', content: 'Content 3', id: 3 },
133 | ];
134 |
135 | (
138 |
145 | )}
146 | />
147 | ```
148 |
149 | #### Available options
150 |
151 | **Disclosure**
152 |
153 | [HTML ul element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
154 |
155 | | Param | Description |
156 | | -------- | ------------------------------- |
157 | | `items` | Array with disclosure items |
158 | | `render` | Render props for DisclosureItem |
159 |
160 | **DisclosureItem**
161 |
162 | [HTML li element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li#attributes) and dedicated params
163 |
164 | | Param | Description |
165 | | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
166 | | `heading` | Heading text value |
167 | | `content` | Content text value |
168 | | `section` | Style label like a heading |
169 | | `expanded` | Add this option to have item expanded on load |
170 | | [`labelProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for label element |
171 | | [`contentProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for content element |
172 |
173 | ---
174 |
175 | ### Icon
176 |
177 | To use the icon, use the following component. Apply the appropriate icon name to select the item you wish to use, you can also add option to change the color, or even spin the icon. You can also specify no icon name to use a text character as an icon (for example, like found in the width + height icon inputs in Figma)
178 |
179 | ```jsx
180 | import { Icon } from 'react-figma-ui';
181 |
182 | // Icon
183 |
184 |
185 | // Icon with blue colorName to change color
186 |
187 |
188 | // Spinner Icon with spinning animation
189 |
190 |
191 | // Text Icon
192 | W
193 | ```
194 |
195 | #### Available options
196 |
197 | [HTML div element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
198 |
199 | | Param | Description |
200 | | ------------- | ---------------------------------------------------------------------------------- |
201 | | `iconName` | Specify which icon to use (e.g.: `alert`, `draft`, `settings`) |
202 | | `spin` | Causes the icon to spin in an endless loop (e.g.: loader used with `spinner` icon) |
203 | | `colorName`\* | Pass the name of any Figma color var to this prop (e.g.: `blue`, `black3`) |
204 |
205 | \*Colors accepted: `blue`, `purple`, `purple4`, `hot-pink`, `green`, `red`, `yellow`, `black`, `black8`, `black3`, `white`, `white8`, `white4`
206 |
207 | [Preview available icons here](https://github.com/thomas-lowry/figma-plugin-ds/#icon)
208 |
209 | ---
210 |
211 | ### Icon button
212 |
213 | The icon button is essentially a wrapper for the icon component.
214 |
215 | ```jsx
216 | import { IconButton } from 'react-figma-ui';
217 |
218 | // Icon button with a blend icon
219 |
220 |
221 | // Icon button with selected option
222 |
223 | ```
224 |
225 | #### Available options
226 |
227 | [HTML div element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
228 |
229 | | Param | Description |
230 | | ----------------------------------- | ------------------------------------------------- |
231 | | `selected` | Add this option to have selected style for button |
232 | | [`iconProps`](#available-options-3) | Props for icon component |
233 |
234 | ---
235 |
236 | ### Input
237 |
238 | To use the input, use the following component.
239 |
240 | ```jsx
241 | import { Input } from 'react-figma-ui';
242 |
243 | // Input with placeholder
244 |
245 |
246 | // Input with initial value
247 |
248 |
249 | // Disabled input
250 |
251 |
252 | // Input with icon
253 |
254 | ```
255 |
256 | #### Available options
257 |
258 | [HTML input element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes) and dedicated params
259 |
260 | | Param | Description |
261 | | ----------------------------------------------------------------------------------------------------------------- | -------------------------- |
262 | | [`containerProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for switch container |
263 | | [`iconProps`](#available-options-3) | Props for icon component |
264 |
265 | ---
266 |
267 | ### Labels and sections
268 |
269 | To use a label or section, use following components.
270 |
271 | ```jsx
272 | import { Label, SectionTitle } from 'react-figma-ui';
273 |
274 | // Label
275 |
276 |
277 | // Section title
278 | Section title
279 | ```
280 |
281 | #### Available options
282 |
283 | [HTML div element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes)
284 |
285 | ---
286 |
287 | ### Onboarding tip
288 |
289 | To create an onboarding tip, use the following component.
290 |
291 | ```jsx
292 | import { OnboardingTip } from 'react-figma-ui';
293 |
294 |
295 | Onboarding tip goes here.
296 |
297 | ```
298 |
299 | #### Available options
300 |
301 | [HTML div element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
302 |
303 | | Param | Description |
304 | | ----------------------------------------------------------------------------------------------------------------- | -------------------------- |
305 | | [`containerProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for switch container |
306 | | [`iconProps`](#available-options-3) | Props for icon component |
307 |
308 | ---
309 |
310 | ### Radio button
311 |
312 | To create an radio button, use the following component. Remember each group of radio buttons must share the same name so that they are related to one another. Each button should have a unique id so that its label is associated with it and remains part of the clickable hit area.
313 |
314 | ```jsx
315 | import { Radio } from 'react-figma-ui';
316 |
317 | // Radio button
318 | Radio button
319 |
320 | // Radio button checked
321 | Radio button
322 |
323 | // Radio button disabled
324 | Radio button
325 | ```
326 |
327 | #### Available options
328 |
329 | [HTML input element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes) and dedicated params
330 |
331 | | Param | Description |
332 | | ----------------------------------------------------------------------------------------------------------------- | ------------------------- |
333 | | [`containerProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for radio container |
334 | | [`labelProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attributes) | Props for label element |
335 |
336 | ---
337 |
338 | ### Select menu
339 |
340 | To create an select menu, use following components.
341 |
342 | The select menu will open and position the menu to the selected object. If there is no vertical room inside your plugin's iFrame, the position of the menu will be moved to ensure it fits inside the iframe. If you have a select menu with too many options to fit within the iFrame, the menu will scroll vertically.
343 |
344 | ```jsx
345 | import { SelectMenu, SelectMenuOption } from 'react-figma-ui';
346 |
347 | // Example options
348 | const options = [
349 | { value: 1, label: 'Option 1' },
350 | { value: 2, label: 'Option 2' },
351 | { value: 3, label: 'Option 3' },
352 | ];
353 |
354 | () => (
355 | (
358 |
359 | {label}
360 |
361 | )}
362 | />
363 | );
364 | ```
365 |
366 | #### Available options
367 |
368 | **SelectMenu**
369 |
370 | [HTML select element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
371 |
372 | | Param | Description |
373 | | --------- | --------------------------------- |
374 | | `options` | Array with select menu options |
375 | | `render` | Render props for SelectMenuOption |
376 |
377 | **SelectMenuOption**
378 |
379 | [HTML option element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes)
380 |
381 | ---
382 |
383 | ### Switch
384 |
385 | To use the switch, use the following component. Remember each switch should get a unique ID that is referenced in the label. This ensures the switch and the entire label are clickable.
386 |
387 | ```jsx
388 | import { Switch } from 'react-figma-ui';
389 |
390 | // Switch
391 | Label
392 |
393 | // Switch checked
394 | Label
395 |
396 | // Switch disabled
397 | Label
398 | ```
399 |
400 | #### Available options
401 |
402 | [HTML input element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes) and dedicated params
403 |
404 | | Param | Description |
405 | | ----------------------------------------------------------------------------------------------------------------- | -------------------------- |
406 | | [`containerProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) | Props for switch container |
407 | | [`labelProps`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attributes) | Props for label element |
408 |
409 | ---
410 |
411 | ### Textarea
412 |
413 | To use the textarea, use the following component.
414 |
415 | ```jsx
416 | import { Textarea } from 'react-figma-ui';
417 |
418 | // Textarea
419 |
420 |
421 | // Textarea disabled
422 |
423 | ```
424 |
425 | #### Available options
426 |
427 | [HTML textarea element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attributes)
428 |
429 | ---
430 |
431 | ### Type
432 |
433 | To use the typography that is styled like it is in the Figma UI, use the following component plus additional options to modify the size, weight, and letterspacing that is optimized for positive (dark text on light background) and negative (light text on dark background) applications.
434 |
435 | ```jsx
436 | import { Type } from 'react-figma-ui';
437 |
438 | UI11, size: xsmall (default) weight: normal, positive
439 |
440 | UI13, size: large, weight: bold, positive
441 |
442 | UI12, size: large, weight: medium, negative
443 | ```
444 |
445 | #### Available options
446 |
447 | [HTML div element props](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#list_of_global_attributes) and dedicated params
448 |
449 | | Param | Description |
450 | | --------- | --------------------------------------------------------------------------------------------------- |
451 | | `size` | Font size: **small** - 12px, **large** - 13px, **xlarge** - 14px |
452 | | `weight` | Font weight: medium, bold |
453 | | `inverse` | Inverted (negative) application where light text is on dark background with increased letterspacing |
454 |
455 | _Defaults: Font size 11px, normal weight, positive application_
456 |
457 | ## License
458 |
459 | This project is licensed under the MIT License © 2020-present Jakub Biesiada
460 |
--------------------------------------------------------------------------------
/__mocks__/figmaPluginMock.ts:
--------------------------------------------------------------------------------
1 | class Dummy {
2 | init() {}
3 | destroy() {}
4 | }
5 |
6 | export const disclosure = new Dummy();
7 | export const selectMenu = new Dummy();
8 |
--------------------------------------------------------------------------------
/__mocks__/styleMock.ts:
--------------------------------------------------------------------------------
1 | export default {};
2 |
--------------------------------------------------------------------------------
/__tests__/Button.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Button } from '../src';
5 |
6 | describe('Button', () => {
7 | it('should render primary Button', () => {
8 | const { container } = render();
9 |
10 | expect(container).toMatchSnapshot();
11 | });
12 |
13 | it('should render secondary Button with destructive style', () => {
14 | const { container } = render(
15 |
18 | );
19 |
20 | expect(container).toMatchSnapshot();
21 | });
22 |
23 | it('should render disabled tertiary Button', () => {
24 | const { container } = render(
25 |
28 | );
29 |
30 | expect(container).toMatchSnapshot();
31 | });
32 |
33 | it('should render Button with custom className', () => {
34 | const { container } = render(
35 |
36 | );
37 |
38 | expect(container).toMatchSnapshot();
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/__tests__/Checkbox.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Checkbox } from '../src';
5 |
6 | describe('Checkbox', () => {
7 | it('should render unchecked Checkbox', () => {
8 | const { container } = render(
9 |
10 | Label
11 |
12 | );
13 |
14 | expect(container).toMatchSnapshot();
15 | });
16 |
17 | it('should render checked Checkbox', () => {
18 | const { container } = render(
19 |
20 | Label
21 |
22 | );
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render disabled Checkbox', () => {
28 | const { container } = render(
29 |
30 | Label
31 |
32 | );
33 |
34 | expect(container).toMatchSnapshot();
35 | });
36 |
37 | it('should render Checkbox with custom className values', () => {
38 | const { container } = render(
39 |
45 | Label
46 |
47 | );
48 |
49 | expect(container).toMatchSnapshot();
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/__tests__/Disclosure.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Disclosure, DisclosureItem } from '../src';
5 |
6 | describe('Disclosure', () => {
7 | const items = [
8 | { heading: 'Heading 1', content: 'Content 1', id: 1 },
9 | { heading: 'Heading 2', content: 'Content 2', id: 2 },
10 | { heading: 'Heading 3', content: 'Content 3', id: 3 },
11 | ];
12 |
13 | it('should render Disclosure', () => {
14 | const { container } = render(
15 | (
18 |
25 | )}
26 | />
27 | );
28 |
29 | expect(container).toMatchSnapshot();
30 | });
31 |
32 | it('should render Disclosure with custom className values', () => {
33 | const { container } = render(
34 | (
38 |
48 | )}
49 | />
50 | );
51 |
52 | expect(container).toMatchSnapshot();
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/__tests__/Icon.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Icon } from '../src';
5 |
6 | describe('Icon', () => {
7 | it('should render blend Icon', () => {
8 | const { container } = render();
9 |
10 | expect(container).toMatchSnapshot();
11 | });
12 |
13 | it('should render Icon with blue colorName to change color', () => {
14 | const { container } = render(
15 |
16 | );
17 |
18 | expect(container).toMatchSnapshot();
19 | });
20 |
21 | it('should render spinner Icon with spinning animation', () => {
22 | const { container } = render();
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render Text Icon', () => {
28 | const { container } = render(W);
29 |
30 | expect(container).toMatchSnapshot();
31 | });
32 |
33 | it('should render Icon with custom className', () => {
34 | const { container } = render(
35 |
36 | );
37 |
38 | expect(container).toMatchSnapshot();
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/__tests__/IconButton.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { IconButton } from '../src';
5 |
6 | describe('IconButton', () => {
7 | it('should render Icon Button with a blend icon', () => {
8 | const { container } = render(
9 |
10 | );
11 |
12 | expect(container).toMatchSnapshot();
13 | });
14 |
15 | it('should render Icon Button with selected option', () => {
16 | const { container } = render(
17 |
18 | );
19 |
20 | expect(container).toMatchSnapshot();
21 | });
22 |
23 | it('should render IconButton with custom className', () => {
24 | const { container } = render(
25 |
29 | );
30 |
31 | expect(container).toMatchSnapshot();
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/__tests__/Input.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Input } from '../src';
5 |
6 | describe('Input', () => {
7 | it('should render Input with placeholder', () => {
8 | const { container } = render();
9 |
10 | expect(container).toMatchSnapshot();
11 | });
12 |
13 | it('should render Input with initial value', () => {
14 | const { container } = render();
15 |
16 | expect(container).toMatchSnapshot();
17 | });
18 |
19 | it('should render Disabled input', () => {
20 | const { container } = render(
21 |
22 | );
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render Input with icon', () => {
28 | const { container } = render(
29 |
30 | );
31 |
32 | expect(container).toMatchSnapshot();
33 | });
34 |
35 | it('should render Input with custom className values', () => {
36 | const { container } = render(
37 |
44 | );
45 |
46 | expect(container).toMatchSnapshot();
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/__tests__/Label.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Label } from '../src';
5 |
6 | describe('Label', () => {
7 | it('should render Label', () => {
8 | const { getByText, container } = render();
9 |
10 | expect(getByText('Label')).toBeInTheDocument();
11 |
12 | expect(container).toMatchSnapshot();
13 | });
14 |
15 | it('should render Label with custom className', () => {
16 | const { getByText, container } = render(
17 |
18 | );
19 |
20 | expect(getByText('Hello World!')).toBeInTheDocument();
21 |
22 | expect(container).toMatchSnapshot();
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/__tests__/OnboardingTip.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { OnboardingTip } from '../src';
5 |
6 | describe('OnboardingTip', () => {
7 | it('should render OnboardingTip', () => {
8 | const { container } = render(
9 |
10 | Onboarding tip goes here.
11 |
12 | );
13 |
14 | expect(container).toMatchSnapshot();
15 | });
16 |
17 | it('should render OnboardingTip with custom className and icon style', () => {
18 | const { container } = render(
19 |
24 | Onboarding tip goes here.
25 |
26 | );
27 |
28 | expect(container).toMatchSnapshot();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/__tests__/Radio.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Radio } from '../src';
5 |
6 | describe('Radio', () => {
7 | it('should render Radio button', () => {
8 | const { container } = render(
9 |
10 | Radio button
11 |
12 | );
13 |
14 | expect(container).toMatchSnapshot();
15 | });
16 |
17 | it('should render checked Radio button', () => {
18 | const { container } = render(
19 |
20 | Radio button
21 |
22 | );
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render disabled Radio button', () => {
28 | const { container } = render(
29 |
36 | Radio button
37 |
38 | );
39 |
40 | expect(container).toMatchSnapshot();
41 | });
42 |
43 | it('should render Radio with custom className values', () => {
44 | const { container } = render(
45 |
54 | Radio button
55 |
56 | );
57 |
58 | expect(container).toMatchSnapshot();
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/__tests__/SectionTitle.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { SectionTitle } from '../src';
5 |
6 | describe('SectionTitle', () => {
7 | it('should render Section title', () => {
8 | const { container } = render(Section title);
9 |
10 | expect(container).toMatchSnapshot();
11 | });
12 |
13 | it('should render Section title with custom className', () => {
14 | const { container } = render(
15 | Section title
16 | );
17 |
18 | expect(container).toMatchSnapshot();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/__tests__/SelectMenu.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { SelectMenu, SelectMenuOption } from '../src';
5 |
6 | describe('SelectMenu', () => {
7 | const options = [
8 | { value: 1, label: 'Option 1' },
9 | { value: 2, label: 'Option 2' },
10 | { value: 3, label: 'Option 3' },
11 | ];
12 |
13 | it('should render SelectMenu', () => {
14 | const { container } = render(
15 | (
18 |
19 | {label}
20 |
21 | )}
22 | />
23 | );
24 |
25 | expect(container).toMatchSnapshot();
26 | });
27 |
28 | it('should render SelectMenu with custom className', () => {
29 | const { container } = render(
30 | (
34 |
35 | {label}
36 |
37 | )}
38 | />
39 | );
40 |
41 | expect(container).toMatchSnapshot();
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/__tests__/Switch.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Switch } from '../src';
5 |
6 | describe('Switch', () => {
7 | it('should render Switch', () => {
8 | const { container } = render(
9 |
10 | Label
11 |
12 | );
13 |
14 | expect(container).toMatchSnapshot();
15 | });
16 |
17 | it('should render checked Switch', () => {
18 | const { container } = render(
19 |
20 | Label
21 |
22 | );
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render disabled Switch', () => {
28 | const { container } = render(
29 |
30 | Label
31 |
32 | );
33 |
34 | expect(container).toMatchSnapshot();
35 | });
36 |
37 | it('should render Switch with custom className values', () => {
38 | const { container } = render(
39 |
46 | Label
47 |
48 | );
49 |
50 | expect(container).toMatchSnapshot();
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/__tests__/Textarea.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Textarea } from '../src';
5 |
6 | describe('Textarea', () => {
7 | it('should render Textarea', () => {
8 | const { container } = render(
9 |
10 | );
11 |
12 | expect(container).toMatchSnapshot();
13 | });
14 |
15 | it('should render disabled Textarea', () => {
16 | const { container } = render(
17 |
18 | );
19 |
20 | expect(container).toMatchSnapshot();
21 | });
22 |
23 | it('should render Textarea with custom className', () => {
24 | const { container } = render(
25 |
31 | );
32 |
33 | expect(container).toMatchSnapshot();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/__tests__/Type.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Type } from '../src';
5 |
6 | describe('Type', () => {
7 | it('should render Type with default values', () => {
8 | const { getByText, container } = render(Lorem ipsum dolor);
9 |
10 | expect(getByText('Lorem ipsum dolor')).toBeInTheDocument();
11 |
12 | expect(container).toMatchSnapshot();
13 | });
14 |
15 | it('should render Type with large size, bold weight and inverse option', () => {
16 | const { getByText, container } = render(
17 |
18 | Lorem ipsum dolor sit
19 |
20 | );
21 |
22 | expect(getByText('Lorem ipsum dolor sit')).toBeInTheDocument();
23 |
24 | expect(container).toMatchSnapshot();
25 | });
26 |
27 | it('should render Type with custom className', () => {
28 | const { getByText, container } = render(
29 | Lorem ipsum dolor sit amet
30 | );
31 |
32 | expect(getByText('Lorem ipsum dolor sit amet')).toBeInTheDocument();
33 |
34 | expect(container).toMatchSnapshot();
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Button.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Button should render Button with custom className 1`] = `
4 |
5 |
10 |
11 | `;
12 |
13 | exports[`Button should render disabled tertiary Button 1`] = `
14 |
15 |
21 |
22 | `;
23 |
24 | exports[`Button should render primary Button 1`] = `
25 |
26 |
31 |
32 | `;
33 |
34 | exports[`Button should render secondary Button with destructive style 1`] = `
35 |
36 |
41 |
42 | `;
43 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Checkbox.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Checkbox should render Checkbox with custom className values 1`] = `
4 |
5 |
8 |
13 |
19 |
20 |
21 | `;
22 |
23 | exports[`Checkbox should render checked Checkbox 1`] = `
24 |
25 |
28 |
35 |
41 |
42 |
43 | `;
44 |
45 | exports[`Checkbox should render disabled Checkbox 1`] = `
46 |
47 |
50 |
57 |
63 |
64 |
65 | `;
66 |
67 | exports[`Checkbox should render unchecked Checkbox 1`] = `
68 |
69 |
72 |
78 |
84 |
85 |
86 | `;
87 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Disclosure.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Disclosure should render Disclosure 1`] = `
4 |
5 |
8 | -
11 |
14 | Heading 1
15 |
16 |
19 | Content 1
20 |
21 |
22 | -
25 |
28 | Heading 2
29 |
30 |
33 | Content 2
34 |
35 |
36 | -
39 |
42 | Heading 3
43 |
44 |
47 | Content 3
48 |
49 |
50 |
51 |
52 | `;
53 |
54 | exports[`Disclosure should render Disclosure with custom className values 1`] = `
55 |
56 |
59 | -
62 |
65 | Heading 1
66 |
67 |
70 | Content 1
71 |
72 |
73 | -
76 |
79 | Heading 2
80 |
81 |
84 | Content 2
85 |
86 |
87 | -
90 |
93 | Heading 3
94 |
95 |
98 | Content 3
99 |
100 |
101 |
102 |
103 | `;
104 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Icon.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Icon should render Icon with blue colorName to change color 1`] = `
4 |
10 | `;
11 |
12 | exports[`Icon should render Icon with custom className 1`] = `
13 |
18 | `;
19 |
20 | exports[`Icon should render Text Icon 1`] = `
21 |
28 | `;
29 |
30 | exports[`Icon should render blend Icon 1`] = `
31 |
37 | `;
38 |
39 | exports[`Icon should render spinner Icon with spinning animation 1`] = `
40 |
46 | `;
47 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/IconButton.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`IconButton should render Icon Button with a blend icon 1`] = `
4 |
13 | `;
14 |
15 | exports[`IconButton should render Icon Button with selected option 1`] = `
16 |
25 | `;
26 |
27 | exports[`IconButton should render IconButton with custom className 1`] = `
28 |
37 | `;
38 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Input.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Input should render Disabled input 1`] = `
4 |
17 | `;
18 |
19 | exports[`Input should render Input with custom className values 1`] = `
20 |
32 | `;
33 |
34 | exports[`Input should render Input with icon 1`] = `
35 |
50 | `;
51 |
52 | exports[`Input should render Input with initial value 1`] = `
53 |
65 | `;
66 |
67 | exports[`Input should render Input with placeholder 1`] = `
68 |
80 | `;
81 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Label.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Label should render Label 1`] = `
4 |
11 | `;
12 |
13 | exports[`Label should render Label with custom className 1`] = `
14 |
15 |
18 | Hello World!
19 |
20 |
21 | `;
22 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/OnboardingTip.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`OnboardingTip should render OnboardingTip 1`] = `
4 |
5 |
8 |
11 |
14 | Onboarding tip goes here.
15 |
16 |
17 |
18 | `;
19 |
20 | exports[`OnboardingTip should render OnboardingTip with custom className and icon style 1`] = `
21 |
22 |
25 |
29 |
32 | Onboarding tip goes here.
33 |
34 |
35 |
36 | `;
37 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Radio.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Radio should render Radio button 1`] = `
4 |
5 |
8 |
16 |
22 |
23 |
24 | `;
25 |
26 | exports[`Radio should render Radio with custom className values 1`] = `
27 |
28 |
31 |
39 |
45 |
46 |
47 | `;
48 |
49 | exports[`Radio should render checked Radio button 1`] = `
50 |
51 |
54 |
63 |
69 |
70 |
71 | `;
72 |
73 | exports[`Radio should render disabled Radio button 1`] = `
74 |
75 |
78 |
87 |
93 |
94 |
95 | `;
96 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/SectionTitle.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`SectionTitle should render Section title 1`] = `
4 |
5 |
8 | Section title
9 |
10 |
11 | `;
12 |
13 | exports[`SectionTitle should render Section title with custom className 1`] = `
14 |
15 |
18 | Section title
19 |
20 |
21 | `;
22 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/SelectMenu.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`SelectMenu should render SelectMenu 1`] = `
4 |
5 |
24 |
25 | `;
26 |
27 | exports[`SelectMenu should render SelectMenu with custom className 1`] = `
28 |
29 |
48 |
49 | `;
50 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Switch.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Switch should render Switch 1`] = `
4 |
5 |
8 |
14 |
20 |
21 |
22 | `;
23 |
24 | exports[`Switch should render Switch with custom className values 1`] = `
25 |
26 |
29 |
35 |
41 |
42 |
43 | `;
44 |
45 | exports[`Switch should render checked Switch 1`] = `
46 |
47 |
50 |
57 |
63 |
64 |
65 | `;
66 |
67 | exports[`Switch should render disabled Switch 1`] = `
68 |
69 |
72 |
79 |
85 |
86 |
87 | `;
88 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Textarea.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Textarea should render Textarea 1`] = `
4 |
5 |
12 |
13 | `;
14 |
15 | exports[`Textarea should render Textarea with custom className 1`] = `
16 |
17 |
24 |
25 | `;
26 |
27 | exports[`Textarea should render disabled Textarea 1`] = `
28 |
29 |
37 |
38 | `;
39 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Type.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Type should render Type with custom className 1`] = `
4 |
5 |
8 | Lorem ipsum dolor sit amet
9 |
10 |
11 | `;
12 |
13 | exports[`Type should render Type with default values 1`] = `
14 |
15 |
18 | Lorem ipsum dolor
19 |
20 |
21 | `;
22 |
23 | exports[`Type should render Type with large size, bold weight and inverse option 1`] = `
24 |
25 |
28 | Lorem ipsum dolor sit
29 |
30 |
31 | `;
32 |
--------------------------------------------------------------------------------
/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'figma-plugin-ds';
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-figma-ui",
3 | "version": "2.0.0",
4 | "description": "React implementation for figma-plugin-ds",
5 | "author": "Jakub Biesiada",
6 | "license": "MIT",
7 | "main": "lib/react-figma-ui.cjs.js",
8 | "module": "lib/react-figma-ui.esm.js",
9 | "types": "lib/index.d.ts",
10 | "scripts": {
11 | "prepack": "yarn prettier && yarn lint && yarn build",
12 | "clean": "rimraf lib/*",
13 | "build": "rollup -c",
14 | "prebuild": "yarn clean",
15 | "test": "jest --coverage",
16 | "watch": "yarn build -- --watch",
17 | "watch:test": "yarn test -- --watch",
18 | "lint": "eslint 'src/**/*.{tsx,ts}' --fix",
19 | "prettier": "prettier --write 'src/**/*.{tsx,ts}'",
20 | "storybook": "start-storybook -p 6006",
21 | "build-storybook": "build-storybook",
22 | "deploy-storybook": "storybook-to-ghpages",
23 | "commit": "git-cz",
24 | "semantic-release": "semantic-release",
25 | "prepare": "husky install",
26 | "pre-commit": "lint-staged"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/JB1905/react-figma-ui.git"
31 | },
32 | "keywords": [
33 | "react",
34 | "components",
35 | "design",
36 | "library",
37 | "ui",
38 | "patterns",
39 | "system",
40 | "figma"
41 | ],
42 | "bugs": {
43 | "url": "https://github.com/JB1905/react-figma-ui/issues"
44 | },
45 | "homepage": "https://github.com/JB1905/react-figma-ui#readme",
46 | "dependencies": {
47 | "clsx": "^1.2.1",
48 | "figma-plugin-ds": "^1.0.1"
49 | },
50 | "devDependencies": {
51 | "@rollup/plugin-node-resolve": "^13.3.0",
52 | "@storybook/addon-backgrounds": "^6.5.16",
53 | "@storybook/addon-controls": "^6.5.16",
54 | "@storybook/addon-docs": "^6.5.16",
55 | "@storybook/addon-storysource": "^6.5.16",
56 | "@storybook/addons": "^6.5.16",
57 | "@storybook/react": "^6.5.16",
58 | "@storybook/storybook-deployer": "^2.8.16",
59 | "@testing-library/jest-dom": "^5.16.5",
60 | "@testing-library/react": "^12.1.5",
61 | "@types/react": "^17.0.38",
62 | "@typescript-eslint/parser": "^5.54.1",
63 | "babel-loader": "^8.2.5",
64 | "cz-conventional-changelog": "^3.3.0",
65 | "eslint": "8.35.0",
66 | "eslint-config-prettier": "^8.7.0",
67 | "eslint-plugin-prettier": "^4.2.1",
68 | "eslint-plugin-react": "^7.32.2",
69 | "eslint-plugin-react-hooks": "^4.6.0",
70 | "husky": "^8.0.3",
71 | "jest": "^28.1.1",
72 | "jest-environment-jsdom": "^28.1.1",
73 | "lint-staged": "^13.1.2",
74 | "prettier": "^2.8.4",
75 | "react": "^17.0.2",
76 | "react-dom": "^17.0.2",
77 | "rollup": "^2.75.6",
78 | "rollup-plugin-postcss": "^4.0.2",
79 | "rollup-plugin-terser": "^7.0.2",
80 | "rollup-plugin-typescript2": "^0.32.1",
81 | "semantic-release": "^19.0.3",
82 | "ts-jest": "^28.0.5",
83 | "typescript": "^4.9.5"
84 | },
85 | "peerDependencies": {
86 | "react": ">=16.8.0",
87 | "react-dom": ">=16.8.0"
88 | },
89 | "config": {
90 | "commitizen": {
91 | "path": "./node_modules/cz-conventional-changelog"
92 | }
93 | },
94 | "jest": {
95 | "testEnvironment": "jsdom",
96 | "testPathIgnorePatterns": [
97 | "/node_modules/"
98 | ],
99 | "setupFilesAfterEnv": [
100 | "/setupTests.ts"
101 | ],
102 | "moduleNameMapper": {
103 | "figma-plugin-ds": "/__mocks__/figmaPluginMock.ts",
104 | "\\.(css)$": "/__mocks__/styleMock.ts"
105 | },
106 | "transform": {
107 | "^.+\\.tsx?$": "ts-jest"
108 | }
109 | },
110 | "lint-staged": {
111 | "src/**/*.{tsx,ts}": [
112 | "yarn prettier",
113 | "yarn lint"
114 | ]
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve';
2 | import typescript from 'rollup-plugin-typescript2';
3 | import { terser } from 'rollup-plugin-terser';
4 | import postcss from 'rollup-plugin-postcss';
5 |
6 | import pkg from './package.json';
7 |
8 | export default {
9 | input: 'src/index.ts',
10 | output: [
11 | {
12 | file: pkg.main,
13 | format: 'cjs',
14 | sourcemap: true,
15 | },
16 | {
17 | file: pkg.module,
18 | format: 'es',
19 | sourcemap: true,
20 | },
21 | ],
22 | plugins: [
23 | resolve(),
24 | postcss({
25 | extract: false,
26 | modules: true,
27 | use: ['sass'],
28 | }),
29 | typescript(),
30 | terser(),
31 | ],
32 | external: [
33 | ...Object.keys(pkg.dependencies || {}),
34 | ...Object.keys(pkg.peerDependencies || {}),
35 | 'figma-plugin-ds/dist/figma-plugin-ds.css',
36 | ],
37 | };
38 |
--------------------------------------------------------------------------------
/setupTests.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/extend-expect';
2 |
--------------------------------------------------------------------------------
/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import React, { DetailedHTMLProps, ButtonHTMLAttributes } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import type { Tint } from '../types';
5 |
6 | interface Props
7 | extends Readonly<
8 | DetailedHTMLProps<
9 | ButtonHTMLAttributes,
10 | HTMLButtonElement
11 | >
12 | > {
13 | readonly tint?: Tint;
14 | readonly destructive?: boolean;
15 | }
16 |
17 | export const Button = ({
18 | children,
19 | tint,
20 | destructive,
21 | className = '',
22 | ...props
23 | }: Props) => (
24 |
34 | );
35 |
--------------------------------------------------------------------------------
/src/components/Checkbox.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props
5 | extends Omit>, 'onChange'> {
6 | readonly containerProps?: Readonly>;
7 | readonly labelProps?: Readonly>;
8 | readonly onChange?: (e: React.ChangeEvent) => void;
9 | }
10 |
11 | export const Checkbox = ({
12 | children,
13 | id,
14 | className = '',
15 | containerProps = {},
16 | labelProps = {},
17 | ...props
18 | }: Props) => {
19 | const { className: containerClassName = '', ...containerRest } =
20 | containerProps;
21 | const { className: labelClassName = '', ...labelRest } = labelProps;
22 |
23 | return (
24 |
25 |
31 |
32 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/components/Disclosure.tsx:
--------------------------------------------------------------------------------
1 | import React, {
2 | useEffect,
3 | HTMLProps,
4 | ReactElement,
5 | DetailedHTMLProps,
6 | LiHTMLAttributes,
7 | } from 'react';
8 | import { disclosure } from 'figma-plugin-ds';
9 | import clsx from 'clsx';
10 |
11 | interface DisclosureProps extends Readonly> {
12 | readonly items: T[];
13 | render(...itemData: [T, number, T[]]): ReactElement;
14 | }
15 |
16 | interface DisclosureItemProps
17 | extends Readonly<
18 | DetailedHTMLProps, HTMLLIElement>
19 | > {
20 | readonly heading: string;
21 | readonly content: string;
22 | readonly section?: boolean;
23 | readonly expanded?: boolean;
24 | readonly labelProps?: Readonly>;
25 | readonly contentProps?: Readonly>;
26 | }
27 |
28 | export function Disclosure({
29 | items,
30 | render,
31 | className = '',
32 | ...props
33 | }: DisclosureProps) {
34 | useEffect(() => {
35 | disclosure.init();
36 |
37 | return () => disclosure.destroy();
38 | }, []);
39 |
40 | return (
41 |
42 | {items.map(render)}
43 |
44 | );
45 | }
46 |
47 | export const DisclosureItem = ({
48 | section,
49 | expanded,
50 | heading,
51 | content,
52 | className = '',
53 | labelProps = {},
54 | contentProps = {},
55 | ...props
56 | }: DisclosureItemProps) => {
57 | const { className: labelClassName = '', ...labelRest } = labelProps;
58 | const { className: contentClassName = '', ...contentRest } = contentProps;
59 |
60 | return (
61 |
69 |
77 | {heading}
78 |
79 |
80 |
84 | {content}
85 |
86 |
87 | );
88 | };
89 |
--------------------------------------------------------------------------------
/src/components/Icon.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import type { IconName, ColorName } from '../types';
5 |
6 | export interface Props extends Readonly> {
7 | readonly iconName?: Readonly;
8 | readonly spin?: boolean;
9 | readonly colorName?: Readonly;
10 | }
11 |
12 | export const Icon = ({
13 | children,
14 | iconName,
15 | className = '',
16 | spin,
17 | colorName,
18 | ...props
19 | }: Props) => (
20 |
30 | {children}
31 |
32 | );
33 |
--------------------------------------------------------------------------------
/src/components/IconButton.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import { Icon, Props as IconProps } from './Icon';
5 |
6 | interface Props extends Readonly> {
7 | readonly selected?: boolean;
8 | readonly iconProps: IconProps;
9 | }
10 |
11 | export const IconButton = ({
12 | selected,
13 | className = '',
14 | iconProps,
15 | ...props
16 | }: Props) => (
17 |
25 |
26 |
27 | );
28 |
--------------------------------------------------------------------------------
/src/components/Input.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import { Icon, Props as IconProps } from './Icon';
5 |
6 | interface Props extends Readonly> {
7 | readonly containerProps?: Readonly>;
8 | readonly iconProps?: IconProps;
9 | }
10 |
11 | export const Input = ({
12 | className = '',
13 | type = 'input',
14 | containerProps = {},
15 | iconProps = {},
16 | ...props
17 | }: Props) => {
18 | const { className: containerClassName = '', ...containerRest } =
19 | containerProps;
20 | const { iconName } = iconProps;
21 |
22 | return (
23 |
31 | {iconName && }
32 |
33 |
38 |
39 | );
40 | };
41 |
--------------------------------------------------------------------------------
/src/components/Label.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props extends Readonly> {}
5 |
6 | export const Label = ({ children, className = '', ...props }: Props) => (
7 |
8 | {children}
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/src/components/OnboardingTip.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import { Icon, Props as IconProps } from './Icon';
5 |
6 | interface Props extends Readonly> {
7 | readonly containerProps?: Readonly>;
8 | readonly iconProps: IconProps;
9 | }
10 |
11 | export const OnboardingTip = ({
12 | children,
13 | className = '',
14 | containerProps = {},
15 | iconProps,
16 | ...props
17 | }: Props) => {
18 | const { className: containerClassName = '', ...containerRest } =
19 | containerProps;
20 |
21 | return (
22 |
26 |
27 |
28 |
29 | {children}
30 |
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/src/components/Radio.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props
5 | extends Omit>, 'onChange'> {
6 | readonly containerProps?: Readonly>;
7 | readonly labelProps?: Readonly>;
8 | readonly onChange?: (e: React.ChangeEvent) => void;
9 | }
10 |
11 | export const Radio = ({
12 | children,
13 | id,
14 | className = '',
15 | containerProps = {},
16 | labelProps = {},
17 | ...props
18 | }: Props) => {
19 | const { className: containerClassName = '', ...containerRest } =
20 | containerProps;
21 | const { className: labelClassName = '', ...labelRest } = labelProps;
22 |
23 | return (
24 |
25 |
31 |
32 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/components/SectionTitle.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props extends Readonly> {}
5 |
6 | export const SectionTitle = ({ children, className = '', ...props }: Props) => (
7 |
8 | {children}
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/src/components/SelectMenu.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, HTMLProps, ReactElement } from 'react';
2 | import { selectMenu } from 'figma-plugin-ds';
3 | import clsx from 'clsx';
4 |
5 | interface SelectMenuProps extends Readonly> {
6 | readonly options: T[];
7 | render(...optionData: [T, number, T[]]): ReactElement;
8 | }
9 |
10 | interface SelectMenuItemProps extends Readonly> {}
11 |
12 | export function SelectMenu({
13 | options,
14 | render,
15 | className = '',
16 | ...props
17 | }: SelectMenuProps) {
18 | useEffect(() => {
19 | selectMenu.init();
20 |
21 | return () => selectMenu.destroy();
22 | }, []);
23 |
24 | return (
25 |
28 | );
29 | }
30 |
31 | export const SelectMenuOption = ({
32 | children,
33 | ...props
34 | }: SelectMenuItemProps) => ;
35 |
--------------------------------------------------------------------------------
/src/components/Switch.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props
5 | extends Omit>, 'onChange'> {
6 | readonly containerProps?: Readonly>;
7 | readonly labelProps?: Readonly>;
8 | readonly onChange?: (e: React.ChangeEvent) => void;
9 | }
10 |
11 | export const Switch = ({
12 | children,
13 | id,
14 | className = '',
15 | containerProps = {},
16 | labelProps = {},
17 | ...props
18 | }: Props) => {
19 | const { className: containerClassName = '', ...containerRest } =
20 | containerProps;
21 | const { className: labelClassName = '', ...labelRest } = labelProps;
22 |
23 | return (
24 |
25 |
31 |
32 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/src/components/Textarea.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | interface Props extends Readonly> {}
5 |
6 | export const Textarea = ({ className = '', ...props }: Props) => (
7 |
8 | );
9 |
--------------------------------------------------------------------------------
/src/components/Type.tsx:
--------------------------------------------------------------------------------
1 | import React, { HTMLProps } from 'react';
2 | import clsx from 'clsx';
3 |
4 | import type { Size, Weight } from '../types';
5 |
6 | interface Props extends Omit>, 'size'> {
7 | readonly size?: Size;
8 | readonly weight?: Weight;
9 | readonly inverse?: boolean;
10 | }
11 |
12 | export const Type = ({
13 | children,
14 | size,
15 | weight,
16 | inverse,
17 | className = '',
18 | ...props
19 | }: Props) => (
20 |
30 | {children}
31 |
32 | );
33 |
--------------------------------------------------------------------------------
/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Button';
2 | export * from './Checkbox';
3 | export * from './Disclosure';
4 | export * from './Icon';
5 | export * from './IconButton';
6 | export * from './Input';
7 | export * from './Label';
8 | export * from './OnboardingTip';
9 | export * from './Radio';
10 | export * from './SectionTitle';
11 | export * from './SelectMenu';
12 | export * from './Switch';
13 | export * from './Textarea';
14 | export * from './Type';
15 |
--------------------------------------------------------------------------------
/src/constants/colorNames.ts:
--------------------------------------------------------------------------------
1 | export const colorNames = [
2 | 'blue',
3 | 'purple',
4 | 'purple4',
5 | 'hot-pink',
6 | 'green',
7 | 'red',
8 | 'yellow',
9 | 'black',
10 | 'black8',
11 | 'black3',
12 | 'white',
13 | 'white8',
14 | 'white4',
15 | ] as const;
16 |
--------------------------------------------------------------------------------
/src/constants/iconNames.ts:
--------------------------------------------------------------------------------
1 | export const iconNames = [
2 | 'adjust',
3 | 'alert',
4 | 'angle',
5 | 'arrow-left-right',
6 | 'up-down',
7 | 'auto-layout-horizontal',
8 | 'auto-layout-vertical',
9 | 'back',
10 | 'blend-empty',
11 | 'blend',
12 | 'break',
13 | 'caret-down',
14 | 'caret-left',
15 | 'caret-right',
16 | 'caret-up',
17 | 'check',
18 | 'close',
19 | 'component',
20 | 'corner-radius',
21 | 'corners',
22 | 'distribute-horizontal-spacing',
23 | 'distribute-vertical-spacing',
24 | 'draft',
25 | 'effects',
26 | 'ellipses',
27 | 'eyedropper',
28 | 'forward',
29 | 'frame',
30 | 'group',
31 | 'hidden',
32 | 'horizontal-padding',
33 | 'hyperlink',
34 | 'image',
35 | 'instance',
36 | 'key',
37 | 'layout-align-bottom',
38 | 'align-horizontal-centers',
39 | 'align-left',
40 | 'align-right',
41 | 'align-top',
42 | 'align-vertical-centers',
43 | 'layout-grid-columns',
44 | 'layout-grid-rows',
45 | 'layout-grid-uniform',
46 | 'library',
47 | 'link-broken',
48 | 'link-connected',
49 | 'list-detailed',
50 | 'list-tile',
51 | 'list',
52 | 'lock-off',
53 | 'lock-on',
54 | 'minus',
55 | 'play',
56 | 'plus',
57 | 'random',
58 | 'recent',
59 | 'resize-to-fit',
60 | 'resolve-filled',
61 | 'resolve',
62 | 'reverse',
63 | 'search-large',
64 | 'search',
65 | 'settings',
66 | 'share',
67 | 'smiley',
68 | 'sort-alpha-asc',
69 | 'sort-alpha-dsc',
70 | 'sort-top-bottom',
71 | 'spacing',
72 | 'spinner',
73 | 'star-off',
74 | 'star-on',
75 | 'stroke-weight',
76 | 'styles',
77 | 'swap',
78 | 'theme',
79 | 'tidy-up-grid',
80 | 'tidy-up-list-horizontal',
81 | 'tidy-up-list-vertical',
82 | 'timer',
83 | 'trash',
84 | 'vertical-padding',
85 | 'visible',
86 | 'warning-large',
87 | 'warning',
88 | ] as const;
89 |
--------------------------------------------------------------------------------
/src/constants/index.ts:
--------------------------------------------------------------------------------
1 | export * from './colorNames';
2 | export * from './iconNames';
3 | export * from './sizes';
4 | export * from './tints';
5 | export * from './weights';
6 |
--------------------------------------------------------------------------------
/src/constants/sizes.ts:
--------------------------------------------------------------------------------
1 | export const sizes = ['small', 'large', 'xlarge'] as const;
2 |
--------------------------------------------------------------------------------
/src/constants/tints.ts:
--------------------------------------------------------------------------------
1 | export const tints = ['primary', 'secondary', 'tertiary'] as const;
2 |
--------------------------------------------------------------------------------
/src/constants/weights.ts:
--------------------------------------------------------------------------------
1 | export const weights = ['medium', 'bold'] as const;
2 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import 'figma-plugin-ds/dist/figma-plugin-ds.css';
2 |
3 | export * from './components';
4 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { colorNames, iconNames, sizes, tints, weights } from './constants';
2 |
3 | export type ColorName = (typeof colorNames)[number];
4 | export type IconName = (typeof iconNames)[number];
5 | export type Size = (typeof sizes)[number];
6 | export type Tint = (typeof tints)[number];
7 | export type Weight = (typeof weights)[number];
8 |
--------------------------------------------------------------------------------
/stories/Button.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { Button } from '../src';
5 |
6 | import { tints } from '../src/constants';
7 |
8 | import type { Tint } from '../src/types';
9 |
10 | interface Props {
11 | readonly tint: Tint;
12 | readonly destructive: boolean;
13 | readonly disabled: boolean;
14 | readonly label: string;
15 | }
16 |
17 | export default {
18 | title: 'Button',
19 | component: Button,
20 | argTypes: {
21 | tint: {
22 | options: tints,
23 | control: {
24 | type: 'inline-radio',
25 | },
26 | },
27 | },
28 | args: {
29 | tint: 'primary',
30 | destructive: false,
31 | disabled: false,
32 | label: 'Label',
33 | } as Props,
34 | } as Meta;
35 |
36 | export const Normal: Story = ({ label, ...args }) => (
37 |
38 | );
39 |
--------------------------------------------------------------------------------
/stories/Checkbox.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 | import { useArgs } from '@storybook/addons';
4 |
5 | import { Checkbox } from '../src';
6 |
7 | interface Props {
8 | readonly checked: boolean;
9 | readonly disabled: boolean;
10 | readonly label: string;
11 | }
12 |
13 | export default {
14 | title: 'Checkbox',
15 | args: {
16 | checked: false,
17 | disabled: false,
18 | label: 'Label',
19 | } as Props,
20 | } as Meta;
21 |
22 | export const Normal: Story = ({ checked, label, ...args }) => {
23 | const [_args, updateArgs] = useArgs();
24 |
25 | return (
26 | updateArgs({ checked: e.target.checked })}
31 | >
32 | {label}
33 |
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/stories/Disclosure.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { Disclosure, DisclosureItem } from '../src';
5 |
6 | const items = [
7 | { heading: 'Heading 1', content: 'Content 1', id: 1 },
8 | { heading: 'Heading 2', content: 'Content 2', id: 2 },
9 | { heading: 'Heading 3', content: 'Content 3', id: 3 },
10 | ];
11 |
12 | interface Props {
13 | readonly items: typeof items;
14 | }
15 |
16 | export default {
17 | title: 'Disclosure',
18 | args: { items } as Props,
19 | parameters: {
20 | controls: {
21 | disabled: true,
22 | },
23 | },
24 | } as Meta;
25 |
26 | export const Normal: Story = ({ items }) => (
27 | (
30 |
37 | )}
38 | />
39 | );
40 |
--------------------------------------------------------------------------------
/stories/Icon.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { Icon } from '../src';
5 |
6 | import { iconNames, colorNames } from '../src/constants';
7 |
8 | import type { IconName, ColorName } from '../src/types';
9 |
10 | interface Props {
11 | readonly iconName: IconName;
12 | readonly colorName: ColorName;
13 | readonly spin: boolean;
14 | readonly value: string;
15 | }
16 |
17 | export default {
18 | title: 'Icon',
19 | component: Icon,
20 | argTypes: {
21 | iconName: {
22 | options: iconNames,
23 | control: {
24 | type: 'select',
25 | },
26 | },
27 | colorName: {
28 | options: colorNames,
29 | control: {
30 | type: 'select',
31 | },
32 | },
33 | },
34 | args: {
35 | iconName: 'blend',
36 | colorName: 'black',
37 | spin: false,
38 | value: '',
39 | } as Props,
40 | parameters: {
41 | backgrounds: {
42 | disable: false,
43 | },
44 | },
45 | } as Meta;
46 |
47 | export const Normal: Story = ({ value, ...args }) => (
48 | {value}
49 | );
50 |
--------------------------------------------------------------------------------
/stories/IconButton.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { IconButton } from '../src';
5 |
6 | import { iconNames } from '../src/constants';
7 |
8 | import type { IconName } from '../src/types';
9 |
10 | interface Props {
11 | readonly iconName: IconName;
12 | readonly selected: boolean;
13 | }
14 |
15 | export default {
16 | title: 'IconButton',
17 | argTypes: {
18 | iconName: {
19 | options: iconNames,
20 | control: {
21 | type: 'select',
22 | },
23 | },
24 | },
25 | args: {
26 | iconName: 'theme',
27 | selected: false,
28 | } as Props,
29 | } as Meta;
30 |
31 | export const Normal: Story = ({ iconName, ...args }) => (
32 |
33 | );
34 |
--------------------------------------------------------------------------------
/stories/Input.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 | import { useArgs } from '@storybook/addons';
4 |
5 | import { Input } from '../src';
6 |
7 | import { iconNames } from '../src/constants';
8 |
9 | import type { IconName } from '../src/types';
10 |
11 | interface Props {
12 | readonly value: string;
13 | readonly placeholder: string;
14 | readonly iconName: IconName;
15 | readonly disabled: boolean;
16 | }
17 |
18 | export default {
19 | title: 'Input',
20 | argTypes: {
21 | iconName: {
22 | options: iconNames,
23 | control: {
24 | type: 'select',
25 | },
26 | },
27 | },
28 | args: {
29 | value: 'Value',
30 | placeholder: 'Placeholder',
31 | iconName: 'search',
32 | disabled: false,
33 | } as Props,
34 | } as Meta;
35 |
36 | export const Normal: Story = ({ iconName, ...args }) => {
37 | const [_args, updateArgs] = useArgs();
38 |
39 | return (
40 |
44 | updateArgs({ value: (e.target as HTMLInputElement).value })
45 | }
46 | />
47 | );
48 | };
49 |
--------------------------------------------------------------------------------
/stories/Label.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { Label } from '../src';
5 |
6 | interface Props {
7 | readonly label: string;
8 | }
9 |
10 | export default {
11 | title: 'Label',
12 | component: Label,
13 | args: {
14 | label: 'Label',
15 | } as Props,
16 | } as Meta;
17 |
18 | export const Normal: Story = ({ label }) => ;
19 |
--------------------------------------------------------------------------------
/stories/OnboardingTip.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { OnboardingTip } from '../src';
5 |
6 | import { iconNames } from '../src/constants';
7 |
8 | import type { IconName } from '../src/types';
9 |
10 | interface Props {
11 | readonly iconName: IconName;
12 | readonly message: string;
13 | }
14 |
15 | export default {
16 | title: 'OnboardingTip',
17 | argTypes: {
18 | iconName: {
19 | options: iconNames,
20 | control: {
21 | type: 'select',
22 | },
23 | },
24 | },
25 | args: {
26 | iconName: 'warning',
27 | message: 'Onboarding tip goes here.',
28 | } as Props,
29 | } as Meta;
30 |
31 | export const Normal: Story = ({ iconName, message }) => (
32 | {message}
33 | );
34 |
--------------------------------------------------------------------------------
/stories/Radio.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 | import { useArgs } from '@storybook/addons';
4 |
5 | import { Radio } from '../src';
6 |
7 | interface Props {
8 | readonly checked: boolean;
9 | readonly disabled: boolean;
10 | readonly value: string;
11 | }
12 |
13 | export default {
14 | title: 'Radio',
15 | args: {
16 | checked: false,
17 | disabled: false,
18 | value: 'Radio Button',
19 | } as Props,
20 | } as Meta;
21 |
22 | export const Normal: Story = ({ checked, value, ...args }) => {
23 | const [_args, updateArgs] = useArgs();
24 |
25 | return (
26 | updateArgs({ checked: e.target.checked })}
31 | >
32 | {value}
33 |
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/stories/SectionTitle.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { SectionTitle } from '../src';
5 |
6 | interface Props {
7 | readonly sectionTitle: string;
8 | }
9 |
10 | export default {
11 | title: 'SectionTitle',
12 | component: SectionTitle,
13 | args: {
14 | sectionTitle: 'Section Title',
15 | } as Props,
16 | } as Meta;
17 |
18 | export const Normal: Story = ({ sectionTitle }) => (
19 | {sectionTitle}
20 | );
21 |
--------------------------------------------------------------------------------
/stories/SelectMenu.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 |
4 | import { SelectMenu, SelectMenuOption } from '../src';
5 |
6 | const options = [
7 | { value: 1, label: 'Option 1' },
8 | { value: 2, label: 'Option 2' },
9 | { value: 3, label: 'Option 3' },
10 | ];
11 |
12 | interface Props {
13 | readonly options: typeof options;
14 | }
15 |
16 | export default {
17 | title: 'SelectMenu',
18 | args: { options } as Props,
19 | decorators: [
20 | (Story) => (
21 |
22 |
23 |
24 | ),
25 | ],
26 | } as Meta;
27 |
28 | export const Normal: Story = ({ options }) => (
29 | (
32 |
33 | {label}
34 |
35 | )}
36 | />
37 | );
38 |
--------------------------------------------------------------------------------
/stories/Switch.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 | import { useArgs } from '@storybook/addons';
4 |
5 | import { Switch } from '../src';
6 |
7 | interface Props {
8 | readonly checked: boolean;
9 | readonly disabled: boolean;
10 | readonly value: string;
11 | }
12 |
13 | export default {
14 | title: 'Switch',
15 | args: {
16 | checked: false,
17 | disabled: false,
18 | value: 'Label',
19 | } as Props,
20 | } as Meta;
21 |
22 | export const Normal: Story = ({ checked, value, ...args }) => {
23 | const [_args, updateArgs] = useArgs();
24 |
25 | return (
26 | updateArgs({ checked: e.target.checked })}
31 | >
32 | {value}
33 |
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/stories/Textarea.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meta, Story } from '@storybook/react';
3 | import { useArgs } from '@storybook/addons';
4 |
5 | import { Textarea } from '../src';
6 |
7 | interface Props {
8 | readonly placeholder: string;
9 | readonly value: string;
10 | readonly rows: number;
11 | readonly disabled: boolean;
12 | }
13 |
14 | export default {
15 | title: 'Textarea',
16 | component: Textarea,
17 | args: {
18 | placeholder: 'Placeholder',
19 | value: 'Initial Value',
20 | rows: 2,
21 | disabled: false,
22 | } as Props,
23 | } as Meta;
24 |
25 | export const Normal: Story = ({ value, ...args }) => {
26 | const [_args, updateArgs] = useArgs();
27 |
28 | return (
29 |