mirror of https://github.com/apache/superset.git
feat: adding Storybook to Superset (#10383)
* Storybook added! * starting to configure junk.... * Storybook works!!! * Now with theme! * apache boilerplate * more apache comments * lots o' knobs for the Button.... taking stock of the codebase * more classes, but killing the knob for now. * nixing unused module * linting * fresh package-lock * now with tooltip! * adding path and zlip because the linter told me to * upgrading storybook packages from devdeps * linting * removing cruft * killing an annoying (and old?) lint issue * lint fix, take 2. * removing zlib/path * package lock reset from master * re-adding new packages for this here PR * nixing console log, simplifying * nixing comment TODOs (done enough!) * basic docs.
This commit is contained in:
parent
961108625e
commit
ca71d4d6ee
|
@ -703,6 +703,17 @@ npm run cypress open
|
||||||
|
|
||||||
See [`superset-frontend/cypress_build.sh`](https://github.com/apache/incubator-superset/blob/master/superset-frontend/cypress_build.sh).
|
See [`superset-frontend/cypress_build.sh`](https://github.com/apache/incubator-superset/blob/master/superset-frontend/cypress_build.sh).
|
||||||
|
|
||||||
|
### Storybook
|
||||||
|
|
||||||
|
Superset includes a [Storybook](https://storybook.js.org/) to preview the layout/styling of various Superset components, and variations thereof. To open and view the Storybook:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd superset-frontend
|
||||||
|
npm run storybool
|
||||||
|
```
|
||||||
|
|
||||||
|
When contributing new React components to Superset, please try to add a Story alongside the component's `jsx/tsx` file.
|
||||||
|
|
||||||
## Translating
|
## Translating
|
||||||
|
|
||||||
We use [Babel](http://babel.pocoo.org/en/latest/) to translate Superset.
|
We use [Babel](http://babel.pocoo.org/en/latest/) to translate Superset.
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// Suerset's webpack.config.js
|
||||||
|
const customConfig = require('../webpack.config.js');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
stories: ['../src/components/**/*.stories.jsx'],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-actions',
|
||||||
|
'@storybook/addon-links',
|
||||||
|
'@storybook/preset-typescript',
|
||||||
|
'storybook-addon-jsx',
|
||||||
|
'@storybook/addon-knobs/register',
|
||||||
|
],
|
||||||
|
webpackFinal: config => ({
|
||||||
|
...config,
|
||||||
|
module: {
|
||||||
|
...config.module,
|
||||||
|
rules: customConfig.module.rules,
|
||||||
|
},
|
||||||
|
plugins: [...config.plugins, ...customConfig.plugins],
|
||||||
|
}),
|
||||||
|
};
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { addDecorator } from '@storybook/react';
|
||||||
|
import { jsxDecorator } from 'storybook-addon-jsx';
|
||||||
|
|
||||||
|
import { supersetTheme, ThemeProvider } from '@superset-ui/style';
|
||||||
|
|
||||||
|
import '../src/theme.ts';
|
||||||
|
|
||||||
|
const themeDecorator = storyFn => (
|
||||||
|
<ThemeProvider theme={supersetTheme}>{storyFn()}</ThemeProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
addDecorator(jsxDecorator);
|
||||||
|
addDecorator(themeDecorator);
|
File diff suppressed because it is too large
Load Diff
|
@ -23,7 +23,9 @@
|
||||||
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
|
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
|
||||||
"clean-css": "prettier --write '{src,stylesheets}/**/*.{css,less,sass,scss}'",
|
"clean-css": "prettier --write '{src,stylesheets}/**/*.{css,less,sass,scss}'",
|
||||||
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
|
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
|
||||||
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json"
|
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
|
||||||
|
"storybook": "NODE_ENV=development BABEL_ENV=development start-storybook -p 6006",
|
||||||
|
"build-storybook": "build-storybook"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -59,6 +61,8 @@
|
||||||
"@babel/runtime-corejs3": "^7.8.4",
|
"@babel/runtime-corejs3": "^7.8.4",
|
||||||
"@data-ui/sparkline": "^0.0.54",
|
"@data-ui/sparkline": "^0.0.54",
|
||||||
"@emotion/core": "^10.0.28",
|
"@emotion/core": "^10.0.28",
|
||||||
|
"@storybook/addon-actions": "^5.3.19",
|
||||||
|
"@storybook/addon-knobs": "^5.3.19",
|
||||||
"@superset-ui/chart": "^0.14.9",
|
"@superset-ui/chart": "^0.14.9",
|
||||||
"@superset-ui/chart-composition": "^0.14.9",
|
"@superset-ui/chart-composition": "^0.14.9",
|
||||||
"@superset-ui/chart-controls": "^0.14.9",
|
"@superset-ui/chart-controls": "^0.14.9",
|
||||||
|
@ -204,6 +208,10 @@
|
||||||
"@emotion/babel-preset-css-prop": "^10.0.27",
|
"@emotion/babel-preset-css-prop": "^10.0.27",
|
||||||
"@hot-loader/react-dom": "^16.13.0",
|
"@hot-loader/react-dom": "^16.13.0",
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||||
|
"@storybook/addon-links": "^5.3.19",
|
||||||
|
"@storybook/addons": "^5.3.19",
|
||||||
|
"@storybook/preset-typescript": "^3.0.0",
|
||||||
|
"@storybook/react": "^5.3.19",
|
||||||
"@svgr/webpack": "^5.4.0",
|
"@svgr/webpack": "^5.4.0",
|
||||||
"@types/classnames": "^2.2.9",
|
"@types/classnames": "^2.2.9",
|
||||||
"@types/dom-to-image": "^2.6.0",
|
"@types/dom-to-image": "^2.6.0",
|
||||||
|
@ -262,6 +270,7 @@
|
||||||
"sinon": "^9.0.2",
|
"sinon": "^9.0.2",
|
||||||
"source-map-support": "^0.5.16",
|
"source-map-support": "^0.5.16",
|
||||||
"speed-measure-webpack-plugin": "^1.2.3",
|
"speed-measure-webpack-plugin": "^1.2.3",
|
||||||
|
"storybook-addon-jsx": "^7.3.3",
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.0.0",
|
||||||
"terser-webpack-plugin": "^1.1.0",
|
"terser-webpack-plugin": "^1.1.0",
|
||||||
"thread-loader": "^1.2.0",
|
"thread-loader": "^1.2.0",
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import ResizableHandle from 'src/dashboard/components/resizable/ResizableHandle';
|
import ResizableHandle from 'src/dashboard/components/resizable/ResizableHandle';
|
||||||
|
|
||||||
|
/* eslint-disable react/jsx-pascal-case */
|
||||||
describe('ResizableHandle', () => {
|
describe('ResizableHandle', () => {
|
||||||
it('should render a right resize handle', () => {
|
it('should render a right resize handle', () => {
|
||||||
const wrapper = shallow(<ResizableHandle.right />);
|
const wrapper = shallow(<ResizableHandle.right />);
|
||||||
|
@ -41,3 +42,4 @@ describe('ResizableHandle', () => {
|
||||||
).toHaveLength(1);
|
).toHaveLength(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
/* eslint-enable react/jsx-pascal-case */
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { withKnobs, boolean, select, text } from '@storybook/addon-knobs';
|
||||||
|
import Button from './index';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Button',
|
||||||
|
component: Button,
|
||||||
|
decorators: [withKnobs],
|
||||||
|
};
|
||||||
|
|
||||||
|
const bsStyleKnob = {
|
||||||
|
label: 'Types',
|
||||||
|
options: {
|
||||||
|
Primary: 'primary',
|
||||||
|
Secondary: 'secondary',
|
||||||
|
Danger: 'danger',
|
||||||
|
Warning: 'warning',
|
||||||
|
Success: 'success',
|
||||||
|
Link: 'link',
|
||||||
|
Default: 'default',
|
||||||
|
None: null,
|
||||||
|
},
|
||||||
|
defaultValue: null,
|
||||||
|
// groupId: 'ButtonType',
|
||||||
|
};
|
||||||
|
const bsSizeKnob = {
|
||||||
|
label: 'Sizes',
|
||||||
|
options: {
|
||||||
|
XS: 'xsmall',
|
||||||
|
S: 'small',
|
||||||
|
M: 'medium',
|
||||||
|
L: 'large',
|
||||||
|
None: null,
|
||||||
|
},
|
||||||
|
defaultValue: null,
|
||||||
|
};
|
||||||
|
// TODO remove the use of these in the codebase where they're not necessary
|
||||||
|
// const classKnob = {
|
||||||
|
// label: 'Known Classes',
|
||||||
|
// options: {
|
||||||
|
// Refresh: 'refresh-btn',
|
||||||
|
// Primary: 'btn-primary',
|
||||||
|
// Reset: 'reset',
|
||||||
|
// Fetch: 'fetch',
|
||||||
|
// Query: 'query',
|
||||||
|
// saveBtn: 'save-btn',
|
||||||
|
// MR3: 'm-r-3',
|
||||||
|
// cancelQuery: 'cancelQuery',
|
||||||
|
// toggleSave: 'toggleSave',
|
||||||
|
// toggleSchedule: 'toggleSchedule',
|
||||||
|
// autocomplete: 'autocomplete',
|
||||||
|
// OK: 'ok',
|
||||||
|
// None: null,
|
||||||
|
// },
|
||||||
|
// defaultValue: null,
|
||||||
|
// };
|
||||||
|
const typeKnob = {
|
||||||
|
label: 'Type',
|
||||||
|
options: {
|
||||||
|
Submit: 'submit',
|
||||||
|
Button: 'button',
|
||||||
|
None: null,
|
||||||
|
},
|
||||||
|
defaultValue: null,
|
||||||
|
};
|
||||||
|
const targetKnob = {
|
||||||
|
label: 'Target',
|
||||||
|
options: {
|
||||||
|
Blank: '_blank',
|
||||||
|
None: null,
|
||||||
|
},
|
||||||
|
defaultValue: null,
|
||||||
|
};
|
||||||
|
const hrefKnob = {
|
||||||
|
label: 'HREF',
|
||||||
|
options: {
|
||||||
|
Superset: 'http://https://superset.incubator.apache.org/',
|
||||||
|
None: null,
|
||||||
|
},
|
||||||
|
defaultValue: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SupersetButton = () => (
|
||||||
|
<Button
|
||||||
|
disabled={boolean('Disabled', false)}
|
||||||
|
bsStyle={select(
|
||||||
|
bsStyleKnob.label,
|
||||||
|
bsStyleKnob.options,
|
||||||
|
bsStyleKnob.defaultValue,
|
||||||
|
bsStyleKnob.groupId,
|
||||||
|
)}
|
||||||
|
bsSize={select(
|
||||||
|
bsSizeKnob.label,
|
||||||
|
bsSizeKnob.options,
|
||||||
|
bsSizeKnob.defaultValue,
|
||||||
|
bsSizeKnob.groupId,
|
||||||
|
)}
|
||||||
|
onClick={action('clicked')}
|
||||||
|
type={select(
|
||||||
|
typeKnob.label,
|
||||||
|
typeKnob.options,
|
||||||
|
typeKnob.defaultValue,
|
||||||
|
typeKnob.groupId,
|
||||||
|
)}
|
||||||
|
target={select(
|
||||||
|
targetKnob.label,
|
||||||
|
targetKnob.options,
|
||||||
|
targetKnob.defaultValue,
|
||||||
|
targetKnob.groupId,
|
||||||
|
)}
|
||||||
|
href={select(
|
||||||
|
hrefKnob.label,
|
||||||
|
hrefKnob.options,
|
||||||
|
hrefKnob.defaultValue,
|
||||||
|
hrefKnob.groupId,
|
||||||
|
)}
|
||||||
|
tooltip={boolean('Tooltip', false) === true ? 'This is a tooltip!' : null}
|
||||||
|
>
|
||||||
|
{text('Label', 'Button!')}
|
||||||
|
</Button>
|
||||||
|
);
|
|
@ -258,7 +258,11 @@ const config = {
|
||||||
test: /\.jsx?$/,
|
test: /\.jsx?$/,
|
||||||
// include source code for plugins, but exclude node_modules within them
|
// include source code for plugins, but exclude node_modules within them
|
||||||
exclude: [/superset-ui.*\/node_modules\//],
|
exclude: [/superset-ui.*\/node_modules\//],
|
||||||
include: [new RegExp(`${APP_DIR}/src`), /superset-ui.*\/src/],
|
include: [
|
||||||
|
new RegExp(`${APP_DIR}/src`),
|
||||||
|
/superset-ui.*\/src/,
|
||||||
|
new RegExp(`${APP_DIR}/.storybook`),
|
||||||
|
],
|
||||||
use: [babelLoader],
|
use: [babelLoader],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue