paris 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # paris
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - eef2375: `TextArea` component
8
+ - 2f6cd01: `Input` component
9
+ - eef2375: `Select` component
10
+
11
+ ### Patch Changes
12
+
13
+ - b61e950: Use `clsx` for cleaner class names
14
+ - b61e950: Add `global.scss` file and update docs to reflect global styles import
15
+ - 16c9c3e: Update docs to specify transpile requirement
16
+ - 2f6cd01: Memoized enhancers
17
+ - 646fccf: Add `status` for `Input` for success/error styling
18
+ - b61e950: Have `Text` use the theme fontFamily instead of inheriting
19
+
3
20
  ## 0.2.2
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -10,17 +10,73 @@ Paris 1.x styling is heavily inspired by Uber's [Base Web](https://baseweb.desig
10
10
 
11
11
  ## Getting started
12
12
 
13
- First, install Paris and SASS in your project:
13
+ First, install Paris in your project:
14
14
 
15
15
  ```bash
16
- pnpm i paris sass
16
+ pnpm i paris
17
17
  # or
18
- yarn add paris sass
18
+ yarn add paris
19
19
  # or
20
- npm i paris sass
20
+ npm i paris
21
21
  ```
22
22
 
23
- Map our types in your `.tsconfig.json` file (this is a temporary workaround that we'll fix soon):
23
+ You'll need to tell your bundler to transpile files from Paris. This is easy in Next.js 13.1+ with the `transpilePackages` option in `next.config.js`:
24
+
25
+ ```js
26
+ // next.config.js
27
+ module.exports = {
28
+ // ...
29
+ transpilePackages: ['paris'],
30
+ };
31
+ ```
32
+
33
+ For older versions of Next.js, you can use a plugin like [next-transpile-modules](https://www.npmjs.com/package/next-transpile-modules). Instructions for other bundlers are coming soon.
34
+
35
+ You'll need to configure your bundler to support Sass/SCSS and SCSS modules. In Next.js, support for SCSS modules is built-in and can be enabled by simply installing `sass` as a dependency.
36
+
37
+ Paris uses `pte` (our theming engine) for powering theming and initial styles through CSS variables. You can use `generateCSS` or `generateThemeInjection` from `paris/theme` to generate the CSS variables and inject them into your app through either a `style` or `script` tag in your document head respectively. Either method supports SSR and server components, since the initial theme is static.
38
+
39
+ Additionally, you need to import the static global styles from `paris/theme/global.scss`.
40
+
41
+ For example, with the Next.js 13 app directory, you can do all of this in your root `layout.tsx` file:
42
+
43
+ ```tsx
44
+ // app/layout.tsx
45
+ import { generateCSS, generateThemeInjection, theme } from 'paris/theme';
46
+
47
+ // Import Paris's static global styling
48
+ import 'paris/theme/global.scss';
49
+
50
+ export default function RootLayout({
51
+ children,
52
+ }: {
53
+ children: React.ReactNode
54
+ }) {
55
+ return (
56
+ <html lang="en">
57
+ <head>
58
+ {/* Using a `style` tag (MUST have the id `pte-vars` and be in the document head) */}
59
+ <style
60
+ id="pte-vars"
61
+ dangerouslySetInnerHTML={{
62
+ __html: generateCSS(theme),
63
+ }}
64
+ />
65
+
66
+ {/* Or, use a `script` tag (can be located anywhere, should be loaded as early as possible to avoid an unstyled flash) */}
67
+ <script
68
+ dangerouslySetInnerHTML={{
69
+ __html: generateThemeInjection(theme),
70
+ }}
71
+ />
72
+ </head>
73
+ <body className={inter.className}>{children}</body>
74
+ </html>
75
+ );
76
+ }
77
+ ```
78
+
79
+ Finally, map our types in your `.tsconfig.json` file (this is a temporary workaround that we'll fix soon):
24
80
 
25
81
  ```json
26
82
  {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "paris",
3
3
  "author": "Sanil Chawla <sanil@slingshot.fm> (https://sanil.co)",
4
4
  "description": "Paris is Slingshot's React design system. It's a collection of reusable components, design tokens, and guidelines that help us build consistent, accessible, and performant user interfaces.",
5
- "version": "0.2.2",
5
+ "version": "0.3.0",
6
6
  "homepage": "https://paris.slingshot.fm",
7
7
  "license": "MIT",
8
8
  "repository": {
@@ -39,25 +39,31 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@changesets/cli": "^2.26.1",
42
+ "@fortawesome/fontawesome-svg-core": "^6.4.0",
43
+ "@fortawesome/free-regular-svg-icons": "^6.4.0",
44
+ "@fortawesome/free-solid-svg-icons": "^6.4.0",
45
+ "@fortawesome/react-fontawesome": "^0.2.0",
42
46
  "@ssh/csstypes": "^1.1.0",
43
47
  "@ssh/eslint-config": "^1.0.0",
44
- "@storybook/addon-essentials": "^7.0.12",
45
- "@storybook/addon-interactions": "^7.0.12",
46
- "@storybook/addon-links": "^7.0.12",
47
- "@storybook/blocks": "^7.0.12",
48
- "@storybook/manager-api": "^7.0.12",
49
- "@storybook/nextjs": "^7.0.12",
50
- "@storybook/react": "^7.0.12",
48
+ "@storybook/addon-essentials": "^7.0.18",
49
+ "@storybook/addon-interactions": "^7.0.18",
50
+ "@storybook/addon-links": "^7.0.18",
51
+ "@storybook/addon-mdx-gfm": "^7.0.18",
52
+ "@storybook/addon-styling": "^1.0.8",
53
+ "@storybook/blocks": "^7.0.18",
54
+ "@storybook/manager-api": "^7.0.18",
55
+ "@storybook/nextjs": "^7.0.18",
56
+ "@storybook/react": "^7.0.18",
51
57
  "@storybook/testing-library": "^0.1.0",
52
- "@storybook/theming": "^7.0.12",
58
+ "@storybook/theming": "^7.0.18",
53
59
  "@types/node": "18.15.11",
54
60
  "@types/react": "18.0.31",
55
61
  "@types/react-dom": "18.0.11",
56
62
  "@typescript-eslint/eslint-plugin": "^5.13.0",
57
63
  "@typescript-eslint/parser": "^5.0.0",
64
+ "autoprefixer": "^10.4.14",
58
65
  "change-case": "^4.1.2",
59
66
  "csstype": "^3.1.2",
60
- "esbuild-scss-modules-plugin": "^1.1.1",
61
67
  "eslint": "^8.2.0",
62
68
  "eslint-config-next": "13.4.2",
63
69
  "eslint-plugin-css": "^0.8.0",
@@ -66,20 +72,24 @@
66
72
  "jss": "^10.10.0",
67
73
  "jss-preset-default": "^10.10.0",
68
74
  "next": "^13.4.2",
75
+ "postcss": "^8.4.23",
69
76
  "react": "^18.2.0",
70
77
  "react-dom": "^18.2.0",
71
78
  "sass": "^1.62.1",
72
- "storybook": "^7.0.12",
79
+ "storybook": "^7.0.18",
73
80
  "storybook-dark-mode": "^3.0.0",
74
81
  "title-case": "^3.0.3",
75
82
  "ts-node": "^10.9.1",
76
83
  "tsconfig-paths-webpack-plugin": "^4.0.1",
77
- "tsup": "^6.7.0",
78
84
  "type-fest": "^3.10.0",
79
85
  "typescript": "^5.0.2"
80
86
  },
81
87
  "dependencies": {
82
- "pte": "^0.4.7"
88
+ "@ariakit/react": "^0.2.3",
89
+ "@headlessui/react": "^1.7.14",
90
+ "clsx": "^1.2.1",
91
+ "pte": "^0.4.7",
92
+ "ts-deepmerge": "^6.0.3"
83
93
  },
84
94
  "scripts": {
85
95
  "dev": "next dev",
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from 'react';
2
+ import { isValidElement, memo } from 'react';
3
+ import type { Enhancer } from '../types/Enhancer';
4
+
5
+ export const renderEnhancer = (enhancer: Enhancer, size: number): ReactNode => {
6
+ if (isValidElement(enhancer)) {
7
+ return enhancer;
8
+ }
9
+
10
+ if (typeof enhancer === 'function') {
11
+ return enhancer({ size });
12
+ }
13
+
14
+ return enhancer;
15
+ };
16
+
17
+ export const MemoizedEnhancer = memo<{ enhancer: Enhancer, size: number }>(({ enhancer, size }) => (
18
+ <>
19
+ { renderEnhancer(enhancer, size)}
20
+ </>
21
+ ), (prev, next) => prev.enhancer === next.enhancer && prev.size === next.size);
@@ -44,11 +44,3 @@ Tokens are the smallest pieces of design language that can be used to build comp
44
44
  ))}
45
45
  </div>
46
46
 
47
- <br />
48
-
49
- ## Typography
50
-
51
- <div>
52
- <pre style={{ color: pvar('colors.contentPrimary') }}>{JSON.stringify(LightTheme.typography, null, 4).replaceAll('"', '').replaceAll(',', '\n').replaceAll('{', '\n').replaceAll('}', '\n').replaceAll('\\', '')}</pre>
53
- </div>
54
-
@@ -1,4 +1,6 @@
1
- // Main styles
1
+ /*
2
+ * Main styles
3
+ */
2
4
  .button {
3
5
  user-select: none;
4
6
 
@@ -12,17 +14,21 @@
12
14
 
13
15
  transition: var(--pte-animations-interaction);
14
16
 
17
+ & > span {
18
+ margin-block-end: var(--pte-typography-verticalMetricsAdjust);
19
+ }
20
+
15
21
  &:hover {
16
22
  cursor: default;
17
23
  background-color: var(--pte-colors-backgroundInverseTertiary);
18
24
  }
19
25
 
20
- &:active {
26
+ &[aria-disabled=false]:active {
21
27
  opacity: 0.9;
22
28
  transform: scale(0.98);
23
29
  }
24
30
 
25
- &[disabled] {
31
+ &[aria-disabled=true] {
26
32
  pointer-events: none;
27
33
  }
28
34
  }
@@ -41,7 +47,7 @@
41
47
  border-color: var(--pte-colors-backgroundInverseTertiary);
42
48
  }
43
49
 
44
- &[disabled] {
50
+ &[aria-disabled=true] {
45
51
  color: var(--pte-colors-contentDisabled);
46
52
  background-color: var(--pte-colors-backgroundTertiary);
47
53
  border-color: var(--pte-colors-backgroundTertiary);
@@ -53,7 +59,7 @@
53
59
  background-color: transparent;
54
60
  border-color: var(--pte-colors-contentPrimary);
55
61
 
56
- &[disabled] {
62
+ &[aria-disabled=true] {
57
63
  color: var(--pte-colors-contentDisabled);
58
64
  border-color: var(--pte-colors-contentDisabled);
59
65
  }
@@ -70,7 +76,7 @@
70
76
  background-color: var(--pte-colors-backgroundTertiary);
71
77
  }
72
78
 
73
- &[disabled] {
79
+ &[aria-disabled=true] {
74
80
  color: var(--pte-colors-contentDisabled);
75
81
  }
76
82
  }
@@ -1,4 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
+ import { createElement } from 'react';
3
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4
+ import { faPlus } from '@fortawesome/free-solid-svg-icons';
2
5
  import { Button } from './Button';
3
6
 
4
7
  const meta: Meta<typeof Button> = {
@@ -40,3 +43,17 @@ export const Tertiary: Story = {
40
43
  kind: 'tertiary',
41
44
  },
42
45
  };
46
+
47
+ /**
48
+ * Enhancers can be used to add icons at the start (left) or end (right) of a button.
49
+ */
50
+ export const WithEnhancer: Story = {
51
+ args: {
52
+ children: 'Button',
53
+ kind: 'primary',
54
+ startEnhancer: ({ size }) => createElement(FontAwesomeIcon, {
55
+ icon: faPlus,
56
+ width: `${size}px`,
57
+ }),
58
+ },
59
+ };
@@ -1,10 +1,20 @@
1
1
  'use client';
2
2
 
3
3
  import type {
4
- ButtonHTMLAttributes, FC, MouseEventHandler, ReactNode,
4
+ FC, MouseEventHandler, ReactNode,
5
5
  } from 'react';
6
+ import type { ButtonProps as AriaButtonProps } from '@ariakit/react';
7
+ import { Button as AriaButton } from '@ariakit/react';
8
+ import clsx from 'clsx';
6
9
  import styles from './Button.module.scss';
7
10
  import { Text } from '../text';
11
+ import type { Enhancer } from '../../types/Enhancer';
12
+ import { MemoizedEnhancer, renderEnhancer } from '../../helpers/renderEnhancer';
13
+
14
+ const EnhancerSizes = {
15
+ large: 13,
16
+ small: 9,
17
+ };
8
18
 
9
19
  export type ButtonProps = {
10
20
  /**
@@ -27,11 +37,11 @@ export type ButtonProps = {
27
37
  *
28
38
  * When Button shape is `circle` or `square`, this element will be the only visible content.
29
39
  */
30
- startEnhancer?: (size: number) => ReactNode;
40
+ startEnhancer?: Enhancer;
31
41
  /**
32
42
  * An icon or other element to render after the Button's text. A `size` argument is passed that should be used to determine the width & height of the content displayed.
33
43
  */
34
- endEnhancer?: (size: number) => ReactNode;
44
+ endEnhancer?: Enhancer;
35
45
  /**
36
46
  * Disables the Button, disallowing user interaction.
37
47
  * @default false
@@ -47,11 +57,19 @@ export type ButtonProps = {
47
57
  * This should be text. When Button shape is `circle` or `square`, the action description should still be passed here for screen readers.
48
58
  */
49
59
  children: string;
50
- } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'disabled' | 'onClick'>;
60
+ } & Omit<AriaButtonProps, 'children' | 'disabled' | 'onClick'>;
51
61
 
52
62
  /**
53
63
  * A `Button` is used to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation.
54
64
  *
65
+ * <hr />
66
+ *
67
+ * To use the `Button` component, import it as follows:
68
+ *
69
+ * ```js
70
+ * import { Button } from 'paris/button';
71
+ * ```
72
+ *
55
73
  * @constructor
56
74
  */
57
75
  export const Button: FC<ButtonProps> = ({
@@ -63,19 +81,38 @@ export const Button: FC<ButtonProps> = ({
63
81
  endEnhancer,
64
82
  onClick,
65
83
  children,
84
+ disabled,
66
85
  ...props
67
86
  }) => (
68
- <button
69
- className={`${props.className} ${styles[kind || 'primary']} ${styles[shape || 'pill']} ${styles[size || 'large']} ${styles.button}`}
87
+ <AriaButton
88
+ {...props}
89
+ className={clsx(
90
+ styles.button,
91
+ styles[kind || 'primary'],
92
+ styles[shape || 'pill'],
93
+ styles[size || 'large'],
94
+ props?.className,
95
+ )}
96
+ aria-disabled={disabled ?? false}
70
97
  type={type || 'button'}
71
98
  aria-details={children}
72
- onClick={onClick}
73
- {...props}
99
+ onClick={!disabled ? onClick : () => {}}
100
+ disabled={false}
74
101
  >
75
- {!!startEnhancer && startEnhancer(size === 'large' ? 16 : 12)}
102
+ {!!startEnhancer && (
103
+ <MemoizedEnhancer
104
+ enhancer={startEnhancer}
105
+ size={EnhancerSizes[size || 'large']}
106
+ />
107
+ )}
76
108
  <Text kind="labelXSmall">
77
109
  {children || 'Button'}
78
110
  </Text>
79
- {!!endEnhancer && endEnhancer(size === 'large' ? 16 : 12)}
80
- </button>
111
+ {!!endEnhancer && (
112
+ <MemoizedEnhancer
113
+ enhancer={endEnhancer}
114
+ size={EnhancerSizes[size || 'large']}
115
+ />
116
+ )}
117
+ </AriaButton>
81
118
  );
@@ -0,0 +1,23 @@
1
+ .transition {
2
+ transition: var(--pte-animations-interaction);
3
+ }
4
+
5
+ .enterFrom {
6
+ opacity: 0;
7
+ transform: translateY(-8px);
8
+ }
9
+
10
+ .enterTo {
11
+ opacity: 1;
12
+ transform: translateY(0);
13
+ }
14
+
15
+ .leaveFrom {
16
+ opacity: 1;
17
+ transform: translateY(0);
18
+ }
19
+
20
+ .leaveTo {
21
+ opacity: 0;
22
+ transform: translateY(-8px);
23
+ }
@@ -0,0 +1,134 @@
1
+ .inputContainer {
2
+ display: flex;
3
+ flex-direction: row;
4
+ gap: 12px;
5
+ min-height: 36px;
6
+
7
+ background-color: var(--pte-colors-backgroundSecondary);
8
+
9
+ //height: 36px;
10
+ width: 100%;
11
+ padding: calc(7.5px - var(--pte-typography-verticalMetricsAdjust)) 15px 7.5px;
12
+
13
+ font-size: var(--pte-typography-styles-paragraphSmall-fontSize);
14
+ font-style: var(--pte-typography-styles-paragraphSmall-fontStyle);
15
+ font-weight: var(--pte-typography-styles-paragraphSmall-fontWeight);
16
+ letter-spacing: var(--pte-typography-styles-paragraphSmall-letterSpacing);
17
+ line-height: var(--pte-typography-styles-paragraphSmall-lineHeight);
18
+ text-transform: var(--pte-typography-styles-paragraphSmall-textTransform);
19
+
20
+ border-width: 1px;
21
+ border-style: solid;
22
+ border-color: var(--pte-colors-backgroundSecondary);
23
+ border-radius: var(--pte-borders-radius-rectangle);
24
+
25
+ transition: var(--pte-animations-interaction);
26
+
27
+ &:focus-within {
28
+ outline: none;
29
+ border-color: var(--pte-colors-borderSelected);
30
+ background-color: var(--pte-colors-backgroundTertiary);
31
+ }
32
+
33
+ &[data-status="disabled"] {
34
+ border-color: var(--pte-colors-backgroundTertiary);
35
+ background-color: var(--pte-colors-backgroundTertiary);
36
+ color: var(--pte-colors-contentDisabled);
37
+ pointer-events: none;
38
+ cursor: default;
39
+
40
+ &:focus-within {
41
+ border-color: var(--pte-colors-backgroundTertiary) !important;
42
+ }
43
+ }
44
+
45
+ &[data-status="error"] {
46
+ border-color: var(--pte-colors-borderNegative);
47
+ background-color: var(--pte-colors-backgroundNegative);
48
+ color: var(--pte-colors-contentNegative);
49
+
50
+ &:focus-within {
51
+ color: var(--pte-colors-contentPrimary);
52
+ }
53
+ }
54
+
55
+ &[data-status="success"] {
56
+ border-color: var(--pte-colors-borderPositive);
57
+ background-color: var(--pte-colors-backgroundPositive);
58
+ color: var(--pte-colors-contentPositive);
59
+
60
+ &:focus-within {
61
+ color: var(--pte-colors-contentPrimary);
62
+ }
63
+ }
64
+
65
+ & > input, & > textarea {
66
+ width: 100%;
67
+ background-color: transparent;
68
+ padding: 0;
69
+ margin: 0;
70
+ border: none;
71
+ outline: none;
72
+
73
+ &::placeholder {
74
+ color: var(--pte-colors-contentTertiary);
75
+ }
76
+
77
+ &[aria-disabled=true] {
78
+ color: var(--pte-colors-contentDisabled);
79
+ cursor: default;
80
+
81
+ &::placeholder {
82
+ color: var(--pte-colors-contentDisabled);
83
+ }
84
+ }
85
+
86
+ &[type="color"]::-webkit-color-swatch {
87
+ border: 1px solid var(--pte-colors-borderSelected);
88
+ border-radius: var(--pte-borders-radius-circle);
89
+ }
90
+
91
+ &[type="color"]::-webkit-color-swatch-wrapper {
92
+ width: 16px;
93
+ height: 100%;
94
+ }
95
+
96
+ &[type="file"]::-webkit-file-upload-button {
97
+ display: none;
98
+ }
99
+ }
100
+ }
101
+
102
+ .enhancer {
103
+ color: var(--pte-colors-contentSecondary);
104
+ margin-block-start: -0.5px;
105
+ font-size: var(--pte-typography-styles-paragraphSmall-fontSize);
106
+ font-style: var(--pte-typography-styles-paragraphSmall-fontStyle);
107
+ font-weight: var(--pte-typography-styles-paragraphSmall-fontWeight);
108
+ letter-spacing: var(--pte-typography-styles-paragraphSmall-letterSpacing);
109
+ line-height: var(--pte-typography-styles-paragraphSmall-lineHeight);
110
+ text-transform: var(--pte-typography-styles-paragraphSmall-textTransform);
111
+ }
112
+
113
+ .container {
114
+ user-select: none;
115
+ cursor: default;
116
+ display: flex;
117
+ flex-direction: column;
118
+ gap: 8px;
119
+ }
120
+
121
+ // Use double selector to ensure specificity is higher than the default styles
122
+ .label.label {
123
+ color: var(--pte-colors-contentPrimary);
124
+ font-weight: var(--pte-typography-boldFontWeight);
125
+ }
126
+
127
+ // Use double selector to ensure specificity is higher than the default styles
128
+ .description.description {
129
+ color: var(--pte-colors-contentTertiary);
130
+ }
131
+
132
+ .hidden {
133
+ display: none;
134
+ }
@@ -0,0 +1,87 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { createElement } from 'react';
3
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4
+ import { faSearch } from '@fortawesome/free-solid-svg-icons';
5
+ import { Input } from './Input';
6
+
7
+ const meta: Meta<typeof Input> = {
8
+ title: 'Inputs/Input',
9
+ component: Input,
10
+ tags: ['autodocs'],
11
+ };
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof Input>;
15
+
16
+ export const Default: Story = {
17
+ args: {
18
+ placeholder: 'Billie Eilish',
19
+ label: 'Name',
20
+ description: 'Type your full name here.',
21
+ },
22
+ };
23
+
24
+ export const Password: Story = {
25
+ args: {
26
+ type: 'password',
27
+ placeholder: 'Password',
28
+ label: 'Password',
29
+ hideLabel: true,
30
+ },
31
+ };
32
+
33
+ export const Success: Story = {
34
+ args: {
35
+ placeholder: 'billie@eilish.com',
36
+ value: 'valid@email.com',
37
+ type: 'email',
38
+ label: 'Email',
39
+ description: 'Enter your email address.',
40
+ status: 'success',
41
+ },
42
+ };
43
+
44
+ export const Error: Story = {
45
+ args: {
46
+ placeholder: 'billie@eilish.com',
47
+ value: 'notavalid@email',
48
+ type: 'email',
49
+ label: 'Email',
50
+ description: 'Enter your email address.',
51
+ status: 'error',
52
+ },
53
+ };
54
+
55
+ export const Disabled: Story = {
56
+ args: {
57
+ placeholder: 'billie@eilish.com',
58
+ type: 'email',
59
+ label: 'Email',
60
+ description: 'Enter your email address.',
61
+ disabled: true,
62
+ },
63
+ };
64
+
65
+ export const WithEnhancer: Story = {
66
+ args: {
67
+ placeholder: 'Billie Eilish',
68
+ label: 'Name',
69
+ description: 'Type your full name here.',
70
+ startEnhancer: ({ size }) => createElement(FontAwesomeIcon, {
71
+ icon: faSearch,
72
+ width: `${size}px`,
73
+ }),
74
+ },
75
+ };
76
+
77
+ export const WithEndEnhancer: Story = {
78
+ args: {
79
+ placeholder: 'Billie Eilish',
80
+ label: 'Name',
81
+ description: 'Type your full name here.',
82
+ endEnhancer: ({ size }) => createElement(FontAwesomeIcon, {
83
+ icon: faSearch,
84
+ width: `${size}px`,
85
+ }),
86
+ },
87
+ };