18 changed files with 549 additions and 11 deletions
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
module.exports = { |
||||
stories: ['../stories/**/*.stories.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'], |
||||
addons: [ |
||||
'@storybook/addon-links', |
||||
'@storybook/addon-essentials', |
||||
'@storybook/addon-interactions', |
||||
'@storybook/preset-scss', |
||||
'@storybook/addon-postcss', |
||||
], |
||||
framework: '@storybook/react', |
||||
}; |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
import 'antd/dist/antd.css'; |
||||
import '../styles/globals.scss'; |
||||
|
||||
export const parameters = { |
||||
actions: { argTypesRegex: '^on[A-Z].*' }, |
||||
controls: { |
||||
matchers: { |
||||
color: /(background|color)$/i, |
||||
date: /Date$/, |
||||
}, |
||||
}, |
||||
}; |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
module.exports = { |
||||
plugins: ['postcss-flexbugs-fixes', 'autoprefixer'], |
||||
}; |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
import React from 'react'; |
||||
import { Menu, Dropdown } from 'antd'; |
||||
import { DownOutlined } from '@ant-design/icons'; |
||||
import { ComponentStory, ComponentMeta } from '@storybook/react'; |
||||
|
||||
const menu = ( |
||||
<Menu> |
||||
<Menu.Item key="0"> |
||||
<a href="https://owncast.online">1st menu item</a> |
||||
</Menu.Item> |
||||
<Menu.Item key="1"> |
||||
<a href="https://directory.owncast.online">2nd menu item</a> |
||||
</Menu.Item> |
||||
<Menu.Divider /> |
||||
<Menu.Item key="3">3rd menu item</Menu.Item> |
||||
</Menu> |
||||
); |
||||
|
||||
const DropdownExample = () => ( |
||||
<Dropdown overlay={menu} trigger={['click']}> |
||||
<button type="button" className="ant-dropdown-link" onClick={e => e.preventDefault()}> |
||||
Click me <DownOutlined /> |
||||
</button> |
||||
</Dropdown> |
||||
); |
||||
|
||||
export default { |
||||
title: 'owncast/Dropdown', |
||||
component: Dropdown, |
||||
parameters: {}, |
||||
} as ComponentMeta<typeof Dropdown>; |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const Template: ComponentStory<typeof Dropdown> = args => <DropdownExample />; |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const Basic = Template.bind({}); |
||||
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
import React, { useState } from 'react'; |
||||
import { ComponentStory, ComponentMeta } from '@storybook/react'; |
||||
import { |
||||
Button, |
||||
Form, |
||||
Input, |
||||
Radio, |
||||
Select, |
||||
Cascader, |
||||
DatePicker, |
||||
InputNumber, |
||||
TreeSelect, |
||||
Switch, |
||||
} from 'antd'; |
||||
|
||||
const FormExample = () => { |
||||
const [componentSize, setComponentSize] = useState('default'); |
||||
|
||||
const onFormLayoutChange = ({ size }) => { |
||||
setComponentSize(size); |
||||
}; |
||||
|
||||
return ( |
||||
<Form |
||||
labelCol={{ |
||||
span: 4, |
||||
}} |
||||
wrapperCol={{ |
||||
span: 14, |
||||
}} |
||||
layout="horizontal" |
||||
initialValues={{ |
||||
size: componentSize, |
||||
}} |
||||
onValuesChange={onFormLayoutChange} |
||||
size={componentSize} |
||||
> |
||||
<Form.Item label="Form Size" name="size"> |
||||
<Radio.Group> |
||||
<Radio.Button value="small">Small</Radio.Button> |
||||
<Radio.Button value="default">Default</Radio.Button> |
||||
<Radio.Button value="large">Large</Radio.Button> |
||||
</Radio.Group> |
||||
</Form.Item> |
||||
<Form.Item label="Required text input" required> |
||||
<Input /> |
||||
</Form.Item> |
||||
<Form.Item label="Select"> |
||||
<Select> |
||||
<Select.Option value="demo">Demo</Select.Option> |
||||
</Select> |
||||
</Form.Item> |
||||
<Form.Item label="TreeSelect"> |
||||
<TreeSelect |
||||
treeData={[ |
||||
{ |
||||
title: 'Light', |
||||
value: 'light', |
||||
children: [ |
||||
{ |
||||
title: 'Bamboo', |
||||
value: 'bamboo', |
||||
}, |
||||
], |
||||
}, |
||||
]} |
||||
/> |
||||
</Form.Item> |
||||
<Form.Item label="Cascader"> |
||||
<Cascader |
||||
options={[ |
||||
{ |
||||
value: 'zhejiang', |
||||
label: 'Zhejiang', |
||||
children: [ |
||||
{ |
||||
value: 'hangzhou', |
||||
label: 'Hangzhou', |
||||
}, |
||||
], |
||||
}, |
||||
]} |
||||
/> |
||||
</Form.Item> |
||||
<Form.Item label="DatePicker"> |
||||
<DatePicker /> |
||||
</Form.Item> |
||||
<Form.Item label="InputNumber"> |
||||
<InputNumber /> |
||||
</Form.Item> |
||||
<Form.Item label="Switch" valuePropName="checked"> |
||||
<Switch /> |
||||
</Form.Item> |
||||
<Form.Item label="Button"> |
||||
<Button>Button</Button> |
||||
</Form.Item> |
||||
</Form> |
||||
); |
||||
}; |
||||
|
||||
export default { |
||||
title: 'owncast/Form', |
||||
component: Form, |
||||
// parameters: {},
|
||||
} as ComponentMeta<typeof Form>; |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const Template: ComponentStory<typeof Form> = args => <FormExample />; |
||||
|
||||
export const Demo = Template.bind({}); |
||||
@ -0,0 +1,211 @@
@@ -0,0 +1,211 @@
|
||||
import { Meta } from '@storybook/addon-docs'; |
||||
import Code from './assets/code-brackets.svg'; |
||||
import Colors from './assets/colors.svg'; |
||||
import Comments from './assets/comments.svg'; |
||||
import Direction from './assets/direction.svg'; |
||||
import Flow from './assets/flow.svg'; |
||||
import Plugin from './assets/plugin.svg'; |
||||
import Repo from './assets/repo.svg'; |
||||
import StackAlt from './assets/stackalt.svg'; |
||||
|
||||
<Meta title="Example/Introduction" /> |
||||
|
||||
<style>{` |
||||
.subheading { |
||||
--mediumdark: '#999999'; |
||||
font-weight: 900; |
||||
font-size: 13px; |
||||
color: #999; |
||||
letter-spacing: 6px; |
||||
line-height: 24px; |
||||
text-transform: uppercase; |
||||
margin-bottom: 12px; |
||||
margin-top: 40px; |
||||
} |
||||
|
||||
.link-list { |
||||
display: grid; |
||||
grid-template-columns: 1fr; |
||||
grid-template-rows: 1fr 1fr; |
||||
row-gap: 10px; |
||||
} |
||||
|
||||
@media (min-width: 620px) { |
||||
.link-list { |
||||
row-gap: 20px; |
||||
column-gap: 20px; |
||||
grid-template-columns: 1fr 1fr; |
||||
} |
||||
} |
||||
|
||||
@media all and (-ms-high-contrast:none) { |
||||
.link-list { |
||||
display: -ms-grid; |
||||
-ms-grid-columns: 1fr 1fr; |
||||
-ms-grid-rows: 1fr 1fr; |
||||
} |
||||
} |
||||
|
||||
.link-item { |
||||
display: block; |
||||
padding: 20px 30px 20px 15px; |
||||
border: 1px solid #00000010; |
||||
border-radius: 5px; |
||||
transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out; |
||||
color: #333333; |
||||
display: flex; |
||||
align-items: flex-start; |
||||
} |
||||
|
||||
.link-item:hover { |
||||
border-color: #1EA7FD50; |
||||
transform: translate3d(0, -3px, 0); |
||||
box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0; |
||||
} |
||||
|
||||
.link-item:active { |
||||
border-color: #1EA7FD; |
||||
transform: translate3d(0, 0, 0); |
||||
} |
||||
|
||||
.link-item strong { |
||||
font-weight: 700; |
||||
display: block; |
||||
margin-bottom: 2px; |
||||
} |
||||
|
||||
.link-item img { |
||||
height: 40px; |
||||
width: 40px; |
||||
margin-right: 15px; |
||||
flex: none; |
||||
} |
||||
|
||||
.link-item span { |
||||
font-size: 14px; |
||||
line-height: 20px; |
||||
} |
||||
|
||||
.tip { |
||||
display: inline-block; |
||||
border-radius: 1em; |
||||
font-size: 11px; |
||||
line-height: 12px; |
||||
font-weight: 700; |
||||
background: #E7FDD8; |
||||
color: #66BF3C; |
||||
padding: 4px 12px; |
||||
margin-right: 10px; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.tip-wrapper { |
||||
font-size: 13px; |
||||
line-height: 20px; |
||||
margin-top: 40px; |
||||
margin-bottom: 40px; |
||||
} |
||||
|
||||
.tip-wrapper code { |
||||
font-size: 12px; |
||||
display: inline-block; |
||||
} |
||||
|
||||
|
||||
`}</style> |
||||
|
||||
# Welcome to Storybook |
||||
|
||||
Storybook helps you build UI components in isolation from your app's business logic, data, and context. |
||||
That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA. |
||||
|
||||
Browse example stories now by navigating to them in the sidebar. |
||||
View their code in the `src/stories` directory to learn how they work. |
||||
We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages. |
||||
|
||||
<div className="subheading">Configure</div> |
||||
|
||||
<div className="link-list"> |
||||
<a |
||||
className="link-item" |
||||
href="https://storybook.js.org/docs/react/addons/addon-types" |
||||
target="_blank" |
||||
> |
||||
<img src={Plugin} alt="plugin" /> |
||||
<span> |
||||
<strong>Presets for popular tools</strong> |
||||
Easy setup for TypeScript, SCSS and more. |
||||
</span> |
||||
</a> |
||||
<a |
||||
className="link-item" |
||||
href="https://storybook.js.org/docs/react/configure/webpack" |
||||
target="_blank" |
||||
> |
||||
<img src={StackAlt} alt="Build" /> |
||||
<span> |
||||
<strong>Build configuration</strong> |
||||
How to customize webpack and Babel |
||||
</span> |
||||
</a> |
||||
<a |
||||
className="link-item" |
||||
href="https://storybook.js.org/docs/react/configure/styling-and-css" |
||||
target="_blank" |
||||
> |
||||
<img src={Colors} alt="colors" /> |
||||
<span> |
||||
<strong>Styling</strong> |
||||
How to load and configure CSS libraries |
||||
</span> |
||||
</a> |
||||
<a |
||||
className="link-item" |
||||
href="https://storybook.js.org/docs/react/get-started/setup#configure-storybook-for-your-stack" |
||||
target="_blank" |
||||
> |
||||
<img src={Flow} alt="flow" /> |
||||
<span> |
||||
<strong>Data</strong> |
||||
Providers and mocking for data libraries |
||||
</span> |
||||
</a> |
||||
</div> |
||||
|
||||
<div className="subheading">Learn</div> |
||||
|
||||
<div className="link-list"> |
||||
<a className="link-item" href="https://storybook.js.org/docs" target="_blank"> |
||||
<img src={Repo} alt="repo" /> |
||||
<span> |
||||
<strong>Storybook documentation</strong> |
||||
Configure, customize, and extend |
||||
</span> |
||||
</a> |
||||
<a className="link-item" href="https://storybook.js.org/tutorials/" target="_blank"> |
||||
<img src={Direction} alt="direction" /> |
||||
<span> |
||||
<strong>In-depth guides</strong> |
||||
Best practices from leading teams |
||||
</span> |
||||
</a> |
||||
<a className="link-item" href="https://github.com/storybookjs/storybook" target="_blank"> |
||||
<img src={Code} alt="code" /> |
||||
<span> |
||||
<strong>GitHub project</strong> |
||||
View the source and add issues |
||||
</span> |
||||
</a> |
||||
<a className="link-item" href="https://discord.gg/storybook" target="_blank"> |
||||
<img src={Comments} alt="comments" /> |
||||
<span> |
||||
<strong>Discord chat</strong> |
||||
Chat with maintainers and the community |
||||
</span> |
||||
</a> |
||||
</div> |
||||
|
||||
<div className="tip-wrapper"> |
||||
<span className="tip">Tip</span>Edit the Markdown in{' '} |
||||
<code>src/stories/Introduction.stories.mdx</code> |
||||
</div> |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
import React, { useState } from 'react'; |
||||
import { ComponentStory, ComponentMeta } from '@storybook/react'; |
||||
import { Modal, Button } from 'antd'; |
||||
|
||||
const Usage = () => { |
||||
const [isModalVisible, setIsModalVisible] = useState(false); |
||||
|
||||
const showModal = () => { |
||||
setIsModalVisible(true); |
||||
}; |
||||
|
||||
const handleOk = () => { |
||||
setIsModalVisible(false); |
||||
}; |
||||
|
||||
const handleCancel = () => { |
||||
setIsModalVisible(false); |
||||
}; |
||||
|
||||
return ( |
||||
<> |
||||
<Button type="primary" onClick={showModal}> |
||||
Test Modal |
||||
</Button> |
||||
<Modal title="Basic Modal" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}> |
||||
<p>Some contents...</p> |
||||
<p>Some contents...</p> |
||||
<p>Some contents...</p> |
||||
</Modal> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default { |
||||
title: 'owncast/Modal', |
||||
component: Modal, |
||||
parameters: {}, |
||||
} as ComponentMeta<typeof Modal>; |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const Template: ComponentStory<typeof Modal> = args => <Usage />; |
||||
|
||||
export const Basic = Template.bind({}); |
||||
|
||||
Usage.propTypes = {}; |
||||
|
||||
Usage.defaultProps = {}; |
||||
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
import React from 'react'; |
||||
import PropTypes from 'prop-types'; |
||||
import { Tabs, Radio } from 'antd'; |
||||
import { ComponentStory, ComponentMeta } from '@storybook/react'; |
||||
|
||||
const { TabPane } = Tabs; |
||||
|
||||
class TabsExample extends React.Component { |
||||
constructor(props) { |
||||
super(props); |
||||
|
||||
this.state = { size: 'small' }; |
||||
} |
||||
|
||||
onChange = e => { |
||||
this.setState({ size: e.target.value }); |
||||
}; |
||||
|
||||
render() { |
||||
const { size } = this.state; |
||||
const { type } = this.props; |
||||
|
||||
return ( |
||||
<div> |
||||
<Radio.Group value={size} onChange={this.onChange} style={{ marginBottom: 16 }}> |
||||
<Radio.Button value="small">Small</Radio.Button> |
||||
<Radio.Button value="default">Default</Radio.Button> |
||||
<Radio.Button value="large">Large</Radio.Button> |
||||
</Radio.Group> |
||||
|
||||
<Tabs defaultActiveKey="1" type={type} size={size}> |
||||
<TabPane tab="Card Tab 1" key="1"> |
||||
Content of card tab 1 |
||||
</TabPane> |
||||
<TabPane tab="Card Tab 2" key="2"> |
||||
Content of card tab 2 |
||||
</TabPane> |
||||
<TabPane tab="Card Tab 3" key="3"> |
||||
Content of card tab 3 |
||||
</TabPane> |
||||
</Tabs> |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
title: 'owncast/Tabs', |
||||
component: Tabs, |
||||
} as ComponentMeta<typeof Tabs>; |
||||
|
||||
const Template: ComponentStory<typeof Tabs> = args => <TabsExample {...args} />; |
||||
|
||||
export const Card = Template.bind({}); |
||||
Card.args = { type: 'card' }; |
||||
|
||||
export const Basic = Template.bind({}); |
||||
Basic.args = { type: '' }; |
||||
|
||||
TabsExample.propTypes = { |
||||
type: PropTypes.string, |
||||
}; |
||||
|
||||
TabsExample.defaultProps = { |
||||
type: '', |
||||
}; |
||||
|
After Width: | Height: | Size: 8.3 KiB |
Loading…
Reference in new issue