@n3e/styled 1.0.0 → 1.0.2

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
@@ -1,44 +1,33 @@
1
1
  # styled
2
2
 
3
- A high performance and easy to use CSS-in-JS library with support for server-side rendering. Built similar to other popular libraries, with a familiar API, providing a great overall developer experience.
4
-
5
- Styles are defined using Object Literal syntax, meaning instead of writing properties in `kebab-case` like regular CSS, they are in `camelCase` eg: `max-width` would be `maxWidth`. Don't worry, Styled provides autocompletion and type checking for CSS properties and values thanks to [CSSType](https://github.com/frenic/csstype#readme).
6
-
7
- There is also a way to define global styles using CSS, more on that later.
3
+ A high performance and easy to use CSS-in-JS library that can be used with `React` or `Solid`.
8
4
 
9
5
  ## Installation
10
6
 
11
-
12
7
  ```shell
13
- # npm
8
+ # with npm
14
9
  npm install @n3e/styled
15
10
 
16
- # yarn
11
+ # with yarn
17
12
  yarn add @n3e/styled
18
13
 
19
- #pnpm
14
+ # with pnpm
20
15
  pnpm add @n3e/styled
21
16
 
22
- #bun
17
+ # with bun
23
18
  bun add @n3e/styled
24
19
  ```
25
20
 
26
- ## Getting started
27
-
28
- Let's start by building a simple button.
21
+ ## Usage
29
22
 
30
23
  ```tsx
31
24
  import styled from '@n3e/styled';
32
25
 
33
- const buttonAccent = 'hotpink';
34
-
35
26
  const Button = styled.button({
36
27
  appearance: 'none',
37
- backgroundColor: buttonAccent,
38
- border: `2px solid ${buttonAccent}`,
39
- borderRadius: '4px',
40
- fontSize: '0.875rem',
41
- lineHeight: '1.5rem',
28
+ backgroundColor: '#ff6995',
29
+ border: '2px solid #ff6995',
30
+ borderRadius: '0.25rem',
42
31
  margin: 0,
43
32
  padding: '0 6px',
44
33
  transition: '0.2s linear'
@@ -51,468 +40,18 @@ const Composition = () => (
51
40
  );
52
41
  ```
53
42
 
54
- ## Pseudo
55
-
56
- Styled comes with a [helper](docs/api.md#style-helper) for writing pseudo styles, below is an example of how to use `pseudo-classes`.
57
-
58
- ```tsx
59
- const Button = styled.button({
60
- // button base styles
61
-
62
- [style.hover]: {
63
- backgroundColor: 'rgba(255, 105, 180, 0.7)'
64
- },
65
-
66
- // pseudo class function
67
- [style.not(style.disabled)]: {
68
- backgroundColor: 'purple',
69
- borderColor: 'purple',
70
- color: 'white'
71
- },
72
-
73
- // you can write it yourself, if preferred
74
- ':hover': {
75
- backgroundColor: 'rgba(255, 105, 180, 0.7)'
76
- },
77
-
78
- ':not(:disabled)': {
79
- backgroundColor: 'purple',
80
- borderColor: 'purple',
81
- color: 'white'
82
- }
83
- });
84
-
85
- const Composition = () => (
86
- <Button>
87
- I'm a button
88
- </Button>
89
- );
90
- ```
91
-
92
- Similarly `pseudo-element` styles are defined as shown below.
93
-
94
- ```tsx
95
- const PrefixedUsingBefore = styled.div({
96
- [style.before]: {
97
- content: '$'
98
- },
99
-
100
- // the same can be done manually
101
- '::before': {
102
- content: '$'
103
- }
104
- });
105
-
106
- const Composition = () => (
107
- <PrefixedUsingBefore>dollar bucks</PrefixedUsingBefore>
108
- );
109
- ```
110
-
111
- ## Combinator
112
-
113
- ### Descendant combinator
114
-
115
- ```tsx
116
- const Paragraph = styled.p({
117
- margin: 0,
118
- padding: 0
119
- });
120
-
121
- const RichText = styled.div({
122
- [style.selector('p')]: {
123
- margin: '0 0 24px'
124
- },
125
-
126
- // target a Styled Component
127
- [style.selector(Paragraph)]: {
128
- margin: '0 0 24px'
129
- }
130
- });
131
-
132
- const Composition = () => (
133
- <RichText>
134
- <p>Para one text<p>
135
- <Paragraph>Para two text<Paragraph>
136
- </RichText>
137
- );
138
- ```
139
-
140
- ### Child combinator (>)
141
-
142
-
143
- ```tsx
144
- const Image = styled.img({
145
- display: 'block',
146
- maxWith: '100%'
147
- });
148
-
149
- const Paragraph = styled.p({
150
- // paragraph styles
151
- });
152
-
153
- const RichText = styled.div({
154
- [style.selector('> img')]: {
155
- border: '2px solid yellow'
156
- },
157
-
158
- // target a Styled Component
159
- [style.selector(`> ${Image}`)]: {
160
- border: '2px solid yellow'
161
- }
162
- });
163
-
164
- const Composition = () => (
165
- <RichText>
166
- <Image src='path/to/image' />
167
- <Paragraph>Para one text<Paragraph>
168
- <Paragraph>Para two text<Paragraph>
169
- </RichText>
170
- );
171
- ```
172
-
173
- ### Sibling combinators (~ or +)
174
-
175
- ```tsx
176
- const Label = styled.label({
177
- display: 'inline-block',
178
- cursor: 'pointer',
179
- verticalAlign: 'top',
180
- });
181
-
182
- const Checkbox = styled.input({
183
- [style.checked]: {
184
- [style.selector('+ label')]: {
185
- fontWeight: 'bold'
186
- }
187
-
188
- // target a Styled Component
189
- [style.selector(`+ ${Label}`)]: {
190
- fontWeight: 'bold'
191
- }
192
- }
193
- });
194
-
195
-
196
- const Composition = () => (
197
- <>
198
- <Checkbox type='checkbox' {...otherProps} />
199
- <Label>Checkbox label</Label>
200
- <>
201
- );
202
- ```
203
-
204
- ## Attribute selectors
205
-
206
- You can event create selectors based on attributes and yes, Styled does comes with a [helper](docs/api.md#attribute-selector) for creating these.
207
-
208
- ```tsx
209
- const Link = styled.a({
210
- // link base styles
211
-
212
- [style.attribute('href').startsWith('http', 'https')]: {
213
- // some attribute based styles
214
- }
215
-
216
- // you need to use Styled's combinator helper `or` to create
217
- // nested selector lists (ie: comma separated selector)
218
- [style.or(
219
- '[href^="http"]',
220
- '[href^="https"]'
221
- )]: {
222
- // some attribute based styles
223
- },
224
-
225
- // or have to duplicate style definitions
226
- '[href^="http"]': { /* some attribute based styles */ },
227
- '[href^="https"]': { /* some attribute based styles */ }
228
- });
229
-
230
- const Composition = () => (
231
- <Link href='#'>
232
- I'm a Link
233
- </Link>
234
- );
235
- ```
236
-
237
- ## At-rules
238
-
239
- Nested at-rules such as `@media`, `@supports` and even `@container` are declared as demonstrated below.
240
-
241
- ```tsx
242
- const Container = styled.div({
243
- // container base styles
244
-
245
- '@media screen and (min-width: 576px)': {
246
- maxWidth: '540px'
247
- },
248
-
249
- '@media screen and (min-width: 768px)': {
250
- maxWidth: '720px'
251
- },
252
-
253
- // you can even nest at-rules
254
- '@supports (display: flex)': {
255
- display: 'flex',
256
- flexDirection: 'column',
257
-
258
- '@media screen and (min-width: 768px)': {
259
- flexDirection: 'row'
260
- }
261
- }
262
- });
263
- ```
264
-
265
- For examples of `@keyframes` and `@font-face`, refer to [API](docs/api.md#global-styles) section.
266
-
267
- Styled also exposes a [helper](docs/api.md#media-query-builder) for building media queries.
268
-
269
- ## Prop based styles
270
-
271
- Property matching or pattern matching can be achieved by calling the `prop` method on the `style` helper.
272
-
273
- ```tsx
274
- const Link = styled.a({
275
- display: 'inline-block',
276
- textTransform: 'uppercase',
277
- cursor: 'pointer',
278
-
279
- [style.prop('isActive')]: {
280
- color: 'hotpink'
281
- textDecoration: 'none'
282
- }
283
- });
284
-
285
- const Composition = () => (
286
- <Link href='#' isActive>
287
- I'm a Link
288
- </Link>
289
- );
290
- ```
291
-
292
- You can even specify a function that takes the prop being matched as its only argument and also type the props for the same.
293
-
294
- ```tsx
295
- type SVGProps = {
296
- width?: number;
297
- height?: number;
298
- };
299
-
300
- const Svg = styled.svg<SVGProps>({
301
- display: 'inline-block',
302
- stroke: 'transparent',
303
- fill: 'currentColor',
304
- verticalAlign: 'middle',
305
- pointerEvents: 'none',
306
- cursor: 'inherit',
307
-
308
- [style.prop('width')]: (width: number) => ({
309
- width: `${width}px`
310
- }),
311
-
312
- [style.prop('height')]: (height: number) => ({
313
- height: `${height}px`
314
- })
315
- });
316
-
317
- const Composition = () => (
318
- <Svg width={36} height={36} />
319
- );
320
- ```
321
-
322
-
323
- > **IMPORTANT!**
324
- >
325
- > In order to avoid maintaining a whitelist of props that are not meant to be passed down to the underlying HTML tag, all props used in any of the pattern matching functions will be treated as transient props and will **NOT** flow downward.
326
- >
327
- > Thus in the example above `width` and `height` props will not be passed to the underlying `svg` tag, so ensure styles are defined to handle that.
328
-
329
- To match against multiple properties, just use one of `all`, `any` or `not` methods on the `style.props` helper.
330
-
331
- ```typescript
332
- type CheckboxUIProps = {
333
- isChecked?: boolean;
334
- isDisabled?: boolean;
335
- };
336
-
337
- const CheckboxUI = styled.span<CheckboxUIProps>({
338
- [style.props.all('isChecked', 'isDisabled')]: {
339
- opacity: 0.7
340
- }
341
- });
342
- ```
343
-
344
- In the above example, opacity styles will only be applied when both `isChecked` and `isDisabled` props are supplied to the `CheckBoxUI` component.
345
-
346
- When using a function for matching multiple props, be sure to pass in **all** props or the props object if not destructuring.
347
-
348
- ```typescript
349
- type ButtonProps = {
350
- borderColour?: string;
351
- borderStyle?: 'solid' | 'dashed' | 'none';
352
- };
353
-
354
- const Button = styled.button<ButtonProps>({
355
- // button base styles
356
-
357
- [style.props.any('borderColour', 'borderStyle')]: ({
358
- borderColour,
359
- borderStyle
360
- }: ButtonProps) => ({
361
- borderColor: borderColour || 'purple',
362
- borderStyle: borderStyle || 'solid'
363
- })
364
- });
365
- ```
366
-
367
- ## Generics
368
-
369
- Not to confuse with Typescript's Generics, there is a mechanism for defining Components that are _"generic"_, basically a Higher Order Component that takes a `Component` as its only argument.
370
-
371
- To define a Generic component, simply call the `generic` method as shown below.
372
-
373
- ```typescript
374
- type SizeProp = {
375
- size?: number;
376
- };
377
-
378
- const GenericSize = styled.generic<SizeProp>({
379
- boxSizing: 'border-box',
380
-
381
- [style.prop('size')]: (size: number) => ({
382
- fontSize: `${size / 16}rem`,
383
- lineHeight: `${(size / 16) * 1.5}rem`
384
- })
385
- });
386
- ```
387
-
388
- Then wrap a component with it as shown below.
389
-
390
- ```tsx
391
- const Heading = styled.h1({
392
- // some styles
393
- });
394
-
395
- const Wrapped = GenericSize(Heading);
396
-
397
- const Composition = () => (
398
- <Wrapped size={64}>
399
- Heading Component wrapped
400
- </Wrapped>
401
- );
402
- ```
403
-
404
- Generic components will pass all props received down to the wrapped component. Ensure that the `className` prop is passed down to the underlying DOM node when using custom components.
405
-
406
- ```tsx
407
- type CustomHeadingProps = {
408
- children?: React.ReactNode;
409
- className?: string;
410
- };
43
+ ## Solid
411
44
 
412
- const CustomHeading = ({
413
- children,
414
- className
415
- }) => <h2 className={className}>{ children }</h2>;
416
-
417
- const Wrapped = GenericSize(CustomHeading);
418
-
419
- const Composition = () => (
420
- <Wrapped size={48}>
421
- CustomHeading Component wrapped
422
- </Wrapped>
423
- );
424
- ```
425
-
426
- To avoid nesting when trying to use multiple generic components, simply call the `extend` method.
45
+ SolidJS users need to import Styled from the the `solid` output folder:
427
46
 
428
47
  ```typescript
429
- const GenericContentParadigm = styled.generic({
430
- margin: '0 0 1.5rem',
431
- [style.lastChild]: {
432
- marginBottom: 0
433
- }
434
- });
435
-
436
- const GenericHugeText = styled.generic({
437
- fontSize: '4.5rem',
438
- lineHeight: '5rem'
439
- });
440
-
441
- const PageHeading = styled.h1({
442
- color: '#333',
443
- fontWeight: 400,
444
- padding: 0
445
- }).extend(
446
- GenericContentParadigm,
447
- GenericHugeText
448
- );
449
- ```
450
-
451
- You can also extend from other Styled Components and even plain object literal styles. The `extend` method performs a deep merge, so nested styles containing duplicate keys will be combined.
48
+ // as ES module
49
+ import styled from '@n3e/styled/solid/esm';
452
50
 
453
- ```typescript
454
- const GenericClearFloat = styled.generic({
455
- float: 'left',
456
- [style.after]: {
457
- content: '',
458
- clear: 'both',
459
- display: 'block'
460
- }
461
- });
462
-
463
- const Danger = styled.span({
464
- color: 'red',
465
- [style.after]: {
466
- content: '!'
467
- }
468
- });
469
-
470
- const ExtendMayhem = styled.div({
471
- color: 'blue',
472
- [style.hover]: {
473
- textDecoration: 'underline',
474
- [style.after]: {
475
- color: 'pink',
476
- cursor: 'pointer'
477
- }
478
- }
479
- }).extend(
480
- Danger,
481
- GenericClearFloat,
482
- {
483
- [style.hover]: {
484
- textDecoration: 'none',
485
- [style.after]: {
486
- cursor: 'default'
487
- }
488
- }
489
- }
490
- );
491
- ```
492
-
493
- The resulting object styles for `<ExtendMayhem>` will be
494
-
495
- ```typescript
496
- {
497
- float: 'left',
498
- color: 'red',
499
- [style.after]: {
500
- content: '',
501
- clear: 'both',
502
- display: 'block'
503
- },
504
- [style.hover]: {
505
- textDecoration: 'none',
506
- [style.after]: {
507
- color: 'pink',
508
- cursor: 'default'
509
- }
510
- }
511
- }
51
+ // as CommonJS module
52
+ import styled from '@n3e/styled/solid/cjs';
512
53
  ```
513
54
 
514
- ## More docs
55
+ ## Documentation
515
56
 
516
- * [Advanced](docs/advanced.md) - server-side rendering, using refs, experimental features etc.
517
- * [API](docs/api.md) - style helper, media query builder, global styles etc.
518
- * [SolidJS](docs/solidjs.md) - as the name suggest, things to know for SolidJS users
57
+ See https://www.styled.guide/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n3e/styled",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CSS-in-JS library with server-side rendering support that can be used with react or solidJS",
5
5
  "module": "react/esm/index.js",
6
6
  "main": "react/cjs/index.js",