Skip to content

Commit

Permalink
feat: styled components for web
Browse files Browse the repository at this point in the history
  • Loading branch information
mauroerta committed May 13, 2021
1 parent c3771c6 commit e5dee4c
Show file tree
Hide file tree
Showing 19 changed files with 285 additions and 115 deletions.
65 changes: 33 additions & 32 deletions apps/web-sandbox/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
import { useState, useCallback, FC } from 'react';
import styled, { ThemeProvider } from '@morfeo/styled-components-web';
import { theme, Component, Components } from '@morfeo/web';
import { useTheme, useStyles } from '@morfeo/hooks';
import { useState, useCallback } from 'react';
import { ThemeProvider } from '@morfeo/styled-components-web';
import { theme, Component, Variant } from '@morfeo/web';
import { useStyles } from '@morfeo/hooks';
import { darkTheme, lightTheme } from './theme';

theme.set(lightTheme as any);

const Button = styled.Button({});

const StyledProvider: FC = ({ children }) => {
const currentTheme = useTheme();

return <ThemeProvider theme={currentTheme}>{children}</ThemeProvider>;
};
import { Box, Button, Typography } from './components';

function getStyle<C extends Component = Component>(
component: C,
variant?: keyof Components['Button']['variants'],
variant?: Variant<C>,
) {
const { style, variants } = theme.getValue('components', component);

// @ts-ignore
const { style, tag, props, variants } = theme.getValue(
'components',
component,
);
// @ts-ignore
if (variant && variants && variants[variant]) {
// @ts-ignore
return JSON.stringify(variants[variant], undefined, 2);
}

return JSON.stringify(style, undefined, 2);
return JSON.stringify({ style, tag, props }, undefined, 2);
}

function App() {
Expand Down Expand Up @@ -54,29 +50,34 @@ function App() {
height: '100%' as any,
},
codeStyle: {
color: 'primary',
display: 'block',
py: 's',
},
});

return (
<StyledProvider>
<div style={containerStyle}>
<div style={blockStyle}>
<ThemeProvider>
<Box style={containerStyle}>
<Box style={blockStyle}>
<Button onClick={onClick}>{light ? `🌙` : `☀️`}</Button>
<pre style={codeStyle}>{getStyle('Button')}</pre>
</div>
<div style={blockStyle}>
<Typography variant="code" style={codeStyle}>
{getStyle('Button')}
</Typography>
</Box>
<Box style={blockStyle}>
<Button variant="primary">Primary variant</Button>
<pre style={codeStyle}>{getStyle('Button', 'primary')}</pre>
</div>
<div style={blockStyle}>
<Typography variant="code" style={codeStyle}>
{getStyle('Button', 'primary')}
</Typography>
</Box>
<Box style={blockStyle}>
<Button variant="round">Round variant</Button>
<pre style={codeStyle}>{getStyle('Button', 'round')}</pre>
</div>
</div>
</StyledProvider>
<Typography variant="code" style={codeStyle}>
{getStyle('Button', 'round')}
</Typography>
</Box>
</Box>
</ThemeProvider>
);
}

Expand Down
3 changes: 3 additions & 0 deletions apps/web-sandbox/src/components/Box.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import styled from '@morfeo/styled-components-web';

export const Box = styled.Box({});
3 changes: 3 additions & 0 deletions apps/web-sandbox/src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import styled from '@morfeo/styled-components-web';

export const Button = styled.Button({});
3 changes: 3 additions & 0 deletions apps/web-sandbox/src/components/Typography.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import styled from '@morfeo/styled-components-web';

export const Typography = styled.Typography({});
3 changes: 3 additions & 0 deletions apps/web-sandbox/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './Box';
export * from './Button';
export * from './Typography';
4 changes: 4 additions & 0 deletions apps/web-sandbox/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React from 'react';
import { theme } from '@morfeo/web';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { lightTheme } from './theme';
import './index.css';

theme.set(lightTheme as any);

