Componentize tabs.

This commit is contained in:
Matt Swensen 2018-11-05 20:57:51 -07:00
parent 036d07bc4c
commit b89661711f
No known key found for this signature in database
GPG Key ID: 3F9E482BFC526F35
8 changed files with 155 additions and 89 deletions

@ -4,8 +4,7 @@ import { UrlStateProvider } from './UrlState';
import ColorState from './ColorState';
import ColorSetInputs from './ColorSetInputs';
import CodePreview from './CodePreview';
import TerminalPreview from './TerminalPreview';
import TextPreviews from './TextPreviews';
export default class App extends PureComponent {
render() {
@ -36,8 +35,7 @@ export default class App extends PureComponent {
<h2 className={ styles.h2 } style={{ color: getColor('shade7')}}>1. Define colors</h2>
<ColorSetInputs />
<h2 className={ styles.h2 } style={{ color: getColor('shade7')}}>2. Preview</h2>
<CodePreview />
<TerminalPreview />
<TextPreviews />
</div>
</div>
) }

@ -5,6 +5,7 @@ import ColorState from './ColorState';
import ColorInput from './ColorInput';
import Checkbox from './Checkbox';
import CalculateIntermediaryShadesState from './CalculateIntermediaryShadesState';
import Tabs from './Tabs';
export default class ColorSetInputs extends PureComponent {
render() {
@ -13,70 +14,66 @@ export default class ColorSetInputs extends PureComponent {
{ ({ getValueOrFallback, mergeState }) => {
const isDark = getValueOrFallback([['activeColorSet']]) === 'dark';
return (
<ColorState>
{ ({ getColor }) => {
const getTabStyle = active => ({
backgroundColor: active ? getColor('shade0') : getColor('shade2', 'shade0'),
color: getColor('shade7'),
borderTopColor: getColor('shade7'),
borderRightColor: getColor('shade7'),
borderBottomColor: active ? getColor('shade0') : getColor('shade7'),
borderLeftColor: getColor('shade7'),
});
return (
<>
<div className={ styles.tabContainer }>
<button
style={ getTabStyle(isDark) }
onClick={ () => mergeState({ activeColorSet: 'dark' }) }
>Dark Variant</button>
<button
style={ getTabStyle(!isDark) }
onClick={ () => mergeState({ activeColorSet: 'light' }) }
>Light Variant</button>
</div>
<div className={ styles.inputContainer } style={{ borderColor: getColor('shade7') }}>
<ColorInput className={ styles.shade0 } colorKey="shade0" help="background color" />
<CalculateIntermediaryShadesState>
{ ({ getValue, setValue }) => (
<>
{ !getValue() && (
<>
<ColorInput className={ styles.shade1 } colorKey="shade1" help="UI" />
<ColorInput className={ styles.shade2 } colorKey="shade2" help="UI, text selection" />
<ColorInput className={ styles.shade3 } colorKey="shade3" help="UI, code comments" />
<ColorInput className={ styles.shade4 } colorKey="shade4" help="UI" />
<ColorInput className={ styles.shade5 } colorKey="shade5" help="UI" />
<ColorInput className={ styles.shade6 } colorKey="shade6" help="foreground text" />
</>
) }
<ColorInput
className={ [styles.shade7, getValue() ? styles.collapsed : ''].join(' ') }
colorKey="shade7"
help="foreground text"
/>
<Checkbox
className={ styles.checkbox }
label="calculate intermediary shades"
value={ getValue() }
onChange={ setValue }
/>
</>
) }
</CalculateIntermediaryShadesState>
<ColorInput className={ styles.accent0 } colorKey="accent0" help="error, vcs deletion" />
<ColorInput className={ styles.accent1 } colorKey="accent1" help="syntax" />
<ColorInput className={ styles.accent2 } colorKey="accent2" help="warning, vcs modification" />
<ColorInput className={ styles.accent3 } colorKey="accent3" help="success, vcs addition" />
<ColorInput className={ styles.accent4 } colorKey="accent4" help="syntax" />
<ColorInput className={ styles.accent5 } colorKey="accent5" help="syntax" />
<ColorInput className={ styles.accent6 } colorKey="accent6" help="syntax, caret/cursor" />
<ColorInput className={ styles.accent7 } colorKey="accent7" help="syntax, special" />
</div>
</>
);
} }
</ColorState>
<Tabs>
{ ({ tabClassName, getTabStyle, contentClassName, contentStyle }) => (
<ColorState>
{ ({ getColor }) => (
<>
<div>
<button
className={ tabClassName }
style={ getTabStyle(isDark) }
onClick={ () => mergeState({ activeColorSet: 'dark' }) }
>Dark Variant</button>
<button
className={ tabClassName }
style={ getTabStyle(!isDark) }
onClick={ () => mergeState({ activeColorSet: 'light' }) }
>Light Variant</button>
</div>
<div className={ `${styles.inputContainer} ${contentClassName}` } style={ contentStyle }>
<ColorInput className={ styles.shade0 } colorKey="shade0" help="background color" />
<CalculateIntermediaryShadesState>
{ ({ getValue, setValue }) => (
<>
{ !getValue() && (
<>
<ColorInput className={ styles.shade1 } colorKey="shade1" help="UI" />
<ColorInput className={ styles.shade2 } colorKey="shade2" help="UI, text selection" />
<ColorInput className={ styles.shade3 } colorKey="shade3" help="UI, code comments" />
<ColorInput className={ styles.shade4 } colorKey="shade4" help="UI" />
<ColorInput className={ styles.shade5 } colorKey="shade5" help="UI" />
<ColorInput className={ styles.shade6 } colorKey="shade6" help="foreground text" />
</>
) }
<ColorInput
className={ [styles.shade7, getValue() ? styles.collapsed : ''].join(' ') }
colorKey="shade7"
help="foreground text"
/>
<Checkbox
className={ styles.checkbox }
label="calculate intermediary shades"
value={ getValue() }
onChange={ setValue }
/>
</>
) }
</CalculateIntermediaryShadesState>
<ColorInput className={ styles.accent0 } colorKey="accent0" help="error, vcs deletion" />
<ColorInput className={ styles.accent1 } colorKey="accent1" help="syntax" />
<ColorInput className={ styles.accent2 } colorKey="accent2" help="warning, vcs modification" />
<ColorInput className={ styles.accent3 } colorKey="accent3" help="success, vcs addition" />
<ColorInput className={ styles.accent4 } colorKey="accent4" help="syntax" />
<ColorInput className={ styles.accent5 } colorKey="accent5" help="syntax" />
<ColorInput className={ styles.accent6 } colorKey="accent6" help="syntax, caret/cursor" />
<ColorInput className={ styles.accent7 } colorKey="accent7" help="syntax, special" />
</div>
</>
) }
</ColorState>
) }
</Tabs>
);
} }
</UrlStateConsumer>

@ -1,25 +1,5 @@
.tabContainer button {
font-size: var(--size-regular);
font-family: 'Fira Code', monospace;
padding: var(--size-small-4) var(--size-small-1);
border-width: var(--border-size);
border-style: solid;
border-top-left-radius: var(--border-radius-size);
border-top-right-radius: var(--border-radius-size);
}
.tabContainer button + button {
margin-left: calc(var(--border-size) * -1);
}
.inputContainer {
padding: var(--size-large-1);
border-width: var(--border-size);
border-style: solid;
margin-top: calc(var(--border-size) * -1);
border-top-right-radius: var(--border-radius-size);
border-bottom-right-radius: var(--border-radius-size);
border-bottom-left-radius: var(--border-radius-size);
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: var(--size-large-1);

25
web/src/Tabs.js Normal file

@ -0,0 +1,25 @@
import React, { PureComponent } from 'react';
import ColorState from './ColorState';
import styles from './Tabs.module.css';
export default class Tabs extends PureComponent {
render() {
return (
<ColorState>
{ ({ getColor }) => this.props.children({
tabClassName: styles.tab,
getTabStyle: active => ({
backgroundColor: active ? getColor('shade0') : getColor('shade2', 'shade0'),
color: getColor('shade7'),
borderTopColor: getColor('shade7'),
borderRightColor: getColor('shade7'),
borderBottomColor: active ? getColor('shade0') : getColor('shade7'),
borderLeftColor: getColor('shade7'),
}),
contentClassName: styles.tabContent,
contentStyle: { borderColor: getColor('shade7') },
}) }
</ColorState>
);
}
}

22
web/src/Tabs.module.css Normal file

@ -0,0 +1,22 @@
.tab {
font-size: var(--size-regular);
font-family: 'Fira Code', monospace;
padding: var(--size-small-4) var(--size-small-1);
border-width: var(--border-size);
border-style: solid;
border-top-left-radius: var(--border-radius-size);
border-top-right-radius: var(--border-radius-size);
}
.tab + .tab {
margin-left: calc(var(--border-size) * -1);
}
.tabContent {
border-width: var(--border-size);
border-style: solid;
margin-top: calc(var(--border-size) * -1);
border-top-right-radius: var(--border-radius-size);
border-bottom-right-radius: var(--border-radius-size);
border-bottom-left-radius: var(--border-radius-size);
}

41
web/src/TextPreviews.js Normal file

@ -0,0 +1,41 @@
import React, { PureComponent } from 'react';
import CodePreview from './CodePreview';
import TerminalPreview from './TerminalPreview';
import Tabs from './Tabs';
import styles from './TextPreviews.module.css';
export default class TextPreviews extends PureComponent {
state = { activePreview: 'code' };
render() {
return (
<Tabs>
{ ({ tabClassName, getTabStyle, contentClassName, contentStyle }) => (
<>
<div>
<button
className={ tabClassName }
style={ getTabStyle(this.state.activePreview === 'code') }
onClick={ () => this.setState({ activePreview: 'code' }) }
>Code</button>
<button
className={ tabClassName }
style={ getTabStyle(this.state.activePreview === 'terminal') }
onClick={ () => this.setState({ activePreview: 'terminal' }) }
>Terminal</button>
</div>
<div className={ `${styles.previewContainer} ${contentClassName}` } style={ contentStyle }>
{ this.state.activePreview === 'code' ? (
<CodePreview />
) : null }
{ this.state.activePreview === 'terminal' ? (
<TerminalPreview />
) : null }
</div>
</>
) }
</Tabs>
);
}
}

@ -0,0 +1,3 @@
.previewContainer {
padding: var(--size-large-1);
}

@ -51,7 +51,7 @@ const fallbackState = {
calculateIntermediaryShades: {
dark: true,
light: true,
}
},
};
export class UrlStateProvider extends Component {