diff options
author | 2019-01-09 11:05:32 +0100 | |
---|---|---|
committer | 2019-01-09 11:05:32 +0100 | |
commit | 2c514e58eabd71af280b727514dccb7c8db4e6cf (patch) | |
tree | b9677f450fe300c6ff16d1ea1e2af7ea35a7bc02 /uidev/src | |
parent | Make packages work in electron, node and web (diff) | |
download | ferdium-app-2c514e58eabd71af280b727514dccb7c8db4e6cf.tar.gz ferdium-app-2c514e58eabd71af280b727514dccb7c8db4e6cf.tar.zst ferdium-app-2c514e58eabd71af280b727514dccb7c8db4e6cf.zip |
Finalize packages & replace storybook with homegrown `uidev`
Diffstat (limited to 'uidev/src')
-rw-r--r-- | uidev/src/app.html | 18 | ||||
-rw-r--r-- | uidev/src/app.tsx | 89 | ||||
-rw-r--r-- | uidev/src/index.tsx | 9 | ||||
-rw-r--r-- | uidev/src/stores/index.ts | 5 | ||||
-rw-r--r-- | uidev/src/stores/stories.ts | 43 | ||||
-rw-r--r-- | uidev/src/stories/input.tsx | 92 | ||||
-rw-r--r-- | uidev/src/withTheme/index.tsx | 50 |
7 files changed, 306 insertions, 0 deletions
diff --git a/uidev/src/app.html b/uidev/src/app.html new file mode 100644 index 000000000..40801775e --- /dev/null +++ b/uidev/src/app.html | |||
@@ -0,0 +1,18 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html> | ||
3 | |||
4 | <head> | ||
5 | <title>UIDev</title> | ||
6 | <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,800" rel="stylesheet"> | ||
7 | <style> | ||
8 | * { | ||
9 | font-family: 'Open Sans', sans-serif; | ||
10 | font-size: 14px; | ||
11 | } | ||
12 | </style> | ||
13 | </head> | ||
14 | |||
15 | <body> | ||
16 | <div id="root"></div> | ||
17 | </body> | ||
18 | </html> | ||
diff --git a/uidev/src/app.tsx b/uidev/src/app.tsx new file mode 100644 index 000000000..a1c9ee343 --- /dev/null +++ b/uidev/src/app.tsx | |||
@@ -0,0 +1,89 @@ | |||
1 | import { Classes } from 'jss'; | ||
2 | import React, { Component } from 'react'; | ||
3 | import { render } from 'react-dom'; | ||
4 | import injectSheet from 'react-jss'; | ||
5 | import './stories/input'; | ||
6 | import { WithTheme } from './withTheme'; | ||
7 | |||
8 | import { store } from './stores'; | ||
9 | |||
10 | const styles = { | ||
11 | container: { | ||
12 | display: 'flex', | ||
13 | width: '100%', | ||
14 | }, | ||
15 | menu: { | ||
16 | width: 300, | ||
17 | position: 'fixed' as any, | ||
18 | }, | ||
19 | stories: { | ||
20 | width: '100%', | ||
21 | marginLeft: 320, | ||
22 | paddingLeft: 40, | ||
23 | paddingRight: 40, | ||
24 | borderLeft: '1px solid #CFCFCF', | ||
25 | }, | ||
26 | sectionHeadline: { | ||
27 | fontSize: 30, | ||
28 | }, | ||
29 | storyHeadline: { | ||
30 | fontSize: 24, | ||
31 | }, | ||
32 | story: { | ||
33 | paddingBottom: 40, | ||
34 | marginBottom: 40, | ||
35 | borderBottom: '1px solid #CFCFCF', | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | const foo = { | ||
40 | seas: 'bar', | ||
41 | }; | ||
42 | |||
43 | export const App = injectSheet(styles)(({ classes }: { classes: Classes }) => ( | ||
44 | <div className={classes.container}> | ||
45 | <ul className={classes.menu}> | ||
46 | {store.stories.sections.map((section, key) => ( | ||
47 | <li key={key}> | ||
48 | <a href={`#section-${key}`}>{ | ||
49 | section.name} | ||
50 | </a> | ||
51 | <ul> | ||
52 | {section.stories.map((story, storyKey) => ( | ||
53 | <li key={storyKey}> | ||
54 | <a href={`#section-${key}-story-${storyKey}`}> | ||
55 | {story.name} | ||
56 | </a> | ||
57 | </li> | ||
58 | ))} | ||
59 | </ul> | ||
60 | </li> | ||
61 | ))} | ||
62 | </ul> | ||
63 | <div className={classes.stories}> | ||
64 | {store.stories.sections.map((section, key) => ( | ||
65 | <div key={key}> | ||
66 | <h1 | ||
67 | id={`section-${key}`} | ||
68 | className={classes.sectionHeadline} | ||
69 | > | ||
70 | {section.name} | ||
71 | </h1> | ||
72 | {section.stories.map((story, storyKey) => ( | ||
73 | <div className={classes.story} key={storyKey}> | ||
74 | <h2 | ||
75 | id={`section-${key}-story-${storyKey}`} | ||
76 | className={classes.storyHeadline} | ||
77 | > | ||
78 | {story.name} | ||
79 | </h2> | ||
80 | <WithTheme> | ||
81 | {story.component()} | ||
82 | </WithTheme> | ||
83 | </div> | ||
84 | ))} | ||
85 | </div> | ||
86 | ))} | ||
87 | </div> | ||
88 | </div> | ||
89 | )); | ||
diff --git a/uidev/src/index.tsx b/uidev/src/index.tsx new file mode 100644 index 000000000..99658b184 --- /dev/null +++ b/uidev/src/index.tsx | |||
@@ -0,0 +1,9 @@ | |||
1 | import React from 'react'; | ||
2 | import { render } from 'react-dom'; | ||
3 | import { App } from './app'; | ||
4 | |||
5 | const app = () => ( | ||
6 | <App /> | ||
7 | ); | ||
8 | |||
9 | render(app(), document.getElementById('root')); | ||
diff --git a/uidev/src/stores/index.ts b/uidev/src/stores/index.ts new file mode 100644 index 000000000..276058ec4 --- /dev/null +++ b/uidev/src/stores/index.ts | |||
@@ -0,0 +1,5 @@ | |||
1 | import { storyStore } from './stories'; | ||
2 | |||
3 | export const store = { | ||
4 | stories: storyStore, | ||
5 | }; | ||
diff --git a/uidev/src/stores/stories.ts b/uidev/src/stores/stories.ts new file mode 100644 index 000000000..064bf275f --- /dev/null +++ b/uidev/src/stores/stories.ts | |||
@@ -0,0 +1,43 @@ | |||
1 | import { store } from './index'; | ||
2 | |||
3 | export type StorySectionName = string; | ||
4 | export type StoryName = string; | ||
5 | export type StoryComponent = Function; | ||
6 | |||
7 | export interface IStories { | ||
8 | name: string; | ||
9 | component: StoryComponent; | ||
10 | } | ||
11 | |||
12 | export interface ISections { | ||
13 | name: StorySectionName; | ||
14 | stories: IStories[]; | ||
15 | } | ||
16 | |||
17 | export interface IStoryStore { | ||
18 | sections: ISections[]; | ||
19 | } | ||
20 | |||
21 | export const storyStore: IStoryStore = { | ||
22 | sections: [], | ||
23 | }; | ||
24 | |||
25 | export const storiesOf = (name: StorySectionName) => { | ||
26 | const length = storyStore.sections.push({ | ||
27 | name, | ||
28 | stories: [], | ||
29 | }); | ||
30 | |||
31 | const actions = { | ||
32 | add: (name: StoryName, component: StoryComponent) => { | ||
33 | storyStore.sections[length - 1].stories.push({ | ||
34 | name, | ||
35 | component, | ||
36 | }); | ||
37 | |||
38 | return actions; | ||
39 | }, | ||
40 | }; | ||
41 | |||
42 | return actions; | ||
43 | }; | ||
diff --git a/uidev/src/stories/input.tsx b/uidev/src/stories/input.tsx new file mode 100644 index 000000000..dc8f6e997 --- /dev/null +++ b/uidev/src/stories/input.tsx | |||
@@ -0,0 +1,92 @@ | |||
1 | import React from 'react'; | ||
2 | |||
3 | import { Input } from '@meetfranz/forms'; | ||
4 | import { storiesOf } from '../stores/stories'; | ||
5 | |||
6 | export const stories = () => (<div>input stories</div>); | ||
7 | |||
8 | const defaultProps = { | ||
9 | label: 'Label', | ||
10 | id: 'test1', | ||
11 | name: 'test1', | ||
12 | onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), | ||
13 | }; | ||
14 | |||
15 | const defaultPasswordProps = { | ||
16 | label: 'Password', | ||
17 | type: 'password', | ||
18 | id: 'test1', | ||
19 | name: 'test1', | ||
20 | onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), | ||
21 | }; | ||
22 | |||
23 | storiesOf('Input') | ||
24 | .add('Basic', () => ( | ||
25 | <Input | ||
26 | {...defaultProps} | ||
27 | placeholder="Placeholder text" | ||
28 | /> | ||
29 | )) | ||
30 | .add('Without Label', () => ( | ||
31 | <Input | ||
32 | {...defaultProps} | ||
33 | showLabel={false} | ||
34 | /> | ||
35 | )) | ||
36 | .add('Disabled', () => ( | ||
37 | <Input {...defaultProps} disabled /> | ||
38 | )) | ||
39 | .add('With prefix', () => ( | ||
40 | <Input | ||
41 | {...defaultProps} | ||
42 | prefix="https://" | ||
43 | /> | ||
44 | )) | ||
45 | .add('With suffix', () => ( | ||
46 | <Input | ||
47 | {...defaultProps} | ||
48 | suffix=".meetfranz.com" | ||
49 | /> | ||
50 | )) | ||
51 | .add('With pre-suffix', () => ( | ||
52 | <Input | ||
53 | {...defaultProps} | ||
54 | prefix="https://" | ||
55 | suffix=".meetfranz.com" | ||
56 | /> | ||
57 | )) | ||
58 | .add('With error', () => ( | ||
59 | <Input | ||
60 | {...defaultProps} | ||
61 | value="faulty input" | ||
62 | error="This is a generic error message." | ||
63 | /> | ||
64 | )); | ||
65 | |||
66 | storiesOf('Password') | ||
67 | .add('Basic', () => ( | ||
68 | <Input | ||
69 | {...defaultPasswordProps} | ||
70 | /> | ||
71 | )) | ||
72 | .add('Show password toggle', () => ( | ||
73 | <Input | ||
74 | {...defaultPasswordProps} | ||
75 | showPasswordToggle | ||
76 | /> | ||
77 | )) | ||
78 | .add('Score password', () => ( | ||
79 | <Input | ||
80 | {...defaultPasswordProps} | ||
81 | showPasswordToggle | ||
82 | scorePassword | ||
83 | /> | ||
84 | )) | ||
85 | .add('Score password with error', () => ( | ||
86 | <Input | ||
87 | {...defaultPasswordProps} | ||
88 | error="Password is too short" | ||
89 | showPasswordToggle | ||
90 | scorePassword | ||
91 | /> | ||
92 | )); | ||
diff --git a/uidev/src/withTheme/index.tsx b/uidev/src/withTheme/index.tsx new file mode 100644 index 000000000..17a1074d3 --- /dev/null +++ b/uidev/src/withTheme/index.tsx | |||
@@ -0,0 +1,50 @@ | |||
1 | import { theme, Theme, ThemeType } from '@meetfranz/theme'; | ||
2 | import { Classes } from 'jss'; | ||
3 | import React from 'react'; | ||
4 | import injectSheet, { ThemeProvider } from 'react-jss'; | ||
5 | |||
6 | const defaultTheme = { | ||
7 | name: 'Default', | ||
8 | variables: theme(ThemeType.default), | ||
9 | }; | ||
10 | |||
11 | const darkTheme = { | ||
12 | name: 'Dark Mode', | ||
13 | variables: theme(ThemeType.dark), | ||
14 | }; | ||
15 | |||
16 | const themes = [defaultTheme, darkTheme]; | ||
17 | |||
18 | const styles = (theme: Theme) => ({ | ||
19 | title: { | ||
20 | fontSize: 14, | ||
21 | }, | ||
22 | container: { | ||
23 | border: theme.inputBorder, | ||
24 | borderRadius: theme.borderRadiusSmall, | ||
25 | marginBottom: 20, | ||
26 | padding: 20, | ||
27 | background: theme.colorContentBackground, | ||
28 | }, | ||
29 | }); | ||
30 | |||
31 | const Container = injectSheet(styles)(({ name, classes, story }: { name: string, classes: Classes, story: React.ReactNode }) => ( | ||
32 | <article> | ||
33 | <h1 className={classes.title}>{name}</h1> | ||
34 | <div className={classes.container}> | ||
35 | {story} | ||
36 | </div> | ||
37 | </article> | ||
38 | )); | ||
39 | |||
40 | export const WithTheme = ({ children }: {children: React.ReactChild}) => { | ||
41 | return ( | ||
42 | <> | ||
43 | {themes.map((theme, key) => ( | ||
44 | <ThemeProvider key={key} theme={theme.variables}> | ||
45 | <Container story={children} name={theme.name} /> | ||
46 | </ThemeProvider> | ||
47 | ))} | ||
48 | </> | ||
49 | ); | ||
50 | }; | ||