@theroutingcompany/components 0.0.12 → 0.0.13

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/README.md CHANGED
@@ -20,7 +20,7 @@ Styling is done with [styled-components](https://styled-components.com/), a CSS-
20
20
  The approach is roughly:
21
21
 
22
22
  1. A "base" styled component with shared styles: `ButtonBase`
23
- 2. Each variant in the [Figma designs](https://www.figma.com/file/xfnqeuF8FgoqhJSUs5GTsK/PDS-Components-Desktop?node-id=16%3A7&t=22cWETfRERKj9wkP-0) is a styled component 'extending' the base component: ` const PrimaryButton = styled(ButtonBase)`` `
23
+ 2. Each variant in the Figma designs is a styled component 'extending' the base component: ` const PrimaryButton = styled(ButtonBase)`` `
24
24
 
25
25
  - All variant are placed in an object (a map but not a `Map()`)
26
26
  - The exported takes a `variant` prop and uses it to get the right styled component from the object map
@@ -29,42 +29,43 @@ The approach is roughly:
29
29
 
30
30
  This component library is very much a work in progress and has many gaps.
31
31
 
32
- * A component that exposes the spacing design tokens in an easy-to-use, type-safe way. Usually this is called `Box`.
33
- * Far from all components in the [Components Figma](https://www.figma.com/file/xfnqeuF8FgoqhJSUs5GTsK/PDS-Components-Desktop) have been implemented
34
- * For existing component, we need more documentation. Often, design systems include a "Guidelines" or "When to Use" section" on the component doc page.
35
- * Tests!
32
+ - A component that exposes the spacing design tokens in an easy-to-use, type-safe way. Usually this is called `Box`.
33
+ - Far from all components in the Components Figma have been implemented
34
+ - For existing component, we need more documentation. Often, design systems include a "Guidelines" or "When to Use" section" on the component doc page.
35
+ - Tests!
36
36
 
37
37
  ## Guiding Principles
38
38
 
39
39
  Partly inspired by these
40
40
 
41
- * [Notes on maintaining an internal React component library](https://www.gabe.pizza/notes-on-component-libraries/)
42
- * [Component API Standards](https://jonambas.com/posts/component-api-standards)
41
+ - [Notes on maintaining an internal React component library](https://www.gabe.pizza/notes-on-component-libraries/)
42
+ - [Component API Standards](https://jonambas.com/posts/component-api-standards)
43
43
 
44
44
  ### Start Simple
45
45
 
46
46
  Or the “Principle of Least Power”.
47
47
 
48
- For example, don’t start building a table component that covers many use-cases. Instead start with just the reusable parts of the table that can be shared between many use-cases.
48
+ For example, don’t start building a table component that covers many use-cases. Instead, start with just the reusable parts of the table that can be shared between many use-cases.
49
49
 
50
50
  ### For content, prefer composition over props
51
51
 
52
- - ❌ `<Text variant="body" text="Some text" />`
53
- - ✅ `<Text variant="body">Some text</Text>`
52
+ - ❌ `<Text variant="body" text="Some text" />`
53
+ - ✅ `<Text variant="body">Some text</Text>`
54
54
 
55
- ### Prefer `compound components` over one large component with many props
55
+ ### Prefer 'compound components' over one large component with many props
56
56
 
57
57
  Similar to last point. Compound components scale better.
58
58
 
59
-
59
+
60
+
60
61
  ```jsx
61
62
  <AlertDialog
62
- title="Header"
63
- description="Optional description"
64
- cancelButtonText="Close"
63
+ title='Header'
64
+ description='Optional description'
65
+ cancelButtonText='Close'
65
66
  onCancel={() => {}}
66
- confirmButtonText="Delete"
67
- confirmButtonVariant="primary"
67
+ confirmButtonText='Delete'
68
+ confirmButtonVariant='primary'
68
69
  onDelete={() => {}}
69
70
  // ... and so on
70
71
  >
@@ -76,37 +77,43 @@ Similar to last point. Compound components scale better.
76
77
  ```
77
78
 
78
79
 
80
+
79
81
  ```jsx
80
- <AlertDialog>
81
- <AlertDialogTrigger asChild>
82
- <Button>Open dialog</Button>
83
- </AlertDialogTrigger>
84
- <AlertDialogContent size={size}>
85
- <AlertDialogTitle>Header</AlertDialogTitle>
86
- <AlertDialogDescription>Optional description</AlertDialogDescription>
87
- <Text type='body'>
88
- Powering the next generation of transit We help build more sustainable
89
- cities with convenient and reliable transit for all
90
- </Text>
91
- <AlertDialogFooter>
92
- <AlertDialogCancel asChild>
93
- <Button size='large' variant='primary' emphasis='medium'>
94
- Close
95
- </Button>
96
- </AlertDialogCancel>
97
- <AlertDialogAction asChild>
98
- <Button size='large' variant='danger'>
99
- Delete
100
- </Button>
101
- </AlertDialogAction>
102
- </AlertDialogFooter>
103
- </AlertDialogContent>
104
- </AlertDialog>
82
+ <AlertDialog>
83
+ <AlertDialogTrigger asChild>
84
+ <Button>Open dialog</Button>
85
+ </AlertDialogTrigger>
86
+ <AlertDialogContent size={size}>
87
+ <AlertDialogTitle>Header</AlertDialogTitle>
88
+ <AlertDialogDescription>Optional description</AlertDialogDescription>
89
+ <Text type='body'>
90
+ Powering the next generation of transit We help build more sustainable
91
+ cities with convenient and reliable transit for all
92
+ </Text>
93
+ <AlertDialogFooter>
94
+ <AlertDialogCancel asChild>
95
+ <Button size='large' variant='primary' emphasis='medium'>
96
+ Close
97
+ </Button>
98
+ </AlertDialogCancel>
99
+ <AlertDialogAction asChild>
100
+ <Button size='large' variant='danger'>
101
+ Delete
102
+ </Button>
103
+ </AlertDialogAction>
104
+ </AlertDialogFooter>
105
+ </AlertDialogContent>
106
+ </AlertDialog>
105
107
  ```
106
108
 
107
109
  ### Prefer React Context for components that depend on each other
108
110
 
109
- See [Most of the time, it’s a good idea to use React context for components that depend on each other.](https://www.gabe.pizza/notes-on-component-libraries/#most-of-the-time-its-a-good-idea-to-use-react-context-for-components-that-depend-on-each-other) for an example. This is also how Radix does it.
111
+ Compound components are components that <q cite="https://kentcdodds.com/blog/compound-components-with-react-hooks">components that work together to accomplish a useful task</q>.
112
+ Radix makes extensive use of compound components.
113
+
114
+ Also see [Most of the time, it’s a good idea to use React context for components that depend on each other.](https://www.gabe.pizza/notes-on-component-libraries/#most-of-the-time-its-a-good-idea-to-use-react-context-for-components-that-depend-on-each-other) for an example.
115
+
116
+ The context should only be consumed within the library component and not exported.
110
117
 
111
118
  <figure>
112
119
  > [T]he context should be kept internal to the library. Allowing the naked context to be imported and handled by applications creates a brittle coupling that will easily break in future upgrades.
@@ -125,13 +132,12 @@ Avoid the Children API and `cloneElement`.
125
132
  The Children API is a <q>leaky abstraction</q> and in [maintenance mode](https://github.com/reactjs/rfcs/pull/61#issuecomment-431247764).
126
133
  <small>At the moment it's only used in the breadcrumbs component.</small>
127
134
 
128
- The [React docs](https://beta.reactjs.org/reference/react/cloneElement#cloneelement) discourages the use of `cloneElement` because <q cite="https://beta.reactjs.org/reference/react/cloneElement#cloneelement">Cloning children makes it hard to tell how the data flows through your app.</q> and <q cite="https://beta.reactjs.org/reference/react/cloneElement#cloneelement">Using cloneElement is uncommon and can lead to fragile code</q>..
129
-
135
+ The [React docs](https://beta.reactjs.org/reference/react/cloneElement#cloneelement) discourages the use of `cloneElement` because <q cite="https://beta.reactjs.org/reference/react/cloneElement#cloneelement">Cloning children makes it hard to tell how the data flows through your app.</q> and <q cite="https://beta.reactjs.org/reference/react/cloneElement#cloneelement">Using cloneElement is uncommon and can lead to fragile code</q>.
130
136
 
131
137
  ### Don't rename HTML attributes
132
138
 
133
139
  <figure>
134
- > Native attributes or common props, such as `className`, `id` or `onClick`, should not be renamed. Don't force your engineers to learn APIs they already know.
140
+ <blockquote> Native attributes or common props, such as `className`, `id` or `onClick`, should not be renamed. Don't force your engineers to learn APIs they already know.</blockquote>
135
141
  <figcaption>
136
142
  <cite>
137
143
  <a href="https://www.jonambas.com/posts/component-api-standards">React Component API Standards — Native Attributes</a>
@@ -148,47 +154,52 @@ It is unfortunate that react-aria breaks with this principle. Therefore we have
148
154
 
149
155
  Using design tokens consistently will make it easier to change values at scale in the future.
150
156
 
151
- - ❌ `color: black;`
152
- - ✅ `color: ${tokens.color_black};`
157
+ - ❌ `color: black;`
158
+ - ✅ `color: ${tokens.color_black};`
153
159
 
154
160
  ## Prefer meaningful tokens
155
161
 
156
162
  For example, if we ever decide to implement dark mode, meaningfully-named tokens will make this switch easier.
157
163
 
158
- - ❌ `color: ${tokens.color_black};`
159
- - ✅ `color: ${tokens.tokens.color_text_strong};`
164
+ - ❌ `color: ${tokens.color_black};`
165
+ - ✅ `color: ${tokens.tokens.color_text_strong};`
160
166
 
161
167
  ### Use HSL colors
162
168
 
163
169
  [HSL notation](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl) is more readable and more intuitive. Prefer it over other color notations like hex codes or `rgb()`
164
170
 
165
- - ❌ `color: #4287f5;`
166
- - ❌ `color: rgb(66, 135, 245);`
167
- - ✅ `color: hsl(217deg 90% 61%);`
171
+ - ❌ `color: #4287f5;`
172
+ - ❌ `color: rgb(66, 135, 245);`
173
+ - ✅ `color: hsl(217deg 90% 61%);`
168
174
 
169
175
  Prefer modern [`hsl()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl) over `hsla()`. `hsla` is legacy syntax. Add the alpha channel at the end after a `/`.
170
176
 
171
- - ❌ `color: hsla(217deg, 90%, 61%, 0.8);`
172
- - ✅ `color: hsl(217deg 90% 61% / 0.8);`
177
+ - ❌ `color: hsla(217deg, 90%, 61%, 0.8);`
178
+ - ✅ `color: hsl(217deg 90% 61% / 0.8);`
173
179
 
174
180
  Some reading material on this:
175
181
 
176
- * [Why you should use HSL over other colour formats in your CSS.](https://sujansundareswaran.com/blog/why-hsl-is-better-than-hex-and-rgb)
177
- * [Using HSL Colors In CSS](https://www.smashingmagazine.com/2021/07/hsl-colors-css/)
182
+ - [Why you should use HSL over other colour formats in your CSS.](https://sujansundareswaran.com/blog/why-hsl-is-better-than-hex-and-rgb)
183
+ - [Using HSL Colors In CSS](https://www.smashingmagazine.com/2021/07/hsl-colors-css/)
178
184
 
179
185
  ## Style variants
180
186
 
181
- Style styled-components usingg CSS variables defined in the component.
182
-
183
187
  > **Warning**
184
188
  > This is not settled and this pattern is not followed consistently (yet?).
185
189
 
190
+ Use CSS variables for the dynamic parts in styled-components using.
191
+
186
192
  See [The styled-components Happy Path](https://www.joshwcomeau.com/css/styled-components/)
187
193
 
194
+ ### Merge props
195
+
196
+ Use the [`mergeProps`](https://react-spectrum.adobe.com/react-aria/mergeProps.html) function from `@react-aria/util` to merge props correctly.
197
+ For example, Radix adds events handlers to buttons inside a `*Trigger` components with an `asChild` prop, `mergeProps` ensures there are chained instead of overwritten which enables functionality to be composed.
198
+
188
199
  ### Forward refs
189
200
 
190
201
  <figure>
191
- > Refs should always be forwarded, either to the outermost DOM element, or to the most applicable element of the component. For example form components should forward refs to `<input/>`.
202
+ <blockquote>Refs should always be forwarded, either to the outermost DOM element, or to the most applicable element of the component. For example form components should forward refs to `<input/>`.</blockquote>
192
203
  <figcaption>
193
204
  <cite>
194
205
  <a href="https://www.jonambas.com/posts/component-api-standards">React Component API Standards — Refs</a>
@@ -199,7 +210,7 @@ See [The styled-components Happy Path](https://www.joshwcomeau.com/css/styled-co
199
210
  This is very important for components based on RadixUI and react-aria to work correctly.
200
211
 
201
212
  <figure>
202
- > All component parts that render a DOM element have an `asChild` prop. This is useful when you want a part to attach its accessibility and functional requirements onto your own element instead.
213
+ <blockquote>All component parts that render a DOM element have an `asChild` prop. This is useful when you want a part to attach its accessibility and functional requirements onto your own element instead.</blockquote>
203
214
  <figcaption>
204
215
  <cite>
205
216
  <a href="https://www.radix-ui.com/docs/primitives/overview/styling#changing-the-rendered-element">React Component API Standards — Changing the rendered element</a>
@@ -218,10 +229,10 @@ For compound states, e.g `date-state='selected on'` the latter will not work.
218
229
 
219
230
  (I like to think of it like `[...strings.split(" ")].includes(value)`. vs `strings === value`)
220
231
 
221
- - ❌ `[data-state='selected']`.
222
- - ✅ `[data-state~='selected']`
223
-
224
- Radix adds a custom attribute with the state automatically. The attribute names and values are listed on each component's doc page ([example](https://www.radix-ui.com/docs/primitives/components/toggle#root)).
232
+ - ❌ `[data-state='selected']`.
233
+ - ✅ `[data-state~='selected']`
234
+
235
+ Radix adds a custom attribute with the state automatically. The attribute names and values are listed on each component's doc page ([example](https://www.radix-ui.com/docs/primitives/components/toggle#root)).
225
236
  For component built on react-aria, we need to add `data-` attribute ourselves.
226
237
 
227
238
  Recommended reads:
@@ -241,7 +252,6 @@ There are also a few react-aria hooks to handle these interaction state ([useFoc
241
252
  > **Warning**
242
253
  > Unfinished
243
254
 
244
-
245
255
  Only write TypeScript files.
246
256
  The linting config is also quite strict with `@typescript-eslint`.
247
257
 
@@ -251,8 +261,12 @@ Correct component types make it easier to use components without having to look
251
261
  Exact types for props (for editor autocomplete) is a necessity, not a nice-to-have. Be as detailed as possible.
252
262
 
253
263
  <figure>
254
- > Avoid “stringly typed” code. Prefer more appropriate types where not every string is a possibility.
255
- > Prefer a union of string literal types to string if that more accurately describes the domain of a variable. You’ll get stricter type checking and improve the development experience.
264
+ <blockquote>
265
+ <ul>
266
+ <li>Avoid “stringly typed” code. Prefer more appropriate types where not every string is a possibility.</li>
267
+ <li>Prefer a union of string literal types to string if that more accurately describes the domain of a variable. You’ll get stricter type checking and improve the development experience.</li>
268
+ </ul>
269
+ </blockquote>
256
270
  <figcaption>
257
271
  <cite>
258
272
  <a href="https://www.oreilly.com/library/view/effective-typescript/9781492053736/ch04.html#avoid-strings">Effective TypeScript - Prefer More Precise Alternatives to String Types</a>
@@ -261,16 +275,15 @@ Exact types for props (for editor autocomplete) is a necessity, not a nice-to-ha
261
275
  </figure>
262
276
  </figure>
263
277
 
264
-
265
- - `type Variant = string;`
266
- - ✅ `type Variant = 'primary' | 'secondary' | 'danger' | 'inverse';`
278
+ - ❌ `type Variant = string;`
279
+ - `type Variant = 'primary' | 'secondary' | 'danger' | 'inverse';`
267
280
 
268
281
  ### Avoid spreads on native JSX elements
269
282
 
270
283
  > **Warning**
271
- > This is a principle we don't currently abide by but should!
284
+ > This is a principle we don't currently abide by but should!
272
285
 
273
- See [Avoiding JSX spread on foreign data prevents weird bugs sometimes.](https://www.gabe.pizza/notes-on-component-libraries/#avoiding-jsx-spread-on-foreign-data-prevents-weird-bugs-sometimes).
286
+ See [Avoiding JSX spread on foreign data prevents weird bugs sometimes.](https://www.gabe.pizza/notes-on-component-libraries/#avoiding-jsx-spread-on-foreign-data-prevents-weird-bugs-sometimes).
274
287
 
275
288
  Two ways we can solve this
276
289
 
@@ -279,34 +292,27 @@ Two ways we can solve this
279
292
 
280
293
  > I recommend, whenever possible, to destructure the props object and forward keys as needed. Breaking the props down removes excessive keys, allows setting defaults, and makes grepping the code easier.
281
294
 
282
- One downside I see the #2 is that
283
-
284
295
  ## Examples
285
296
 
286
297
  - [the component gallery](https://component.gallery/) "Designed to be a reference for anyone building component-based user interfaces, The Component Gallery is an up-to-date repository of interface components based on examples from the world of design systems."
287
298
  - [Storybook showcase](https://storybook.js.org/showcase)
299
+ - [Shopify Polaris](https://polaris.shopify.com/)
288
300
  - [Primer: React implementation of GitHub's Primer Design System](https://primer.style/react/)
289
301
  - [Paste: The Design System for building Twilio customer experiences](https://paste.twilio.design/)
290
302
  - [Spectrum: Adobe’s design system.](https://react-spectrum.adobe.com/react-spectrum/)
291
303
  - [Evergreen: Segment’s design system](https://evergreen.segment.com/)
292
304
  - [awesome-react-design-systems](https://github.com/jbranchaud/awesome-react-design-systems)
293
305
 
294
- ## Reading
306
+ ## Misc Reading
295
307
 
296
308
  - [The styled-components Happy Path](https://www.joshwcomeau.com/css/styled-components/)
309
+ - [Demystifying styled-components](https://www.joshwcomeau.com/react/demystifying-styled-components/)
297
310
  - [CSS Variables for React Devs](https://www.joshwcomeau.com/css/css-variables-for-react-devs/)
298
-
299
311
  - [You Don’t Need A UI Framework](https://www.smashingmagazine.com/2022/05/you-dont-need-ui-framework/)
300
-
301
- ###
302
-
303
312
  - [Vadim Demedes Design system tips](https://twitter.com/i/events/1577907596966641665)
304
- - [https://www.robinrendle.com/notes/the-difference-between-correct-ness-and-useful-ness-in-a-design-system/](https://www.robinrendle.com/notes/the-difference-between-correct-ness-and-useful-ness-in-a-design-system/)
305
-
313
+ - [The difference between correct-ness and useful-ness in a design system/](https://www.robinrendle.com/notes/the-difference-between-correct-ness-and-useful-ness-in-a-design-system/)
306
314
  - [Apple Developer: Layout - Foundations - Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/foundations/layout/)
307
315
 
308
-
309
-
310
316
  #### TypeScript
311
317
 
312
318
  - [TypeScript + React: Typing Generic forwardRefs](https://fettblog.eu/typescript-react-generic-forward-refs/)