Skip to content

Commit

Permalink
feat: add basic CssVars implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Feb 13, 2018
1 parent cb88c75 commit b2bd30b
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 8 deletions.
79 changes: 71 additions & 8 deletions src/CssVars/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,74 @@
import {Component} from 'react';
import {Provider, Consumer} from '../context';
import {h} from '../util';
import renderProp from '../util/renderProp';

const vars = {
color: 'red'
};
let idCnt = 0;

// export class CssVarsProvider extends Component<any, any> {
// render () {
// return this.props.children;
// }
// }
const supportsCssVariables = typeof window === 'object' && (window as any).CSS && CSS.supports && CSS.supports('--a', '0');

export type TVars = {[name: string]: string};

export interface ICssVarsProviderProps {
ns?: string;
prefix?: string;
vars: TVars;
}

export interface ICssVarsProviderState {
}

export class CssVarsProvider extends Component<ICssVarsProviderProps, ICssVarsProviderState> {
vars: TVars = {};

constructor (props, context) {
super(props, context);

this.updateVars(props.vars);
}

updateVars (vars: TVars) {
if (supportsCssVariables) {
const {prefix = ''} = this.props;
const {style} = document.documentElement;

for (const name in vars) {
const id = (idCnt++).toString(36);
const varName = `---${prefix}${id}`;

this.vars[name] = `var(${varName})`;
style.setProperty(varName, String(vars[name]));
}
} else {
this.vars = vars;
}
}

render () {
return h(Provider, {
name: 'css/' + this.props.ns,
value: this.vars
},
this.props.children
);
}
}

export interface ICssVarsProps {
children?: any;
render?: any;
component?: any;
comp?: any;
ns?: string;
}

export interface ICssVarsState {
}

export class CssVars extends Component<ICssVarsProps, ICssVarsState> {
render () {
return h(Consumer, {name: 'css/' + this.props.ns}, (vars) => {
return renderProp(this.props, vars);
});
}
}
50 changes: 50 additions & 0 deletions src/cssvars/__story__/Example1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {Component, createElement as h} from 'react';
import {CssVarsProvider, CssVars} from '..';

const Print = (props) => <pre style={{fontFamily: 'monospace'}}>{JSON.stringify(props, null, 4)}</pre>;

export class Example1 extends Component<any, any> {
el;
vars;

ref = (el) => {
this.el = el;
};

componentDidMount () {
this.applyCssVars();
}

componentDidUpdate () {
this.applyCssVars();
}

applyCssVars () {
if (this.el && this.vars) {
for (const name in this.vars) {
console.log('name, this.vars[name]', name, this.vars[name]);
this.el.style.setProperty(name, this.vars[name]);
}
}
}

render () {
return (
<CssVarsProvider vars={{
color: 'tomato',
border: '1px solid tomato'
}}>
<CssVars>{(vars) => {
this.vars = vars;

return (
<div>
<Print {...vars} />
<button ref={this.ref}>Click me!</button>
</div>
);
}}</CssVars>
</CssVarsProvider>
);
}
}
39 changes: 39 additions & 0 deletions src/cssvars/__story__/story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {createElement as h} from 'react';
import {storiesOf} from '@storybook/react';
import {action} from '@storybook/addon-actions';
import {linkTo} from '@storybook/addon-links';
import ShowDocs from '../../../.storybook/ShowDocs'
import {CssVarsProvider, CssVars} from '..';
import {Example1} from './Example1';

const Print = (props) => <pre style={{fontFamily: 'monospace'}}>{JSON.stringify(props, null, 4)}</pre>;

storiesOf('Context/CSS Variables', module)
// .add('Documentation', () => h(ShowDocs, {md: require('../../../docs/en/FocusSensor.md')}))
.add('Basic example', () => <Example1 />)
.add('Inline style', () =>
<CssVarsProvider vars={{
color: 'tomato',
border: '1px solid tomato'
}}>
<CssVars>{(vars) =>
<div>
<Print {...vars} />
<button style={vars}>Click me!</button>
</div>
}</CssVars>
</CssVarsProvider>
)
.add('With namespace', () =>
<CssVarsProvider ns='namespace' prefix='prefix-' vars={{
color: 'tomato',
border: '1px solid tomato'
}}>
<CssVars ns='namespace'>{(vars) =>
<div>
<Print {...vars} />
<button style={vars}>Click me!</button>
</div>
}</CssVars>
</CssVarsProvider>
)

0 comments on commit b2bd30b

Please sign in to comment.