mirror of
https://github.com/apache/superset.git
synced 2026-04-24 10:35:01 +00:00
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:
140
superset-frontend/src/components/Button/button.stories.jsx
Normal file
140
superset-frontend/src/components/Button/button.stories.jsx
Normal file
@@ -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>
|
||||
);
|
||||
114
superset-frontend/src/components/Button/index.tsx
Normal file
114
superset-frontend/src/components/Button/index.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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 { kebabCase } from 'lodash';
|
||||
import {
|
||||
Button as BootstrapButton,
|
||||
Tooltip,
|
||||
OverlayTrigger,
|
||||
} from 'react-bootstrap';
|
||||
import styled from '@superset-ui/style';
|
||||
|
||||
export type OnClickHandler = React.MouseEventHandler<BootstrapButton>;
|
||||
|
||||
export interface ButtonProps {
|
||||
className?: string;
|
||||
tooltip?: string;
|
||||
placement?: string;
|
||||
onClick?: OnClickHandler;
|
||||
disabled?: boolean;
|
||||
bsStyle?: string;
|
||||
btnStyles?: string;
|
||||
bsSize?: BootstrapButton.ButtonProps['bsSize'];
|
||||
style?: BootstrapButton.ButtonProps['style'];
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const BUTTON_WRAPPER_STYLE = { display: 'inline-block', cursor: 'not-allowed' };
|
||||
|
||||
const SupersetButton = styled(BootstrapButton)`
|
||||
&.supersetButton {
|
||||
border-radius: ${({ theme }) => theme.borderRadius}px;
|
||||
border: none;
|
||||
color: ${({ theme }) => theme.colors.secondary.light5};
|
||||
font-size: ${({ theme }) => theme.typography.sizes.s};
|
||||
font-weight: ${({ theme }) => theme.typography.weights.bold};
|
||||
min-width: ${({ theme }) => theme.gridUnit * 36}px;
|
||||
min-height: ${({ theme }) => theme.gridUnit * 8}px;
|
||||
text-transform: uppercase;
|
||||
margin-left: ${({ theme }) => theme.gridUnit * 4}px;
|
||||
&:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
i {
|
||||
padding: 0 ${({ theme }) => theme.gridUnit * 2}px 0 0;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background-color: ${({ theme }) => theme.colors.primary.base};
|
||||
}
|
||||
&.secondary {
|
||||
color: ${({ theme }) => theme.colors.primary.base};
|
||||
background-color: ${({ theme }) => theme.colors.primary.light4};
|
||||
}
|
||||
&.danger {
|
||||
background-color: ${({ theme }) => theme.colors.error.base};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Button(props: ButtonProps) {
|
||||
const buttonProps = {
|
||||
...props,
|
||||
bsSize: props.bsSize || 'sm',
|
||||
placement: props.placement || 'top',
|
||||
};
|
||||
const tooltip = props.tooltip;
|
||||
const placement = props.placement;
|
||||
delete buttonProps.tooltip;
|
||||
delete buttonProps.placement;
|
||||
|
||||
let button = (
|
||||
<SupersetButton {...buttonProps}>{props.children}</SupersetButton>
|
||||
);
|
||||
if (tooltip) {
|
||||
if (props.disabled) {
|
||||
// Working around the fact that tooltips don't get triggered when buttons are disabled
|
||||
// https://github.com/react-bootstrap/react-bootstrap/issues/1588
|
||||
buttonProps.style = { pointerEvents: 'none' };
|
||||
button = (
|
||||
<div style={BUTTON_WRAPPER_STYLE}>
|
||||
<SupersetButton {...buttonProps}>{props.children}</SupersetButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement={placement}
|
||||
overlay={
|
||||
<Tooltip id={`${kebabCase(tooltip)}-tooltip`}>{tooltip}</Tooltip>
|
||||
}
|
||||
>
|
||||
{button}
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
Reference in New Issue
Block a user