, document.getElementById('root'));
--------------------------------------------------------------------------------
/src/docs/advanced.md:
--------------------------------------------------------------------------------
1 | * [Concept: Deduping](/#/advanced/concept-deduping)
2 | * [Concept: Ordering pseudo classes](/#/advanced/concept-ordering-pseudo-classes)
3 | * [Concept: Ordering media queries](/#/advanced/concept-ordering-media-queries)
4 | * [Concept: Ensuring a unique selector](/#/advanced/concept-ensuring-a-unique-selector)
5 | * [content](/#/advanced/-content-)
6 | * [Google Fonts](/#/advanced/google-fonts)
7 | * [$debugName](/#/advanced/-debugname-)
8 | * [Multiple instances](/#/core/multiple-instances)
9 |
10 | ## Concept: Deduping
11 | It is safe to call `style` with the same object strucure again and again (e.g. from within a react render function). `style` doesn't generate new CSS if it's not required, this is shown below:
12 |
13 | ```play
14 | import {style} from 'typestyle';
15 |
16 | const a = style({color:'red'});
17 | const b = style({color:'red'});
18 |
19 |
a:{a},b:{b}. Same? {(a===b).toString()}
;
20 | ```
21 |
22 | We even automatically try to generate the smallest deduped CSS possible e.g. the following
23 | ```ts
24 | style({ color: 'red', $nest: { '&>*': { color: 'red' } } });
25 | ```
26 | Generates the CSS:
27 | ```css
28 | .f1nv0def,.f1nv0def>*{color:red}
29 | ```
30 | You can see that since the structure `{color:red}` was common, so the selectors `.f1nv0def,.f1nv0def>*` are concatenated.
31 |
32 | This gives the following gains:
33 |
34 | * No needless CSS updates + reflows.
35 | * True freedom to use `className` like you would use `style` in your framework of choice.
36 | * No style bloat: Automatically smaller stylesheets based on your object reuse.
37 |
38 | ## Concept: Ordering pseudo classes
39 | You normally don't need to worry about ordering your pseudo classes. For cases when you do, you should use `&&`, then `&&&` so on, to increase specificity (in CSS `.foo` loses to `.foo.foo`). This also shows that you explicitly want the ordering to matter for any later code review.
40 |
41 | ```play
42 | /** BAD */
43 | const hoverBackground = 'green';
44 | const focusBackground = 'red';
45 | const buttonClass = style({
46 | $nest: {
47 | '&:focus': { background: focusBackground },
48 | '&:hover': { background: hoverBackground },
49 | },
50 | });
51 |
52 | /** Force `:focus` to come to the bottom of the generated CSS due to deduping */
53 | const moveDown = style({
54 | background: focusBackground
55 | });
56 |
57 | /** Now `hover` will not work if `focus`ed anymore! */
58 |
59 |
60 |
61 |
62 | ```
63 |
64 | Sample fix:
65 |
66 | ```play
67 | /** GOOD */
68 | const hoverBackground = 'green';
69 | const focusBackground = 'red';
70 | const buttonClass = style({
71 | $nest: {
72 | '&:focus': { background: focusBackground },
73 | /** Use && to increase specifity and show that order matters */
74 | '&&:hover': { background: hoverBackground },
75 | },
76 | });
77 |
78 | /** Force `:focus` to come to the bottom of the generated CSS due to deduping */
79 | const moveDown = style({
80 | background: focusBackground
81 | });
82 |
83 | /** Now `hover` will still work even if `focus`ed! */
84 |
85 |
86 |
87 |
88 | ```
89 |
90 | A common pattern is sytling anchors using [LVHA-order](https://developer.mozilla.org/en-US/docs/Web/CSS/:active):
91 |
92 | ```play
93 | const anchorClass = style({
94 | $nest: {
95 | '&:link': { color: 'blue' },
96 | '&&:visited': { color: 'purple' },
97 | '&&&:hover': { fontWeight: 'bold' },
98 | '&&&&:active': { color: 'lime' },
99 | },
100 | });
101 |
102 | TypeStyle;
106 | ```
107 |
108 | ## Concept: Ordering media queries
109 | Conventional css authors will write media queries with an *override* mindset i.e
110 |
111 | ```css
112 | .some {
113 | /** Common */
114 | font-size: 50px;
115 | /** Default */
116 | color: red;
117 | }
118 | /** Override: change for bigger screens */
119 | @media (min-width: 500px) {
120 | .some {
121 | color: green;
122 | }
123 | }
124 | ```
125 |
126 | Due to style deduping you should not depend on style ordering, with TypeStyle you should write with a *mutally exclusive* mindset
127 |
128 | ```play
129 | import { style, media } from 'typestyle';
130 |
131 | const some = style(
132 | /** Common */
133 | {fontSize: '50px'},
134 | /** Default */
135 | media({minWidth: 0, maxWidth: 499}, {color:'red'}),
136 | /** Change for bigger screens */
137 | media({minWidth: 500}, {color:'green'}),
138 | );
139 |
140 |
Hello world
;
141 | ```
142 |
143 | ## Concept: Ensuring a unique selector
144 | For certain browser scenarios you need to have a unique selector with its own body. The only use case we have experienced for now are browser specific pseudo selectors. For example for `placeholder` styling, having multiple browser specific selectors does not work (even though its valid CSS):
145 |
146 | ```css
147 | /** Does not work */
148 | .f13byak::-webkit-input-placeholder, /* WebKit fails here */
149 | .f13byak::-moz-placeholder, /* Firefox fails here */
150 | .f13byak::-ms-input-placeholder { /* IE fails here */
151 | color: rgb(255, 0, 0),
152 | }
153 |
154 | /** Does work */
155 | .f13byak::-webkit-input-placeholder {
156 | color: rgb(255, 0, 0),
157 | }
158 | .f13byak::-moz-placeholder {
159 | color: rgb(255, 0, 0),
160 | }
161 | .f13byak::-ms-input-placeholder {
162 | color: rgb(255, 0, 0),
163 | }
164 | ```
165 |
166 | You can ensure that a selector gets its own body by adding `$unique : true`. This ensures *that particular object* is not tested for deduping and always emitted even if a similar structure exists:
167 |
168 | ```play
169 | const className = style({
170 | $nest: {
171 | '&::-webkit-input-placeholder': {
172 | $unique: true,
173 | color: `rgb(255, 0, 0)`,
174 | },
175 | '&::-moz-placeholder': {
176 | $unique: true,
177 | color: `rgb(255, 0, 0)`,
178 | },
179 | '&::-ms-input-placeholder': {
180 | $unique: true,
181 | color: `rgb(255, 0, 0)`,
182 | }
183 | }
184 | });
185 |
186 |
187 | ```
188 |
189 | ## `content`
190 |
191 | When assigning a string to the content property it requires double or single quotes in CSS. So you should use whatever string you want e.g. if you want to prefix with `'Hello'` you can wrap that whole content easily with backticks.
192 |
193 | ```play
194 | const hello = style({
195 | $nest: {
196 | '&:before': {
197 | content: `'Hello '`
198 | }
199 | }
200 | });
201 |
is it me you are looking for?
202 | ```
203 | We don't do automatic quoting as you are free to use other things in CSS content that aren't quoted e.g. `attr`:
204 |
205 | ```play
206 | const before = style({
207 | $nest: {
208 | '&:before': {
209 | content: `attr(data-before)`
210 | }
211 | }
212 | });
213 |
214 | is it me you are looking for?
215 |
216 | ```
217 |
218 | ## Google Fonts
219 | If you want to use google fonts e.g. [Roboto](http://www.google.com/fonts#UsePlace:use/Collection:Roboto), you can just use the `@import` syntax they give you with `cssRaw`
220 |
221 | > Note: Be sure to have this call *before* any other calls to `cssRaw` because [@import only works if its at the top of the file](https://www.w3.org/TR/css-cascade-3/#at-import)
222 |
223 | ```ts
224 | /** Import the file */
225 | cssRaw(`
226 | @import url('https://fonts.googleapis.com/css?family=Roboto');
227 | `);
228 |
229 | ```
230 | and then you can use the font like you normally would e.g.
231 |
232 | ```ts
233 | /** Elsewhere */
234 | const className = style({fontFamily:'Roboto, sans-serif'});
235 |
236 |
Demo
237 |
Demo
238 |
Demo
239 |
Demo
240 |
Demo
241 |
;
242 | ```
243 |
244 | ## `$debugName`
245 | If you want meaningful word associated with the generated className for debugging you can use the `$debugName` property e.g.:
246 |
247 | ```play
248 | const className = style({
249 | $debugName: 'bigRed',
250 | color: 'red',
251 | fontSize: '50px',
252 | });
253 |
;
258 | ```
259 |
260 | Note that this name is purely for debugging convenience and has no impact on any of the other logic (e.g. deduping).
261 |
262 | ## Multiple instances
263 | The core `style` function is simply a handle to a single instance of `TypeStyle.style`.
264 |
265 | You can create multiple instances of TypeStyle using the `createTypeStyle` function. There are two ways to use this function:
266 |
267 | * You can use this to create a TypeStyle instance if you just want to *collect* the generated CSS.
268 |
269 | ```js
270 | const instance = typestyle.createTypeStyle();
271 | instance.style({ color : 'red' }); // Will not write a stylesheet anywhere.
272 | const styles = instance.getStyles(); // Write these styles somewhere. You can write them to a tag or a file or wherever.
273 | ```
274 |
275 | * You can pass in a style tag and this typestyle instance will write the styles to that tag.
276 |
277 | ```js
278 | const tag = document.createElement('style');
279 | document.head.appendChild(tag);
280 | const instance = typestyle.createTypeStyle(tag);
281 | instance.style({ color : 'red' }); // Will write to the tag you created
282 | ```
283 |
--------------------------------------------------------------------------------
/src/docs/box.md:
--------------------------------------------------------------------------------
1 | How you manage the space around and inside your components is vital to a great design. First a quick recap of some core CSS concepts that we will use here.
2 |
3 | ### Never let margin bleed
4 | You really only need to know the difference between `margin` (something that's outside) and `padding` (something that is inside). Here's a picture:
5 |
6 | 
7 |
8 |
9 | One more thing about margin : *it collapses*. This means that if two items are next to each other with a margin of `30px` and `20px`, instead of of being separated by `50px` they will be separated by `30px`. This shown below:
10 |
11 | 
12 |
13 | Not only that, if an element is unfortunate to be at the border of its parent, its margin will collapse with its parent. These facts are shown below:
14 |
15 | 
16 |
17 | This makes it very difficult to create a maintainable layout system if your components have external margins
18 |
19 | * Don't have an external `margin` on components.
20 | * `margin` is something that a parent should push down to put a visual seperation between its children. More on this later.
21 |
22 | ### Avoid inline
23 | Having an element as `display: inline` means that it completely ignores its height. Here is a visual difference where an element has been given a height but `inline` ignored it and `inline-block` got it.
24 |
25 | 
26 |
27 | 
28 |
29 | Also you cannot CSS3 transform inline elements. So use a `span` but if there is anything fancy you need the `span` to do, be sure to `inline-block` it.
30 |
31 | > TIP: `csstips` has a mixin `csstips.inlineBlock` for your inline desires.
32 |
33 | ## `csstips.padding`
34 |
35 | `csstips.padding` is a nice mixin to create padding for managing the space inside a component. e.g. Here is some pretty text you can hover over,
36 |
37 | ```play
38 | import {style} from 'typestyle';
39 | import * as csx from 'csx';
40 | import * as csstips from 'csstips';
41 |
42 | const bg = csx.black;
43 | const color = csx.white;
44 | const prettyBox = style(
45 | csstips.padding(10),
46 | csstips.inlineBlock,
47 | {
48 | color:color.darken(.2).toHexString(),
49 | cursor:'pointer',
50 | backgroundColor:bg.toHexString(),
51 | transition: 'color .2s, background-color .2s',
52 | $nest: {
53 | '&:hover':{
54 | color: color.toHexString(),
55 | backgroundColor:bg.lighten(.2).toHexString(),
56 | }
57 | }
58 | }
59 | );
60 |
61 |
Hello World
62 | ```
63 |
64 | This is what a padding should be used for. Maintaining a nice boundary seperation *inside* a component.
65 |
66 | ## Spacing children
67 |
68 | > If a function only does mutation inside is it still functional?
69 |
70 | Remeber the lesson of margins: You cannot have margins bleed. However you can use them to create a nice visual seperation between *your* children (subitems of the component). We provide utilities for just that `csstips.horizontallySpaced` and `csstips.verticallySpaced`
71 |
72 | E.g. a nice vertical layout:
73 |
74 | ```play
75 | import {style} from 'typestyle';
76 | import * as csstips from 'csstips';
77 |
78 | const DemoItem = () =>
85 | Demo Item
86 |
;
87 |
88 |
89 |
90 |
91 |
92 |
93 | ```
94 |
95 | The reason for letting such spacing come down from the parent *instead* of having it on each `DemoItem` is common in application layouts, where you have buttons / page sections popping in and popping out due to some logic regarding page state and user permissions. Having this visual seperation come down using *margins* from the parent results in a more maintainable layout (as the components can be blissfully unaware of their siblings).
96 |
97 | Spacing items like this where there is no *margin bleed* at the borders **composes** nicely too e.g. here are two columns:
98 |
99 | ```play
100 | import {style} from 'typestyle';
101 | import * as csx from 'csx';
102 | import * as csstips from 'csstips';
103 |
104 | const DemoItem = () =>
;
126 | ```
127 |
128 | You can see that, for the user, its impossible to tell the fact that there are two sets of three `DemoItem`s instead of one set of six `DemoItem`s.
129 |
130 | At some level up the heirarchy you would need to create a visual seperation from the border (e.g. at the page level) and there you should use `csstips.padding`. This is shown below where we have a nice root `Page` component:
131 |
132 | ```play
133 | import {style} from 'typestyle';
134 | import * as csx from 'csx';
135 | import * as csstips from 'csstips';
136 |
137 | const DemoItem = () =>
144 | Demo Item
145 |
;
146 |
147 | const DemoCollection = () =>
148 |
149 |
150 |
151 |
;
152 |
153 | /** A nice Page component with padding */
154 | const Page = (props) =>
155 | {props.children}
156 |
;
157 |
158 |
159 |
160 |
161 | ;
162 | ```
163 |
164 |
--------------------------------------------------------------------------------
/src/docs/colors.md:
--------------------------------------------------------------------------------
1 | Color management in a large project is always a challenge. With this in mind, TypeStyle (csx) comes with SASS/LESS/Stylus inspired color functions to make styling simple and reusable.
2 |
3 | > Values from these `csx` utilities need to be `toString`ed before being used in TypeStyle or any other library. This means that they can be used with or without TypeStyle 🌹
4 |
5 | Here are some of the things you can do:
6 |
7 | ---
8 | ## Create New Colors
9 |
10 | ### color(value: string): ColorHelper
11 | Creates a new color from a string
12 |
13 | - Can be a six character hex code, a three character hex code, or a CSS color function
14 |
15 | ```typescript
16 | import { color } from 'csx';
17 |
18 | var red2 = color('#FF0000');
19 | var red3 = color('#F00');
20 | var red4 = color('rgb(255,0,0)');
21 | var red5 = color('rgba(255,0,0,1)');
22 | var red6 = color('hsl(0,100%,50%)');
23 | var red7 = color('hsl(0,100%,50%,1)');
24 | ```
25 |
26 | ### hsl(hue: number, saturation: number | string: lightness: number | string): ColorHelper
27 | Creates a color from hue, saturation, and lightness
28 |
29 | - Hue is a number between 0 and 360.
30 | - Saturation and Lightness can be expressed as a string (e.g. '10%') or as a number between 0 and 1 (e.g. 0.1)
31 |
32 | ```typescript
33 | import { hsl } from 'csx';
34 |
35 | const color1 = hsl(250, .5, .5);
36 | const color1 = hsl(250, '50%', '50%');
37 | ```
38 |
39 | ### hsla(hue: number, saturation: number | string: lightness: number | string, alpha: number | string): ColorHelper
40 | Creates a color from hue, saturation, lightness, and alpha
41 |
42 | - Hue is a number between 0 and 360.
43 | - Saturation and Lightness can be expressed as a string (e.g. '10%') or as a number between 0 and 1 (e.g. 0.1)
44 | - Alpha is expressed as a string (e.g. '10%') or as a number between 0 and 1 (e.g. 0.1)
45 |
46 | ```typescript
47 | import { hsla } from 'csx';
48 |
49 | const color1 = hsla(250, .5, .5, .5);
50 | const color1 = hsla(250, '50%', '50%', '50%');
51 | ```
52 |
53 | ### rgb(red: number, green: number: blue: number): ColorHelper
54 | Creates a color from red, green, and blue values
55 |
56 | - Red, Green, and Blue are expressed as numbers between 0 and 255
57 |
58 | ```typescript
59 | import { rgb } from 'csx';
60 |
61 | const red = rgb(255, 0, 0);
62 | const green = rgb(0, 255, 0);
63 | const blue = rgb(0, 0, 255);
64 | ```
65 |
66 | ### rgba(red: number, green: number: blue: number, alpha: number | string): ColorHelper
67 | Creates a color from red, green, blue, and alpha values
68 |
69 | - Red, Green, and Blue are expressed as numbers between 0 and 255
70 | - Alpha is expressed as a string (e.g. '10%') or as a number between 0 and 1 (e.g. 0.1)
71 |
72 | ```typescript
73 | import { rgba } from 'csx';
74 |
75 | const red = rgba(255, 0, 0, 1);
76 | const green = rgba(0, 255, 0, '100%');
77 | const blue = rgba(0, 0, 255, 1);
78 | ```
79 |
80 | ---
81 | ## Convert to String
82 |
83 | ### toHexString(): string
84 | Returns a string with the RGB Hex code (e.g. black = #000000). Useful when supporting a legacy browser.
85 | ```typescript
86 | import { color } from 'csx';
87 |
88 | color('#FFF').toHexString(); // #FFFFFF
89 | ```
90 |
91 | ### toString(): string
92 | Returns a string representing the color in its current color space. Hex color codes are automatically output as rgb()
93 | ```typescript
94 | import { hsla, rgba } from 'csx';
95 |
96 | rgba(0, 0, 0, .5).toString(); // rgba(0, 0, 0, 50%)
97 | hsla(0, 0, 0, .5).toString(); // hsla(0, 0, 0, 50%)
98 | ```
99 |
100 | ---
101 | ## Changing Color Space / Format
102 |
103 | ### toHSL(): string
104 | Converts to the **H**ue **S**aturation **L**ightness color space
105 | ```typescript
106 | import { color } from 'csx';
107 |
108 | // outputs hsl(0,100%,50%)
109 | const red = color('rgb(255,0,0)').toHSL().toString();
110 | ```
111 |
112 | ### toHSLA(): string
113 | Converts to the **H**ue **S**aturation **L**ightness color space with an **A**lpha channel
114 | ```typescript
115 | import { color, rgb } from 'csx';
116 |
117 | // outputs hsla(0,100%,50%,1)
118 | const red = rgb(255, 0, 0).toHSLA().toString();
119 | ```
120 |
121 | ### toRGB(): string
122 | Converts to the **R**ed **G**reen **B**lue color space
123 | ```typescript
124 | import { color } from 'csx';
125 |
126 | // outputs rgb(255,0,0)
127 | const red = color('hsl(0,100%,50%)').toRGB().toString();
128 | ```
129 |
130 | ### toRGBA(): string
131 | Converts to the **R**ed **G**reen **B**lue color space with an **A**lpha channel
132 | ```typescript
133 | import { color } from 'csx';
134 |
135 | // outputs rgba(255,0,0,1)
136 | const red = hsl(0, 1, .5).toRGBA().toString();
137 | ```
138 |
139 | ---
140 | ## Create a New Colors From Other Colors
141 |
142 | ### darken(amount: number | string, relative?: boolean): ColorHelper
143 | Creates a darker color
144 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
145 |
146 | ```typescript
147 | import { color } from 'csx';
148 |
149 | const red = color('#FF0000');
150 | const red1 = red.darken('10%');
151 | const red2 = red.darken(.1);
152 | ```
153 |
154 | ### desaturate(amount: number | string, relative?: boolean): ColorHelper
155 | Creates a less saturated color
156 |
157 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
158 |
159 | ```typescript
160 | import { color } from 'csx';
161 |
162 | const red = color('#FF0000');
163 | const red1 = red.desaturate('10%');
164 | const red2 = red.desaturate(.1);
165 | ```
166 |
167 | ### fade(alpha: number | string): ColorHelper
168 | Creates the same color with the specified opacity/alpha
169 |
170 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
171 |
172 | ```typescript
173 | import { color } from 'csx';
174 |
175 | const red = color('#FF0000');
176 | const red1 = red.fade('50%');
177 | const red2 = red.fade(.5);
178 | ```
179 |
180 | ### fadeIn(amount: number | string, relative?: boolean): ColorHelper
181 | Creates a more opaque color
182 |
183 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
184 |
185 | ```typescript
186 | import { color } from 'csx';
187 |
188 | const red = color('#FF0000');
189 | const red1 = red.fadeIn('10%');
190 | const red2 = red.fadeIn(.1);
191 | ```
192 |
193 | ### fadeOut(amount: number | string, relative?: boolean): ColorHelper
194 | Creates a more transparent color
195 |
196 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
197 |
198 | ```typescript
199 | import { color } from 'csx';
200 |
201 | const red = color('#FF0000');
202 | const red1 = red.fadeOut('10%');
203 | const red2 = red.fadeOut(.1);
204 | ```
205 |
206 | ### grayscale(): ColorHelper
207 | Creates a grayscale version of the color
208 |
209 | ```typescript
210 | import { color } from 'csx';
211 |
212 | const red = color('#FF0000');
213 | const gray = red.grayscale();
214 | ```
215 |
216 | ### invert(): ColorHelper
217 | Creates the inverse of a color
218 |
219 | ```typescript
220 | import { color } from 'csx';
221 |
222 | const green = color('#FFF').invert();
223 | ```
224 |
225 | ### lighten(amount: number | string): ColorHelper
226 | Creates a lighter color
227 |
228 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
229 |
230 | ```typescript
231 | import { color } from 'csx';
232 |
233 | const red = color('#FF0000');
234 | const red1 = red.lighten('10%');
235 | const red2 = red.lighten(.1);
236 | ```
237 |
238 | ### mix(color2: CSSColor, weight?: string | number): ColorHelper
239 | Creates a new color from an existing color and a second color
240 |
241 | - color2 can be any type that resolves to a CSSColor (string, ColorHelper, etc.)
242 | - weight is expressed as a string (e.g. '50%') or a number between 0 and 1 (e.g. 0.5)
243 |
244 | ```typescript
245 | import { rgb } from 'csx';
246 |
247 | const red = rgb(255, 0, 0);
248 | const blue = rgb(0, 0, 255);
249 | const purple = red.mix(blue, 0.5);
250 | ```
251 |
252 | ### saturate(amount: number | string, relative?: boolean): ColorHelper
253 | Creates a more saturation color
254 |
255 | - amount can be a string (e.g. '10%') or a number between 0 and 1 (e.g. 0.1)
256 |
257 | ```typescript
258 | import { color } from 'csx';
259 |
260 | const red = color('#FF0000');
261 | const red1 = red.saturate('10%');
262 | const red2 = red.saturate(.1);
263 | ```
264 |
265 | ### shade(weight: number): ColorHelper
266 | It darkens the color by mixing black into it. It is the same as black.mix(color, weight).
267 |
268 | - weight is expressed as a number between 0 and 1 (e.g. 0.5)
269 |
270 | ```typescript
271 | import { color } from 'csx';
272 |
273 | const red = color('#FF0000');
274 | const darkerRed = red.shade(0.5);
275 | ```
276 |
277 | ### spin(degrees: number): ColorHelper
278 | Shifts the hue around the color wheel by a certain number of positive or negative degrees
279 |
280 | - degrees is expressed as a number between -360 to 360. Values above or below that range will be wrapped around (e.g. 480 is the same as 120, -480 is the same as -120).
281 |
282 | ```typescript
283 | import { color, spin } from 'csx';
284 |
285 | const red = color('#FF0000');
286 | const green = red.spin(120);
287 | const blue = green.spin(120);
288 | const redAgain = blue.spin(120);
289 | ```
290 |
291 | ### tint(weight: number): ColorHelper
292 | It lightens the color by mixing white into it. It is the same as white.mix(color, weight).
293 |
294 | - weight is expressed as a number between 0 and 1 (e.g. 0.5)
295 |
296 | ```typescript
297 | import { color } from 'csx';
298 |
299 | const red = color('#FF0000');
300 | const lighterRed = red.tint(0.5);
301 | ```
302 |
303 |
304 |
305 | ---
306 | ## Inspect Colors
307 |
308 | ### red(): number
309 | Returns the value of the red component of the color
310 | ```typescript
311 | import { rgb } from 'csx';
312 |
313 | const value = rgb(255, 0, 0).red(); // 255
314 | ```
315 |
316 | ### green(): number
317 | Returns the value of the green component of the color
318 | ```typescript
319 | import { rgb } from 'csx';
320 |
321 | const value = rgb(0, 255, 0).green(); // 255
322 | ```
323 |
324 | ### blue(): number
325 | Returns the value of the blue component of the color
326 | ```typescript
327 | import { rgb } from 'csx';
328 |
329 | const value = rgb(0, 0, 255).blue(); //255
330 | ```
331 |
332 | ### hue(): number
333 | Returns the hue of the color
334 | ```typescript
335 | import { hsl } from 'csx';
336 |
337 | const value = hsl(120, .5, .5).hue(); // 120
338 | ```
339 |
340 | ### saturation(): number
341 | Returns the saturation of the color
342 | ```typescript
343 | import { hsl } from 'csx';
344 |
345 | const value = hsl(120, .5, .5).saturation(); // 0.5
346 | ```
347 |
348 | ### lightness(): number
349 | Returns the lightness/luminosity of the color
350 | ```typescript
351 | import { hsl } from 'csx';
352 |
353 | const value = hsl(120, .5, .5).lightness(); // O.5
354 | ```
355 |
356 | ### alpha() / opacity(): number
357 | Returns the alpha/opacity of the color
358 | ```typescript
359 | import { hsl, rgb } from 'csx';
360 |
361 | const value1 = hsl(120, .5, .5).opacity(); // 1
362 | const value2 = rgb(128, 255, 0).alpha(); // 1
363 | ```
364 |
--------------------------------------------------------------------------------
/src/docs/flex.md:
--------------------------------------------------------------------------------
1 | Having well defined semantics of *how the layout will happen* is important for a maintainable layout system. The more variables you throw into the semantics the less reliable the layout becomes because *you need to compile the final result in your brain* in order to maintain the layout. We will cover the *concept* of a flexible layout system inspired by a *subset* of CSS flexbox.
2 |
3 | ## Root
4 | We will look at `flex`ible children and `content` children. These concepts exist inside a *`root`*. The root is simply the *container* that is used as a point of reference for these children.
5 |
6 | > A general purpose `csstips.flexRoot` exists.
7 |
8 | ## Flex
9 | > A *flex* container `csstips.flex` has the same size as its parent.
10 |
11 | Consider the following layout:
12 |
13 | 
14 |
15 | Here the content *takes up all the available space offered by the parent*. If the parent offers more space, the child takes it gladly.
16 |
17 | 
18 |
19 | The space taken by the child (content) is what is available to its children. No more, no less.
20 |
21 | Such a child is called *flex* (`csstips.flex`).
22 |
23 | ## Content
24 | > A *content* (`csstips.content`) child determines its size based on the size of its content
25 |
26 | In the previous example the child *flexed* into the parent. The only other concept we need for a child is that of *content*. **A *content* child determines its size based on the size of its content**. That is all the space it takes up in the parent. This is shown below where if the parent is too big the rest of the space is unused:
27 |
28 | 
29 |
30 | If the parent is too small the content will overflow:
31 |
32 | 
33 |
34 | > If you want the parent flex container to scroll for content just mixin `csstips.scroll`.
35 |
36 | ## Root (redux)
37 |
38 | In CSS flexbox the concept of `root` does not exist without combining it with the concept of *flex direction*.
39 |
40 | > The general purpose `csstips.flexRoot` is just an alias (more semantic name) for `csstips.horizontal`.
41 |
42 | A root has a default *main axis* of `horizontal`. This is axis in which the children are layed out. In the *cross axis* the children are by default forced to `flex`.
43 |
44 | So there are really two roots:
45 | * `csstips.horizontal`: Lays out children horizontally based on `content` and `flexes` them vertically.
46 | * `csstips.vertical`: Lays out children vertically based on `content` and `flexes` them horizontally.
47 |
48 | Here is an example of a `csstips.horizontal` layout with `content` children.
49 |
50 | 
51 |
52 | Here is an example of a `csstips.vertical` layout with `content` children.
53 |
54 | 
55 |
56 | # Examples
57 | We've seen four types of containers : `csstips.vertical`, `csstips.horizontal`, `csstips.flex`, `csstips.content`. The next step is to practice with real world examples
58 |
59 | ## Vertical Example
60 | Consider the following layout:
61 |
62 | 
63 |
64 | Up front we know that the root is `csstips.vertical`. Assume that we want the `body` section to *flex* i.e. as the root becomes larger it expands to consume the remaining space, while `header` and `footer` remain sized based on their content:
65 |
66 | 
67 |
68 | In our lingo the `root` here is `csstips.vertical` that has three children:
69 |
70 | * header: `csstips.content`
71 | * body: `csstips.flex`
72 | * footer: `csstips.content`
73 |
74 | Visually:
75 |
76 | 
77 |
78 | > As mentioned before the children are going to automatically flex in the cross dimension (in this case horizontal).
79 |
80 | ## Multiple Flex Children
81 | The `flex` children actually share the *remainder* of the space left in the `root` after all the `content` children take up the space they need. This is shown below:
82 |
83 | 
84 |
85 | If the parent becomes bigger the `flex` children share all the space that remains after the `content` children take their share:
86 |
87 | 
88 |
89 | Actually a flex child can decide a *flex scaling factor* (`csstips.flex1`,`csstips.flex2` ... `csstips.flex12`) to divide up the remaining space. E.g. a 1:2 ratio can easily be achieved:
90 |
91 | 
92 |
93 | The remainder space is divided into `3` (`1 + 2`) equal parts with `1` part going to a `A` and `2` parts going to `B`.
94 |
95 | ## Horizontal Example
96 |
97 | Consider the layout:
98 |
99 | 
100 |
101 | Where we want to `body` to grow:
102 |
103 | 
104 |
105 | We can see intutively that it is a *horizontal* container with *content* sidebars and *flex* body.
106 |
107 | * root: `csstips.horizontal`
108 | * sidebar: `csstips.content`
109 | * body: `csstips.flex`
110 | * sidebar: `csstips.content`
111 |
112 | This example should have been fairly obvious and was designed to give you a hands on experience 🌹. Visually:
113 |
114 | 
115 |
116 | ## Arbitrary Layout
117 | Consider this layout:
118 |
119 | ```
120 | ----------------------------------------------------
121 | | HEADER |
122 | ----------------------------------------------------
123 | | | | |
124 | | SIDEBAR | BODY | SIDEBAR |
125 | | | | |
126 | ----------------------------------------------------
127 | | FOOTER |
128 | ----------------------------------------------------
129 | ```
130 | This is actually a layout used by lots of applications. If you think about it, its just a nesting of concepts you already know `csstips.vertical`,`csstips.horizontal`, `csstips.flex`, `csstips.content`.
131 |
132 | In fact its a combination of the first example layout (`csstips.vertical`):
133 |
134 | ```
135 | ------------------------------------
136 | | HEADER |
137 | ------------------------------------
138 | | |
139 | | BODY1 |
140 | | |
141 | ------------------------------------
142 | | FOOTER |
143 | ------------------------------------
144 | ```
145 |
146 | Where the `body1` is itself a `csstips.horizontal` containing the `sidebar`s and `body`:
147 |
148 | ```
149 | -----------------------------------------------
150 | | HEADER |
151 | -----------------------------------------------
152 | | | | |
153 | | SIDEBAR | BODY | SIDEBAR |
154 | | | | |
155 | -----------------------------------------------
156 | | FOOTER |
157 | -----------------------------------------------
158 | ```
159 | Easy right! Here is a demo for you to play with:
160 |
161 | ```play
162 | const bg = (color) => ({backgroundColor:color});
163 |
164 |
165 |
166 | Header
167 |
168 |
169 |
170 | Sidebar
171 |
172 |
173 | Body
174 |
175 |
176 | Sidebar
177 |
178 |
179 |
180 | Footer
181 |
182 |
183 | ```
184 |
185 | [](TODO: # Scrolling)
186 |
187 | [](TODO: # Scrolling a sub child)
188 |
189 | [](TODO Components: We've covered enough of layout to allow you to create basic layouts quite easily)
190 |
191 | [](TODO: Overlays)
192 |
193 | [](TODO: Menu)
194 |
--------------------------------------------------------------------------------
/src/docs/intro.md:
--------------------------------------------------------------------------------
1 | Maintainable CSS is nearly impossible. But writing maintainable JavaScript is a fairly solved problem. Lets combine the two to make CSS maintainability an issue of the past.
2 |
3 | 
4 |
5 | The DOM `style` attribute is not enough to cater for things like pseudo states and media queries. We provide a simple *zero config* `style` function that gives you all the power of CSS with all the safety and maintainability of TypeScript / JavaScript.
6 |
7 | # Utilities
8 |
9 | TypeStyle core is actually **very** small (~6k gz) and you are free to use just that. However this guide and TypeStyle is designed to be approachable by both beginner and expert CSS devs. So we provide utilities that are mentioned next.
10 |
11 | # About `csx`
12 | Provided as a separate library (`npm install csx`):
13 |
14 | * helps you manage CSS properties e.g. **colors** and create typed CSS variables.
15 |
16 | # About `csstips`
17 |
18 | Provided as a separate library (`npm install csstips`). Provides utilities for pagesetup / CSS normalization along with mixins and mixin creators.
19 |
20 | * it essentially documents CSS tips that people might not be familiar with.
21 | * gives names to these CSS tips.
22 |
23 | # Installation
24 |
25 | Available easily via npm:
26 |
27 | ```
28 | npm install typestyle --save
29 | ```
30 |
31 | # Video Course
32 | We also have a free [video course based on the same content as this guide if you prefer to watch instead of reading][course].
33 |
34 | [][course]
35 |
36 | [course]:https://egghead.io/courses/maintainable-css-using-typestyle
37 |
--------------------------------------------------------------------------------
/src/docs/page.md:
--------------------------------------------------------------------------------
1 | There are very few simple things about the default layout of an HTML page that need to be setup in order to prepare it for the application development era:
2 |
3 | * Full Sized Body
4 | * Box Model
5 |
6 | ## Full Sized Body
7 | You really want the root of your page to be something that takes up all the available space on screen and provides it as a drawing canvas for children. This can be done easily:
8 |
9 | ```css
10 | html, body {
11 | height: 100%;
12 | width: 100%;
13 | padding: 0px;
14 | margin: 0px;
15 | }
16 | ```
17 |
18 | ## Box Model
19 | You really want the `width`/`height` of an element to represent the `border+padding+content`. This is shown below:
20 |
21 | 
22 |
23 | It sounds something basic but the first HTML spec got wrong. Its easy to fix though:
24 |
25 | ```css
26 | html {
27 | box-sizing: border-box;
28 | }
29 | *, *:before, *:after {
30 | box-sizing: inherit;
31 | }
32 | ```
33 |
34 | ## Root
35 | Finally with modern web frameworks you normally render to some container div. e.g. `root` in the following example:
36 |
37 | ```html
38 |
39 |
40 |
41 |
42 |
43 |
44 | ```
45 |
46 | You probably want `#root` to be the same size as the body. Easily done by making its width / height `100%`.
47 |
48 | ## `setupPage`
49 | Combine all that we've talked about and we have the following page setup.
50 |
51 | ```html
52 |
53 |
54 |
55 |
56 |
57 |
58 | ```
59 |
60 | ```ts
61 | import {setupPage} from "csstips";
62 | setupPage('#root');
63 | ```
64 |
65 | * sets up box model
66 | * sets up `html/body` size
67 | * sets up root component size
68 |
69 | Easy as :)
70 |
71 | ## `normalize`
72 | Browsers have different default styles for a few a the native tags e.g. the `template` tag *does not have `display: none` in IE but has it in all other browers. The list of such quirks is small but not something that you should bother with. This is why [normalize.css] exists. It is used by all the popular css frameworks including bootstrap. So a good idea to include in your own designs as well. Super simple with `normalize` ;)
73 |
74 | ```ts
75 | import {normalize} from "csstips";
76 | normalize();
77 |
78 | // Yay. Browser quirks ironed out
79 | ```
80 |
81 | ## Recommended page setup
82 |
83 | Hence the recommended page setup
84 |
85 | ```html
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | ```
96 |
97 | ```ts
98 | import {normalize, setupPage} from "csstips";
99 |
100 | normalize();
101 | setupPage('#root');
102 |
103 | // All your designs will now be more consistent across browsers
104 | ```
105 |
106 | Notes on some non `css` stuff in this page setup:
107 | * `` ensures that mobile browsers use their width to render the page. Otherwise mobiles render the page at desktop resolutions, forcing the user to zoom in to read text and then you get horizontal scrollbars. Its lovingly called the *responsive meta tag*.
108 | * Having the `script` after the root `div` ensures that it can be used from our JavaScript without needing something like `DOMContentLoaded`
109 |
110 | [normalize.css]:https://github.com/necolas/normalize.css
111 |
--------------------------------------------------------------------------------
/src/docs/play.md:
--------------------------------------------------------------------------------
1 | We found the JavaScript playgrounds out there missing key features for a great TypeScript experience.
2 |
3 | > ProTip: You *can* use typestyle in playgrounds as we also provide a `umd` build: e.g. https://unpkg.com/typestyle/umd/typestyle.js example http://codepen.io/basarat/pen/GNeyzX
4 |
5 | Introducing the TypeStyle playground : [https://typestyle.github.io/play/](https://typestyle.github.io/play/). It supports *full* demo development with:
6 |
7 | * JavaScript in the form of TypeScript
8 | * HTML in the form of React/JSX
9 | * CSS in the form of TypeStyle
10 |
11 | Here is the hello world:
12 |
13 | ```play
14 |
15 | Hello world
16 |
17 | ```
18 |
19 | ## Features
20 |
21 | ### Autocomplete
22 |
23 | `ctrl + space`
24 |
25 | 
26 |
27 | ### Errors
28 |
29 | We do continuous linting (TypeScript is really just the world's most powerful JavaScript linter). The first error is shown inline so you don't need to use your mouse much.
30 |
31 | 
32 |
33 | ## Sharing
34 |
35 | The url is always kept in sync with the code so you can share it around at any point you want.
36 |
37 | ## Compilation Context
38 |
39 | We put the following variables into the compilation context (and runtime) for you so that you don't need to do anything special
40 |
41 | * `typestyle`: The complete `"typestyle"` module
42 | * `style`, `keyframes`, `classes` from the `"typestyle"` module
43 | * `csstips` : The complete `"csstips"` module
44 | * `csx`: The complete `"typestyle/lib/csx"` module
45 |
46 |
47 | Additionally we have `React` in context as well as its used internally by any JSX (e.g. `` becomes `React.createElement('div')`). You can even create your own React components
48 |
49 | ```play
50 | const HelloWorld = () =>
Hello World
;
51 |
52 | ```
53 |
54 | ## Output
55 |
56 | The last JSX expression that gets evaluated in the code gets rendered to the output window. You are free to write any other TypeScript code before that if you want.
57 |
58 | ```play
59 | let message = "Hello World!";
60 |
61 | {message}
62 |
63 | ```
64 |
65 | 
66 |
67 | ## Root
68 |
69 | > We cover more of `csx` / `csstips` and the concepts of mixins and flexbox and all that jazz in other sections of the book. This is just a quick look to demonstrate the playground.
70 |
71 | The output is rendered in a container that has `position: relative`. So you can attach to it with handy dandy `csx.fillParent` e.g.
72 |
73 | ```play
74 | const bg = (backgroundColor) => ({backgroundColor});
75 |
76 |
77 | I fill the root
78 |
79 | ```
80 |
81 | And if you want to play with flexbox just use `csstips.vertical` (or `csstips.horizontal`) wherever it makes sense e.g. here we show two flex children:
82 |
83 | ```play
84 | const bg = (backgroundColor) => ({backgroundColor});
85 |
86 |
87 |
88 |
89 |
90 | ```
91 |
92 | And another with three children showing a common header / body / footer layout:
93 |
94 | ```play
95 | const bg = (backgroundColor) => ({backgroundColor});
96 |
97 |
98 |
99 | Header
100 |
101 |
102 | Body
103 |
104 |
105 | Footer
106 |
107 |
108 | ```
109 |
--------------------------------------------------------------------------------
/src/docs/raw.md:
--------------------------------------------------------------------------------
1 | * [cssRule](/#/raw/-cssrule-)
2 | * [cssRaw](/#/raw/-cssraw-)
3 | * [Advantages of these functions over loaders](/#/raw/advantages-of-these-functions-over-loaders)
4 |
5 | We understand that just classes are not sufficient for a full CSS in JS story as the generated dom is not always coming from your library, or in your control.
6 |
7 | For those scenarios we have two functions
8 |
9 | ## `cssRule`
10 |
11 | You can even use any raw CSS selector as well using `cssRule` e.g.
12 |
13 | * To setup a application style layout:
14 |
15 | ```ts
16 | /** Use full window size for application */
17 | cssRule('html, body', {
18 | height: '100%',
19 | width: '100%',
20 | padding: 0,
21 | margin: 0
22 | });
23 | ```
24 |
25 | * Page level media queries:
26 |
27 | ```ts
28 | /** Save ink with a white background */
29 | cssRule('@media print', {
30 | body: {
31 | background: 'white'
32 | }
33 | });
34 | ```
35 |
36 |
37 | ## `fontFace`
38 |
39 | Specifying fonts has a special function for readability:
40 |
41 | ```ts
42 | import { fontFace } from 'typestyle';
43 |
44 | fontFace({
45 | fontFamily: 'Roboto',
46 | fontStyle: 'normal',
47 | fontWeight: 400,
48 | src: /* url here */'',
49 | unicodeRange: 'U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F'
50 | });
51 | ```
52 |
53 | * Fonts can also be specified using the above ```cssRule``` using the @font-face rule.
54 |
55 | ```ts
56 | cssRule('@font-face', {
57 | fontFamily: '"Bitstream Vera Serif Bold"',
58 | src: 'url("https://mdn.mozillademos.org/files/2468/VeraSeBd.ttf")'
59 | });
60 | ```
61 |
62 | ## `cssRaw`
63 |
64 | Sometimes someone just hands you are raw CSS file and you can't be bothered to make it into objects. An excellent use case is using something like `normalize.css`.
65 |
66 | ```ts
67 | import {cssRaw} from "typestyle"
68 |
69 | /** Sample rule from normalize.css */
70 | cssRaw(`
71 | /**
72 | * Correct the font size and margin on h1 elements within section and
73 | * article contexts in Chrome, Firefox, and Safari.
74 | */
75 | h1 {
76 | font-size: 2em;
77 | margin: 0.67em 0;
78 | }
79 | `)
80 | ```
81 |
82 | > Protip `csstips.normalize()` uses this function internally to actually add `normalize.css`. More on this later.
83 |
84 | ## Advantages of these functions over loaders
85 |
86 | * Works seemlessly in a nodejs enviroment (example use cases are nodejs testing / server side rendering) whereas `require('./someCss.css')` does not without additional setup.
87 | * You still get to use JS and share variables with JS (using template strings!).
88 | * With `cssRule` you can also use all our (and your!) fancy mixins.
89 |
90 | Great. That covers the key TypeStyle API surface.
--------------------------------------------------------------------------------
/src/docs/reviews.md:
--------------------------------------------------------------------------------
1 |
2 | * [I haven't been this giggly-happy about a library in a long time!!!](https://twitter.com/andrestaltz/status/788665551325454337)
3 | * [A type-safe CSS-in-JS library like no other - TypeStyle](https://twitter.com/areknawo/status/1135643283688964096) / [Blog post](https://areknawo.com/a-different-approach-to-css-in-js/)
4 | * [Rad idea!](https://twitter.com/iammerrick/status/788784672314576897)
5 | * [What a fantastic #css resource](https://twitter.com/zbrianw/status/792177209490313217)
6 | * [This is the CSS framework I have wanted to exist for the past 5 years.](https://twitter.com/jeffwhelpley/status/802275885353054208)
7 | * [Relief! CSS w/ Type Safety!](https://twitter.com/wwwalkerrun/status/802329604471959552)
8 | * [This is seriously cool stuff.](https://twitter.com/jonbrennecke/status/802351164247265280)
9 | * [YES! That's freaking awesome!](https://twitter.com/brechtbilliet/status/802385818295746560)
10 | * [This is an example of both types and linting being enforced by the same systems as the rest of your code](https://twitter.com/rauchg/status/802706919823581185)
11 | * [Nice approach to have your #css in order and using #typescript](https://twitter.com/chris_noring/status/802824657401475073)
12 | * [Try out #TypeStyle which uses #Typescript to generate your styles!](https://twitter.com/designpuddle/status/802658082924937216)
13 | * [The IDE abilities of TypeScript and TypeStyle are appealing for a larger component based design system](https://twitter.com/twnsndco/status/804081260633214977)
14 | * [I just discovered typestyle. It's awesome. 👍](https://twitter.com/arnarbirgisson/status/805805142289293314)
15 | * [The future of CSS for TypeScript powered applications #TypeStyle](https://twitter.com/piotrekwitek/status/817655604206596096)
16 | * [I really love #TypeStyle. So agnostic, so small, so out of your way. Css in JS that just works.](https://twitter.com/nickbalestra/status/818393513847037953)
17 | * [#typescript + #reactjs + #typestyle is just a thing of beauty, it's like developer ambrosia](https://twitter.com/deis/status/823404962323505152)
18 | * [I just came across TypeStyle ... I can't praise the library enough! Ultimate typesafe CSS solution](https://twitter.com/erikcupal/status/823700902578163712)
19 | * [Holy cow! TypeStyle combines #TypeScript with #CSS for maintainable styles! 😍](https://twitter.com/timo_ernst/status/823262762596007937)
20 | * [Started building a UI library for our platform @CyclePlatform with #typestyle. Absolute pleasure so far, thanks for the great work.](https://twitter.com/alexmattoni/status/839961368375590912)
21 | * [TypeStyle by @basarat is a fantastic #CSS in #javascript lib. Effectively CSS modules wrapped in JS/TS and excellent DX.](https://twitter.com/SteveALee/status/858255868139319296)
22 | * [TypeStyle by @notoriousb1t and @basarat is the perfect CSS-in-TS library. Small, elegant and strongly typed ;)](https://twitter.com/ale_burato/status/899165879849684992)
23 | * [TypeStyle looks like the typed CSS-in-JS solution I was looking for. If you can spare 30 minutes, do yourself a favor and watch the videos. Great work!](https://twitter.com/frontsideair/status/1019491595224276992)
24 | * [Last time I used CSS modules I got frustrated by the lack of type safety - lately I've been using (and loving) TypeStyle](https://twitter.com/muelvenables/status/1119369238286725120)
25 |
26 | * [Add yours 🌹!](https://twitter.com/intent/tweet?text=Super%20simple%20maintainable%20%23CSS%20with%20%23TypeStyle%3A%20https%3A%2F%2Ftypestyle.github.io%0A%0A%23JavaScript%20%23TypeScript%20%40basarat%20%F0%9F%8C%B9)
27 |
28 | # Samples
29 |
30 | TypeStyle is simply just a `style` function with a handful of *simple* utilities that we cover nicely in the rest of the book. So don't need another hello world here. That said, the best samples are real world usages. Here are a few:
31 |
32 | * [http://matrixmultiplication.xyz/](http://matrixmultiplication.xyz/) Built with TypeStyle / CycleJS / TypeScript
33 | * [This website, with docs](https://github.com/typestyle/typestyle.github.io) as well as [the playground](https://typestyle.github.io/play) are all built 100% with typestyle.
34 | * [alm.tools](http://alm.tools) and IDE designed to provide the best developer experience for TypeScript.
35 | * [https://wmaurer.github.io/cyclejs-fractals/](https://wmaurer.github.io/cyclejs-fractals) Built with TypeStyle / CycleJS / TypeScript
36 |
--------------------------------------------------------------------------------
/src/docs/server.md:
--------------------------------------------------------------------------------
1 | Sever side rendering + static page generations is supported with a super easy function. It may not be a feature you need so you can safely skip reading this section.
2 |
3 | ## `getStyles`
4 | It allows you to get the styles as CSS which you can return as a part of your server response. e.g.
5 |
6 | ```ts
7 | /** Import */
8 | import {style, getStyles} from "typestyle";
9 |
10 | /** convert a style object to a CSS class name */
11 | const className = style({color: 'red'});
12 |
13 | /** Render to CSS style tag */
14 | const styleTag = ``
15 | /** ^ send this as a part of your HTML response */
16 | ```
17 |
18 | Here is a more *fancy* example function that uses React:
19 |
20 | ```ts
21 | export const renderPage = ({ html, css }: { html: string, css: string }) => `
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
${html}
32 |
33 |
34 |
35 | `;
36 |
37 | import {getStyles} from "typestyle";
38 | import {App} from "./yourApp";
39 |
40 | const response = renderPage({
41 | html: ReactDOMServer.renderToString(),
42 | css: getStyles()
43 | });
44 |
45 | /** ^ send this as your HTML response */
46 | ```
47 |
48 | Then in the frontend you simply use the same style tag after rendering the html:
49 |
50 | ```ts
51 | import {setStylesTarget} from "typestyle";
52 | ReactDOM.render(, document.getElementById('root'));
53 | setStylesTarget(document.getElementById('styles-target'));
54 | ```
--------------------------------------------------------------------------------
/src/docs/utilities.md:
--------------------------------------------------------------------------------
1 | TypeStyle (csx) includes utilities that make using units and css functions feel natural and flow in JavaScript.
2 |
3 | > Values from these `csx` utilities need to be `toString`ed before being used in TypeStyle or any other library. This means that they can be used with or without TypeStyle 🌹
4 |
5 | ## Unit utilities
6 |
7 | ### em(value: number): string
8 | Returns the number followed by the em unit
9 |
10 | ```typescript
11 | import { em } from 'csx';
12 |
13 | // outputs '0.5em'
14 | const width = em(.5);
15 | ```
16 |
17 | ### percent(value: number): string
18 | Returns the number followed by the % unit
19 |
20 | ```typescript
21 | import { percent } from 'csx';
22 |
23 | // outputs '50%'
24 | const width = percent(50);
25 | ```
26 |
27 | ### px(value: number): string
28 | Returns the number followed by the px unit
29 |
30 | ```typescript
31 | import { px } from 'csx';
32 |
33 | // outputs '42px'
34 | const width = px(42);
35 | ```
36 |
37 | ### rad(value: number): string
38 | Returns the number followed by the rad unit
39 |
40 | ```typescript
41 | import { rad } from 'csx';
42 |
43 | // outputs '20rad'
44 | const rotation = rad(20);
45 | ```
46 |
47 | ### rem(value: number): string
48 | Returns the number followed by the rem unit
49 |
50 | ```typescript
51 | import { rem } from 'csx';
52 |
53 | // outputs '1.5rem'
54 | const width = rem(1.5);
55 | ```
56 |
57 | ### viewHeight(value: number): string
58 | Returns the number followed by the vh (view height) unit
59 |
60 | ```typescript
61 | import { viewHeight } from 'csx';
62 |
63 | // outputs '25vh'
64 | const height = viewHeight(100/4);
65 | ```
66 |
67 | ### viewWidth(value: number): string
68 | Returns the number followed by the vw (view width) unit
69 |
70 | ```typescript
71 | import { viewWidth } from 'csx';
72 |
73 | // outputs '85vw'
74 | const width = viewWidth(85);
75 | ```
76 |
77 | ### turn(value: number): string
78 | Returns the number followed by the turn unit
79 |
80 | ```typescript
81 | import { turn } from 'csx';
82 |
83 | // outputs '1turn'
84 | const rotation = turn(1);
85 | ```
86 |
87 |
88 | ## Function utilities
89 |
90 | ### important(value: string): string
91 |
92 | Returns the string followed by !important
93 |
94 | ```typescript
95 | import { important } from 'csx';
96 |
97 | // outputs 'red !important'
98 | const content = important('red');
99 | ```
100 |
101 | ### quote(value: string): string
102 |
103 | Returns the string wrapped by quote(). Single quotes in the value are escaped
104 |
105 | ```typescript
106 | import { quote } from 'csx';
107 |
108 | // outputs "quote('&')"
109 | const content = quote('&');
110 |
111 | // outputs "quote('It\'s the cat\'s pajamas')"
112 | const content1 = quote("It's the cat's pajamas");
113 | ```
114 |
115 | ### url(value: string): string
116 |
117 | Returns the url wrapped by url()
118 |
119 | ```typescript
120 | import { url } from 'csx';
121 |
122 | // outputs "url(images/my-background.png)"
123 | const imageLocation = url('images/my-background.png');
124 | ```
--------------------------------------------------------------------------------
/src/docs/why.md:
--------------------------------------------------------------------------------
1 | The biggest reason is developer happiness from not having to manage too many files that are intrinsically linked to each other and not having to use different tools to get the *single* job done 🌹.
2 |
3 | But of course, there are lots of other reasons as well and we present a few below.
4 |
5 | # Comparison to other options
6 |
7 | There are a lot of other CSS in JS frameworks out there. In the past we used and experimented with quite a few. Some quick reasons why we wrote our own.
8 |
9 | * We are focused on Autocomplete / *Compile* time error analysis
10 | * None of them had this out of the box.
11 | * Not all APIs are statically analyzable e.g. if the API is powered by template strings, the CSS portion is essentially not analyzed at all.
12 | * Some forced you to use a custom AST transforms
13 | * Would be fine if custom ASTs came with IDE support + static analysis. It doesn't.
14 | * Many others are framework specific e.g. React specific
15 | * Some force you to rethink / wrap your component. Didn't want that.
16 | * They make upgrading your frontend framework harder as you need for them to update their wrapper first.
17 | * Many others try to solve problem with JS events instead of generating CSS.
18 | * This can result in issues when a JS event is absent, e.g. [a stuck `:hover`](https://goo.gl/e5tUyt)
19 | * Can be significantly slower in real world usage as CSS does a faster job of changing quick styles than events.
20 | * The number of issues reported on libraries that use JS events is generally too high for comfort.
21 | * Generally framework specific and that has problems we've mentioned before.
22 | * They also tend to change `style` instead of writing CSS which makes using devtools with immediate feedback (e.g. chrome dev tools) harder.
23 | * CSS Modules : Not CSS in JS. Just solves namespacing.
24 | * Most the other CSS managment problems still exist. We are essentially CSS modules, if CSS modules were written in JS.
25 | * Super small core size (~6k gz).
26 | * We are just putting a type system + encapsulation / maintainability (no globals) on CSS.
27 |
28 | Of course we would not exist without their previous and continued hard work and public idea exchange 🌹
29 |
30 | ## Concept: Hashed className
31 |
32 | CSS class names (e.g. `.btn`) suffer from global conflicts.
33 |
34 | * This makes integrating with third party libraries hard. Each library must follow a convention to prevent mistakes e.g. `bootstrap-btn` but *most libraries* don't and camp on global names.
35 | * This makes even writing maintainable CSS *in your project* hard and you need to treat it as *global* e.g. if you want to create a class for buttons in two components e.g. date picker and a file dropzone you must have `.mine-datepicker-button` and `.mine-dropzone-button` to prevent mistaken conflicts. With JS/TS you would probably have seperate `.js` files (e.g. `datePicker.js` and `dropzone.js`) and each can have a local variable `buttonClass` without any conflicts. You don't even need to export these to the outside world.
36 |
37 | However due to limitations of CSS we still need to generate a CSS file to allow you to use features like hover states and media queries. Hence we generate a className based on the content for you:
38 |
39 | ```play
40 | import {style} from 'typestyle';
41 |
42 | const myColorClass = style({color:'red'});
43 |
44 |
The generated class name: {myColorClass}
;
45 | ```
46 |
47 | This gives you:
48 |
49 | * Isolation: No globals!
50 |
51 | ## Concept: Dead CSS
52 |
53 | Determining the impact of a CSS className on your codebase is one of the hardest problems facing frontend maintainability.
54 |
55 | Having the styles managed in JS (especially with TypeScript) gives you the following immediate gains:
56 |
57 | * You can immediately see all the places where a class is used (e.g find references in TypeScript). This also gives you the *impact* footprint of a CSS class.
58 | * Refactor class names easily, especially true with TypeScript (e.g. from `fooClass` to `barClass`. You no longer need to be afraid to touch your CSS class names).
59 | * Remove CSS classes that are no longer used easily (e.g. switch on `noUnusedLocals` in TypeScript).
60 | * Delete a TS file containing CSS classNames. If it's used, you get a nice compiler error which you can fix easily (same way you fix / remove unused JS code). Next go out and party 🎉.
61 | * Based on how *all module loaders work* (including webpack/tsify/rollup) if a file isn't *required*, it doesn't become a part of the bundle. So their CSS also goes away *automatically*.
62 | * With fancy tree shaking module loaders (like rollup/webpack2) if a variable isn't used, it's removed from the bundle. So even without `noUnusedLocals`, the CSS bound to these variables (e.g. `const fooUnused = style({color:'red'})`) goes away.
63 |
64 | ## Vendor Prefixing
65 |
66 | Note: We don't do *automatic* vendor prefixing for a few reasons:
67 |
68 | * Code bloat, runtime performance, you might want more control (we don't make choices that you might need to undo).
69 | * Vendor prefixing has no future: https://webkit.org/blog/6131/updating-our-prefixing-policy/
70 |
71 | > Protip: Big fan of flexbox? Use `csstips` as it provides the necessary vendor prefixes so you don't need to worry about them.
72 |
73 | ## More boring reasons
74 |
75 | Beyond that here is a boring list of additional reasons to use TypeStyle.
76 |
77 | * No context switching your brain (think it's worth mentioning again).
78 | * Built in dependency system same as the rest of your JS. No special code for CSS needed.
79 | * Ship CSS in the same channel that you ship JS, with no special configuration being required by your library user.
80 | * Minification (Minify JS with existing tools). The CSS we generate is already nearly whitespace free.
81 | * Shared constants and reusable styles (Using variables and objects)
82 | * Extensible (Just use JavaScript with all its power)
83 | * Your components are still free to have class names that you can give to external people to further style your stuff (better still take `className` as a property and let them use *typestyle* too!).
84 | * Develop components alongside the style (No more hunting CSS files for estranged `ul > li > a`)
85 | * Create isomorphic applications (easy export to a CSS file is supported)
86 | * All the power of CSS without compromise e.g. pseudo states (e.g. `&:hover`)
87 | * Better than CSS, management of media queries i.e. *nested class driven* media quries
88 | * Fallback CSS properties using arrays (`{ backgroundColor: ['red', 'linear-gradient(to right, red 0%, blue 100%)'] }`)
89 | * Super small core size (~1k).
90 | * Extremely small and powerful API that works with any ecosystem.
91 | * Provides great TypeScript developer autocomplete experience.
92 | * No custom AST transform or module loader support needed.
93 | * Works with any framework (react, angular2, cyclejs, whatever, doesn't matter).
94 | * Zero config. Just use.
95 |
96 | > Note: Many of these are truly the advantages of using FreeStyle. The additional features by typestyle are *autoinjection*, *`types`* (for autocomplete and errors), `csx` (CSSFunctions and Typed CSS value creators) and *csstips* (a great set of CSS mixins / page setup helpers to give a smooth learning curve for even new CSS devs).
97 |
--------------------------------------------------------------------------------
/src/play.tsx:
--------------------------------------------------------------------------------
1 | /** Setup es6 */
2 | import 'babel-polyfill';
3 |
4 | import { setupPage, normalize } from 'csstips';
5 | import * as csstips from 'csstips';
6 | import { style, cssRule, media } from 'typestyle';
7 | normalize();
8 | setupPage('#root');
9 |
10 | /**
11 | * Clear default margins from all things
12 | * I wouldn't do this in a production site. But doing it to make teaching easier
13 | */
14 | cssRule('h1,h2,h3,h4,h5,h6,h7,h8,p', {
15 | margin: '0px'
16 | });
17 |
18 | import * as React from 'react';
19 | import * as ReactDOM from 'react-dom';
20 | import * as cp from './components';
21 | import { CodeEditor } from './play/codeEditor/codeEditor';
22 | import { observable, action, computed } from 'mobx';
23 | import { observer } from 'mobx-react';
24 | import { debounce } from './utils';
25 | import * as ts from 'byots';
26 | import * as ps from './play/projectService';
27 | import { demoState } from './play/playState';
28 | import { CodeOutput } from './play/codeOutput/codeOutput';
29 | import * as gls from './components/gls';
30 |
31 | @observer
32 | export class HeaderSmall extends React.Component<{}, {}> {
33 | render() {
34 | return (
35 |