ReactDOM.render(
<React.StrictMode>
<App />
Expand Down
49 changes: 40 additions & 9 deletions apps/web-sandbox/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ export const lightTheme = {
light: 'all 0.5s',
},
components: {
Box: {
tag: 'div',
style: {},
},
Button: {
tag: 'button',
style: {
componentTag: 'button',
transition: 'light',
height: 'm',
width: 'm',
Expand All @@ -50,20 +54,47 @@ export const lightTheme = {
},
props: {
'aria-label': 'button',
type: 'submit',
type: 'button',
},
variants: {
primary: {
bg: 'secondary',
borderColor: 'primary',
color: 'primary',
'&:hover': {
bg: 'primary',
color: 'secondary',
props: {
'aria-label': 'primary button',
},
style: {
bg: 'secondary',
borderColor: 'primary',
color: 'primary',
'&:hover': {
bg: 'primary',
color: 'secondary',
},
},
},
round: {
borderRadius: 'round',
style: { borderRadius: 'round' },
},
},
},
Typography: {
tag: 'p',
style: {},
variants: {
h1: {
tag: 'h1',
style: { color: 'red' },
},
h2: {
tag: 'h1',
style: { color: 'green' },
},
h3: {
tag: 'h3',
style: { color: 'blue' },
},
code: {
tag: 'pre',
style: { color: 'primary' },
},
},
},
Expand Down
16 changes: 10 additions & 6 deletions packages/core/src/parsers/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ function getVariantStyle(
if (!variant || !variants || !variants[variant]) {
return {};
}
return variants[variant];
return variants[variant].style;
}

export function components({ value, style }: ParserParams<'componentName'>) {
const { variant } = style || {};
const { style: componentStyle, variants } = value
? theme.getValue('components', value) || {}
: ({} as any);
if (!value || !theme.getValue('components', value)) {
return {};
}

const { style: componentStyle, variants } = theme.getValue(
'components',
value,
);

const variantStyle = getVariantStyle(variants, variant);

return parsers.resolve({
Expand All @@ -30,6 +36,4 @@ export function components({ value, style }: ParserParams<'componentName'>) {

export const componentsParses = {
componentName: components,
variant: () => {},
componentTag: () => {},
};
2 changes: 1 addition & 1 deletion packages/core/tests/parsers/components.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const THEME: Theme = {
},
variants: {
primary: {
color: 'secondary',
style: { color: 'secondary' },
},
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@types/react-native": "^0.64.4"
},
"peerDependencies": {
"react": "^17.0.2",
"react-native": "^0.64.1"
},
"publishConfig": {
Expand Down
16 changes: 9 additions & 7 deletions packages/spec/src/types/components.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { Style } from './style';

type ComponentStyle = Style & {
componentTag?: string;
type ComponentStyle<Props extends Style = Style> = {
tag?: string;
style: Style;
props: Props;
};

export type ComponentConfig<
Variant extends string = string,
Props extends Style = Style,
> = {
style: ComponentStyle;
props: Props;
variants: Record<Variant, ComponentStyle>;
> = ComponentStyle<Props> & {
variants: Record<Variant, ComponentStyle<Props>>;
};
export interface Components {
Box: ComponentConfig;
}

export type Component = keyof Components;

export type Variant<C extends Component> = keyof Components[C]['variants'];

export type ComponentProps<C extends Component = Component> = {
componentName?: C;
variant?: keyof Components[C]['variants'];
variant?: Variant<C>;
};
4 changes: 4 additions & 0 deletions packages/styled-components-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"peerDependencies": {
"@morfeo/web": "^0.0.3",
"csstype": "^3.0.8",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"styled-components": "^5.2.3"
Expand All @@ -32,5 +33,8 @@
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@morfeo/web": "^0.0.3"
}
}
15 changes: 15 additions & 0 deletions packages/styled-components-web/src/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { FC, useEffect, useState } from 'react';
import { theme } from '@morfeo/web';
import { ThemeProvider as StyledProvider } from 'styled-components';

type Props = Omit<React.ComponentProps<typeof StyledProvider>, 'theme'>;

export const ThemeProvider: FC<Props> = ({ children }) => {
const [currentTheme, setTheme] = useState(theme.get());

useEffect(() => {
theme.listen(setTheme);
}, []);

return <StyledProvider theme={currentTheme}>{children}</StyledProvider>;
};
5 changes: 3 additions & 2 deletions packages/styled-components-web/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { morfeoStyled, propsParser } from './styled';
import { morfeoStyled, propsParser, attributesParser } from './styled';
export * from 'styled-components';
export * from './types';

export { propsParser };
export { propsParser, attributesParser };
export default morfeoStyled;
export { ThemeProvider } from './ThemeProvider';
Loading

0 comments on commit e5dee4c

Please sign in to comment.