mirror of
https://github.com/mathuo/dockview
synced 2025-01-22 17:35:57 +00:00
chore: storybook docs
This commit is contained in:
parent
b7d1dad0da
commit
65a8095e27
6
packages/splitview-demo/package-lock.json
generated
6
packages/splitview-demo/package-lock.json
generated
@ -6538,9 +6538,9 @@
|
||||
}
|
||||
},
|
||||
"dockview": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.11.tgz",
|
||||
"integrity": "sha512-Rj6pu9ul+AGrCtSNpv/KE6yRHYA89EoRsZfP1TUW73rNkuaUIH0iK+tJglSvoFVxwJFn6oW33erT1IzWfgXIxw=="
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/dockview/-/dockview-0.0.12.tgz",
|
||||
"integrity": "sha512-BQW1yUdVjpKgJaGxkpZyAogkEr//ka/lN+8JM+IgWMszEcry6UXj1T+zcaW6DOo7ZEtgHCsdPvlyEYthMgrPWA=="
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "3.0.0",
|
||||
|
16
packages/splitview-demo/src/resources/dockview-logo.svg
Normal file
16
packages/splitview-demo/src/resources/dockview-logo.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 30H45V70H5C2.23858 70 0 67.7614 0 65V30Z" fill="#1E90FF"/>
|
||||
<path d="M45 30H70V65C70 67.7614 67.7614 70 65 70H45V30Z" fill="#FF1E90"/>
|
||||
<rect x="45" y="30" width="25" height="5" fill="#AC1160"/>
|
||||
<rect x="45" y="30" width="10" height="5" fill="#EB1D85"/>
|
||||
<rect y="30" width="45" height="5" fill="#1863AD"/>
|
||||
<rect y="30" width="10" height="5" fill="#1A84EC"/>
|
||||
<rect x="10" y="30" width="10" height="5" fill="#1973CB"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H30V30H0V5Z" fill="#1EFF8D"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H30V5H0V5Z" fill="#1BCA71"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H10V5H0V5Z" fill="#1DF387"/>
|
||||
<path d="M30 0H65C67.7614 0 70 2.23858 70 5V30H30V0Z" fill="#FF8D1E"/>
|
||||
<path d="M30 0H65C67.7614 0 70 2.23858 70 5V5H30V0Z" fill="#BA6817"/>
|
||||
<rect x="30" width="10" height="5" fill="#EF841B"/>
|
||||
<rect x="40" width="10" height="5" fill="#DC7A1B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 974 B |
8
packages/splitview-demo/src/resources/gridview-logo.svg
Normal file
8
packages/splitview-demo/src/resources/gridview-logo.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 55H20V70H5C2.23858 70 0 67.7614 0 65V55Z" fill="#8D1EFF"/>
|
||||
<path d="M45 55H70V65C70 67.7614 67.7614 70 65 70H45V55Z" fill="#FF1E90"/>
|
||||
<path d="M20 55H45V70H20V55Z" fill="#90FF1E"/>
|
||||
<path d="M0 30H70V55H0V30Z" fill="#1E90FF"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H30V30H0V5Z" fill="#1EFF8D"/>
|
||||
<path d="M30 0H65C67.7614 0 70 2.23858 70 5V30H30V0Z" fill="#FF8D1E"/>
|
||||
</svg>
|
After Width: | Height: | Size: 479 B |
25
packages/splitview-demo/src/resources/logo.svg
Normal file
25
packages/splitview-demo/src/resources/logo.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<svg width="200" height="70" viewBox="0 0 200 70" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 52.1429H60V60C60 62.7614 57.7614 65 55 65H5C2.23858 65 0 62.7614 0 60V52.1429Z" fill="#FF1E90"/>
|
||||
<path d="M0 30.7143H60V52.1428H0V30.7143Z" fill="#1E90FF"/>
|
||||
<path d="M0 10C0 7.23857 2.23858 5 5 5H55C57.7614 5 60 7.23858 60 10V30.7143H0V10Z" fill="#1EFF8D"/>
|
||||
<path d="M65 55H85V70H70C67.2386 70 65 67.7614 65 65V55Z" fill="#8D1EFF"/>
|
||||
<path d="M110 55H135V65C135 67.7614 132.761 70 130 70H110V55Z" fill="#FF1E90"/>
|
||||
<path d="M85 55H110V70H85V55Z" fill="#90FF1E"/>
|
||||
<path d="M65 30H135V55H65V30Z" fill="#1E90FF"/>
|
||||
<path d="M65 5C65 2.23858 67.2386 0 70 0H95V30H65V5Z" fill="#1EFF8D"/>
|
||||
<path d="M95 0H130C132.761 0 135 2.23858 135 5V30H95V0Z" fill="#FF8D1E"/>
|
||||
<path d="M140 30.7143H178.571V65H145C142.239 65 140 62.7614 140 60V30.7143Z" fill="#1E90FF"/>
|
||||
<path d="M178.571 30.7143H200V60C200 62.7614 197.761 65 195 65H178.571V30.7143Z" fill="#FF1E90"/>
|
||||
<rect x="178.571" y="30.7143" width="21.4286" height="4.28572" fill="#AC1160"/>
|
||||
<rect x="178.571" y="30.7143" width="8.57143" height="4.28572" fill="#EB1D85"/>
|
||||
<rect x="140" y="30.7143" width="38.5714" height="4.28572" fill="#1863AD"/>
|
||||
<rect x="140" y="30.7143" width="8.57143" height="4.28572" fill="#1A84EC"/>
|
||||
<rect x="148.571" y="30.7143" width="8.57143" height="4.28572" fill="#1973CB"/>
|
||||
<path d="M140 10C140 7.23858 142.239 5 145 5H165.714V30.7143H140V10Z" fill="#1EFF8D"/>
|
||||
<path d="M140 9.28572C140 6.91878 141.919 5 144.286 5H165.714V9.28572H140V9.28572Z" fill="#1BCA71"/>
|
||||
<path d="M140 9.28572C140 6.91878 141.919 5 144.286 5H148.571V9.28572H140V9.28572Z" fill="#1DF387"/>
|
||||
<path d="M165.714 5H195C197.761 5 200 7.23858 200 10V30.7143H165.714V5Z" fill="#FF8D1E"/>
|
||||
<path d="M165.714 5H195.714C198.081 5 200 6.91878 200 9.28572V9.28572H165.714V5Z" fill="#BA6817"/>
|
||||
<rect x="165.714" y="5" width="8.57143" height="4.28572" fill="#EF841B"/>
|
||||
<rect x="174.286" y="5" width="8.57143" height="4.28572" fill="#DC7A1B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
8
packages/splitview-demo/src/resources/paneview-logo.svg
Normal file
8
packages/splitview-demo/src/resources/paneview-logo.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 55H70V65C70 67.7614 67.7614 70 65 70H5C2.23858 70 0 67.7614 0 65V55Z" fill="#FF1E90"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H65C67.7614 0 70 2.23858 70 5V50H0V5Z" fill="#1EFF8D"/>
|
||||
<path d="M0 40H70V65C70 67.7614 67.7614 70 65 70H5C2.23858 70 0 67.7614 0 65V40Z" fill="#FF1E90"/>
|
||||
<rect y="35" width="70" height="5" fill="#AC1160"/>
|
||||
<path d="M0 30H70V35H0V30Z" fill="#1863AD"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H65C67.7614 0 70 2.23858 70 5V5H0V5Z" fill="#1BCA71"/>
|
||||
</svg>
|
After Width: | Height: | Size: 583 B |
5
packages/splitview-demo/src/resources/splitview-logo.svg
Normal file
5
packages/splitview-demo/src/resources/splitview-logo.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 55H70V65C70 67.7614 67.7614 70 65 70H5C2.23858 70 0 67.7614 0 65V55Z" fill="#FF1E90"/>
|
||||
<path d="M0 30H70V55H0V30Z" fill="#1E90FF"/>
|
||||
<path d="M0 5C0 2.23858 2.23858 0 5 0H65C67.7614 0 70 2.23858 70 5V30H0V5Z" fill="#1EFF8D"/>
|
||||
</svg>
|
After Width: | Height: | Size: 340 B |
@ -1,50 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './button.css';
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const Button = ({ primary, backgroundColor, size, label, ...props }) => {
|
||||
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
|
||||
style={backgroundColor && { backgroundColor }}
|
||||
{...props}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
Button.propTypes = {
|
||||
/**
|
||||
* Is this the principal call to action on the page?
|
||||
*/
|
||||
primary: PropTypes.bool,
|
||||
/**
|
||||
* What background color to use
|
||||
*/
|
||||
backgroundColor: PropTypes.string,
|
||||
/**
|
||||
* How large should the button be?
|
||||
*/
|
||||
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||
/**
|
||||
* Button contents
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
backgroundColor: null,
|
||||
primary: false,
|
||||
size: 'medium',
|
||||
onClick: undefined,
|
||||
};
|
@ -1,36 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Button } from './Button';
|
||||
|
||||
export default {
|
||||
title: 'Example/Button',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => <Button {...args} />;
|
||||
|
||||
export const Primary = Template.bind({});
|
||||
Primary.args = {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Secondary = Template.bind({});
|
||||
Secondary.args = {
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Large = Template.bind({});
|
||||
Large.args = {
|
||||
size: 'large',
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Small = Template.bind({});
|
||||
Small.args = {
|
||||
size: 'small',
|
||||
label: 'Button',
|
||||
};
|
@ -1,38 +0,0 @@
|
||||
import React from 'react';
|
||||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
|
||||
import { Story, Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
import { Button, ButtonProps } from './Button';
|
||||
|
||||
export default {
|
||||
title: 'Example/Button',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<ButtonProps> = (args) => <Button {...args} />;
|
||||
|
||||
export const Primary = Template.bind({});
|
||||
Primary.args = {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Secondary = Template.bind({});
|
||||
Secondary.args = {
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Large = Template.bind({});
|
||||
Large.args = {
|
||||
size: 'large',
|
||||
label: 'Button',
|
||||
};
|
||||
|
||||
export const Small = Template.bind({});
|
||||
Small.args = {
|
||||
size: 'small',
|
||||
label: 'Button',
|
||||
};
|
@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
import './button.css';
|
||||
|
||||
export interface ButtonProps {
|
||||
/**
|
||||
* Is this the principal call to action on the page?
|
||||
*/
|
||||
primary?: boolean;
|
||||
/**
|
||||
* What background color to use
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* How large should the button be?
|
||||
*/
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
/**
|
||||
* Button contents
|
||||
*/
|
||||
label: string;
|
||||
/**
|
||||
* Optional click handler
|
||||
*/
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary UI component for user interaction
|
||||
*/
|
||||
export const Button: React.FC<ButtonProps> = ({
|
||||
primary = false,
|
||||
size = 'medium',
|
||||
backgroundColor,
|
||||
label,
|
||||
...props
|
||||
}) => {
|
||||
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
|
||||
style={{ backgroundColor }}
|
||||
{...props}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
};
|
@ -1,52 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Button } from './Button';
|
||||
import './header.css';
|
||||
|
||||
export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => (
|
||||
<header>
|
||||
<div className="wrapper">
|
||||
<div>
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<path
|
||||
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
|
||||
fill="#FFF"
|
||||
/>
|
||||
<path
|
||||
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
|
||||
fill="#555AB9"
|
||||
/>
|
||||
<path
|
||||
d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
|
||||
fill="#91BAF8"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<h1>Acme</h1>
|
||||
</div>
|
||||
<div>
|
||||
{user ? (
|
||||
<Button size="small" onClick={onLogout} label="Log out" />
|
||||
) : (
|
||||
<>
|
||||
<Button size="small" onClick={onLogin} label="Log in" />
|
||||
<Button primary size="small" onClick={onCreateAccount} label="Sign up" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
Header.propTypes = {
|
||||
user: PropTypes.shape({}),
|
||||
onLogin: PropTypes.func.isRequired,
|
||||
onLogout: PropTypes.func.isRequired,
|
||||
onCreateAccount: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
user: null,
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Header } from './Header';
|
||||
|
||||
export default {
|
||||
title: 'Example/Header',
|
||||
component: Header,
|
||||
};
|
||||
|
||||
const Template = (args) => <Header {...args} />;
|
||||
|
||||
export const LoggedIn = Template.bind({});
|
||||
LoggedIn.args = {
|
||||
user: {},
|
||||
};
|
||||
|
||||
export const LoggedOut = Template.bind({});
|
||||
LoggedOut.args = {};
|
@ -1,20 +0,0 @@
|
||||
import React from 'react';
|
||||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
|
||||
import { Story, Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
import { Header, HeaderProps } from './Header';
|
||||
|
||||
export default {
|
||||
title: 'Example/Header',
|
||||
component: Header,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<HeaderProps> = (args) => <Header {...args} />;
|
||||
|
||||
export const LoggedIn = Template.bind({});
|
||||
LoggedIn.args = {
|
||||
user: {},
|
||||
};
|
||||
|
||||
export const LoggedOut = Template.bind({});
|
||||
LoggedOut.args = {};
|
@ -1,47 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Button } from './Button';
|
||||
import './header.css';
|
||||
|
||||
export interface HeaderProps {
|
||||
user?: {};
|
||||
onLogin: () => void;
|
||||
onLogout: () => void;
|
||||
onCreateAccount: () => void;
|
||||
}
|
||||
|
||||
export const Header: React.FC<HeaderProps> = ({ user, onLogin, onLogout, onCreateAccount }) => (
|
||||
<header>
|
||||
<div className="wrapper">
|
||||
<div>
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<path
|
||||
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
|
||||
fill="#FFF"
|
||||
/>
|
||||
<path
|
||||
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
|
||||
fill="#555AB9"
|
||||
/>
|
||||
<path
|
||||
d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
|
||||
fill="#91BAF8"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<h1>Acme</h1>
|
||||
</div>
|
||||
<div>
|
||||
{user ? (
|
||||
<Button size="small" onClick={onLogout} label="Log out" />
|
||||
) : (
|
||||
<>
|
||||
<Button size="small" onClick={onLogin} label="Log in" />
|
||||
<Button primary size="small" onClick={onCreateAccount} label="Sign up" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
@ -7,201 +7,61 @@ import Flow from './assets/flow.svg';
|
||||
import Plugin from './assets/plugin.svg';
|
||||
import Repo from './assets/repo.svg';
|
||||
import StackAlt from './assets/stackalt.svg';
|
||||
import Splitview from '../resources/splitview-logo.svg';
|
||||
import Gridview from '../resources/gridview-logo.svg';
|
||||
import Dockview from '../resources/dockview-logo.svg';
|
||||
import Paneview from '../resources/paneview-logo.svg';
|
||||
import './introduction.css';
|
||||
|
||||
<Meta title="Example/Introduction" />
|
||||
<Meta title="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;
|
||||
}
|
||||
# Dockview
|
||||
|
||||
.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/storybook-examples` 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="subheading">Components</div>
|
||||
|
||||
<div className="link-list">
|
||||
<a className="link-item" href="https://storybook.js.org/docs/react/api/presets" 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://www.learnstorybook.com" 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/UUt2PJb" 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/storybook-examples/welcome.mdx</code>
|
||||
<a
|
||||
className="link-item"
|
||||
href="https://storybook.js.org/docs/react/api/presets"
|
||||
target="_blank"
|
||||
>
|
||||
<img src={Splitview} alt="splitview" />
|
||||
<span>
|
||||
<strong>Splitview</strong>
|
||||
Vertical or horiziontal splitview panels
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className="link-item"
|
||||
href="https://storybook.js.org/docs/react/configure/webpack"
|
||||
target="_blank"
|
||||
>
|
||||
<img src={Gridview} alt="gridview" />
|
||||
<span>
|
||||
<strong>Gridview</strong>
|
||||
Splitviews within splitviews
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
className="link-item"
|
||||
href="https://storybook.js.org/docs/react/configure/styling-and-css"
|
||||
target="_blank"
|
||||
>
|
||||
<img src={Dockview} alt="dockview" />
|
||||
<span>
|
||||
<strong>Dockview</strong>
|
||||
Dockable and tabular panels within Gridviews
|
||||
</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={Paneview} alt="paneview" />
|
||||
<span>
|
||||
<strong>Paneview</strong>
|
||||
An extension to splitviews allowing collapsable panels with a persistant header section
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -1,71 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Header } from './Header';
|
||||
import './page.css';
|
||||
|
||||
export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => (
|
||||
<article>
|
||||
<Header user={user} onLogin={onLogin} onLogout={onLogout} onCreateAccount={onCreateAccount} />
|
||||
|
||||
<section>
|
||||
<h2>Pages in Storybook</h2>
|
||||
<p>
|
||||
We recommend building UIs with a{' '}
|
||||
<a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
|
||||
<strong>component-driven</strong>
|
||||
</a>{' '}
|
||||
process starting with atomic components and ending with pages.
|
||||
</p>
|
||||
<p>
|
||||
Render pages with mock data. This makes it easy to build and review page states without
|
||||
needing to navigate to them in your app. Here are some handy patterns for managing page data
|
||||
in Storybook:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Use a higher-level connected component. Storybook helps you compose such data from the
|
||||
"args" of child component stories
|
||||
</li>
|
||||
<li>
|
||||
Assemble data in the page component from your services. You can mock these services out
|
||||
using Storybook.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Get a guided tutorial on component-driven development at{' '}
|
||||
<a href="https://www.learnstorybook.com" target="_blank" rel="noopener noreferrer">
|
||||
Learn Storybook
|
||||
</a>
|
||||
. Read more in the{' '}
|
||||
<a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer">
|
||||
docs
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<div className="tip-wrapper">
|
||||
<span className="tip">Tip</span> Adjust the width of the canvas with the{' '}
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<path
|
||||
d="M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z"
|
||||
id="a"
|
||||
fill="#999"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
Viewports addon in the toolbar
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
);
|
||||
Page.propTypes = {
|
||||
user: PropTypes.shape({}),
|
||||
onLogin: PropTypes.func.isRequired,
|
||||
onLogout: PropTypes.func.isRequired,
|
||||
onCreateAccount: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Page.defaultProps = {
|
||||
user: null,
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Page } from './Page';
|
||||
import * as HeaderStories from './Header.stories';
|
||||
|
||||
export default {
|
||||
title: 'Example/Page',
|
||||
component: Page,
|
||||
};
|
||||
|
||||
const Template = (args) => <Page {...args} />;
|
||||
|
||||
export const LoggedIn = Template.bind({});
|
||||
LoggedIn.args = {
|
||||
...HeaderStories.LoggedIn.args,
|
||||
};
|
||||
|
||||
export const LoggedOut = Template.bind({});
|
||||
LoggedOut.args = {
|
||||
...HeaderStories.LoggedOut.args,
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
import React from 'react';
|
||||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
|
||||
import { Story, Meta } from '@storybook/react/types-6-0';
|
||||
|
||||
import { Page, PageProps } from './Page';
|
||||
import * as HeaderStories from './Header.stories';
|
||||
|
||||
export default {
|
||||
title: 'Example/Page',
|
||||
component: Page,
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<PageProps> = (args) => <Page {...args} />;
|
||||
|
||||
export const LoggedIn = Template.bind({});
|
||||
LoggedIn.args = {
|
||||
...HeaderStories.LoggedIn.args,
|
||||
};
|
||||
|
||||
export const LoggedOut = Template.bind({});
|
||||
LoggedOut.args = {
|
||||
...HeaderStories.LoggedOut.args,
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Header } from './Header';
|
||||
import './page.css';
|
||||
|
||||
export interface PageProps {
|
||||
user?: {};
|
||||
onLogin: () => void;
|
||||
onLogout: () => void;
|
||||
onCreateAccount: () => void;
|
||||
}
|
||||
|
||||
export const Page: React.FC<PageProps> = ({ user, onLogin, onLogout, onCreateAccount }) => (
|
||||
<article>
|
||||
<Header user={user} onLogin={onLogin} onLogout={onLogout} onCreateAccount={onCreateAccount} />
|
||||
|
||||
<section>
|
||||
<h2>Pages in Storybook</h2>
|
||||
<p>
|
||||
We recommend building UIs with a{' '}
|
||||
<a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
|
||||
<strong>component-driven</strong>
|
||||
</a>{' '}
|
||||
process starting with atomic components and ending with pages.
|
||||
</p>
|
||||
<p>
|
||||
Render pages with mock data. This makes it easy to build and review page states without
|
||||
needing to navigate to them in your app. Here are some handy patterns for managing page data
|
||||
in Storybook:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Use a higher-level connected component. Storybook helps you compose such data from the
|
||||
"args" of child component stories
|
||||
</li>
|
||||
<li>
|
||||
Assemble data in the page component from your services. You can mock these services out
|
||||
using Storybook.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Get a guided tutorial on component-driven development at{' '}
|
||||
<a href="https://www.learnstorybook.com" target="_blank" rel="noopener noreferrer">
|
||||
Learn Storybook
|
||||
</a>
|
||||
. Read more in the{' '}
|
||||
<a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer">
|
||||
docs
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<div className="tip-wrapper">
|
||||
<span className="tip">Tip</span> Adjust the width of the canvas with the{' '}
|
||||
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<path
|
||||
d="M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z"
|
||||
id="a"
|
||||
fill="#999"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
Viewports addon in the toolbar
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
);
|
@ -1,30 +0,0 @@
|
||||
.storybook-button {
|
||||
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-weight: 700;
|
||||
border: 0;
|
||||
border-radius: 3em;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
}
|
||||
.storybook-button--primary {
|
||||
color: white;
|
||||
background-color: #1ea7fd;
|
||||
}
|
||||
.storybook-button--secondary {
|
||||
color: #333;
|
||||
background-color: transparent;
|
||||
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
|
||||
}
|
||||
.storybook-button--small {
|
||||
font-size: 12px;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
.storybook-button--medium {
|
||||
font-size: 14px;
|
||||
padding: 11px 20px;
|
||||
}
|
||||
.storybook-button--large {
|
||||
font-size: 16px;
|
||||
padding: 12px 24px;
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
import {
|
||||
CompositeDisposable,
|
||||
DockviewApi,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
GroupChangeKind,
|
||||
IDockviewPanelProps,
|
||||
IWatermarkPanelProps,
|
||||
PanelCollection,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Meta } from '@storybook/react';
|
||||
import 'dockview/dist/styles.css';
|
||||
|
||||
const components: PanelCollection<IDockviewPanelProps> = {
|
||||
default: (props) => {
|
||||
return (
|
||||
<div style={{ padding: '10px', height: '100%' }}>
|
||||
This content is not within an IFrame
|
||||
</div>
|
||||
);
|
||||
},
|
||||
iframe: (props) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: '25px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
margin: '0px 4px',
|
||||
}}
|
||||
>
|
||||
The contents below is within an iFrame
|
||||
</div>
|
||||
<iframe
|
||||
src="./"
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
boxSizing: 'border-box',
|
||||
border: '1px solid red',
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Iframe = (props: {
|
||||
onEvent: (name: string) => void;
|
||||
theme: string;
|
||||
hideBorders: boolean;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<DockviewApi>();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.onGridEvent((e) => props.onEvent(e.kind));
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
title: 'Standard Panel',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
title: 'IFrame Panel',
|
||||
component: 'iframe',
|
||||
});
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
hideBorders={props.hideBorders}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Dockview/Iframe',
|
||||
component: Iframe,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
||||
return (
|
||||
<div style={{ height: '100vh', fontFamily: 'Arial' }}>
|
||||
<Component />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
],
|
||||
args: { theme: 'dockview-theme-light' },
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['dockview-theme-dark', 'dockview-theme-light'],
|
||||
},
|
||||
},
|
||||
onEvent: { action: 'onEvent' },
|
||||
},
|
||||
} as Meta;
|
@ -0,0 +1,108 @@
|
||||
import {
|
||||
CompositeDisposable,
|
||||
DockviewApi,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
GroupChangeKind,
|
||||
IDockviewPanelProps,
|
||||
IWatermarkPanelProps,
|
||||
PanelCollection,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Meta } from '@storybook/react';
|
||||
import 'dockview/dist/styles.css';
|
||||
|
||||
const components: PanelCollection<IDockviewPanelProps> = {
|
||||
default: (props) => {
|
||||
return (
|
||||
<div style={{ padding: '10px', height: '100%' }}>hello world</div>
|
||||
);
|
||||
},
|
||||
iframe: (props) => {
|
||||
return (
|
||||
<div style={{ height: '100%', width: '100%' }}>
|
||||
<iframe src="./" style={{ height: '100%', width: '100%' }}>
|
||||
Hello world
|
||||
</iframe>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Simple = (props: {
|
||||
onEvent: (name: string) => void;
|
||||
theme: string;
|
||||
hideBorders: boolean;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<DockviewApi>();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.onGridEvent((e) => props.onEvent(e.kind));
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
position: { referencePanel: 'panel1', direction: 'right' },
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel4',
|
||||
component: 'default',
|
||||
position: { referencePanel: 'panel3', direction: 'below' },
|
||||
});
|
||||
|
||||
// event.api.getPanel('panel1').api;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
hideBorders={props.hideBorders}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Dockview/Simple',
|
||||
component: Simple,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
||||
return (
|
||||
<div style={{ height: '100vh', fontFamily: 'Arial' }}>
|
||||
<Component />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
],
|
||||
args: { theme: 'dockview-theme-light' },
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['dockview-theme-dark', 'dockview-theme-light'],
|
||||
},
|
||||
},
|
||||
onEvent: { action: 'onEvent' },
|
||||
},
|
||||
} as Meta;
|
@ -29,99 +29,7 @@ const components: PanelCollection<IDockviewPanelProps> = {
|
||||
},
|
||||
};
|
||||
|
||||
export const IFrame = (props: {
|
||||
onEvent: (name: string) => void;
|
||||
theme: string;
|
||||
hideBorders: boolean;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<DockviewApi>();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.onGridEvent((e) => props.onEvent(e.kind));
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'iframe',
|
||||
});
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
hideBorders={props.hideBorders}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Simple = (props: {
|
||||
onEvent: (name: string) => void;
|
||||
theme: string;
|
||||
hideBorders: boolean;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<DockviewApi>();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.onGridEvent((e) => props.onEvent(e.kind));
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
position: { referencePanel: 'panel1', direction: 'right' },
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel4',
|
||||
component: 'default',
|
||||
position: { referencePanel: 'panel3', direction: 'below' },
|
||||
});
|
||||
|
||||
// event.api.getPanel('panel1').api;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
hideBorders={props.hideBorders}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Watermark = (props: IWatermarkPanelProps) => {
|
||||
const [size, setSize] = React.useState<number>(props.containerApi.size);
|
||||
@ -226,8 +134,8 @@ export const CustomWatermark = (props: {
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Dockview',
|
||||
component: Simple,
|
||||
title: 'Dockview/CustomWatermark',
|
||||
component: CustomWatermark,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
@ -99,7 +99,7 @@ export const Simple = (props: {
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Gridview',
|
||||
title: 'Gridview/Simple',
|
||||
component: Simple,
|
||||
decorators: [
|
||||
(Component) => {
|
@ -1,26 +0,0 @@
|
||||
.wrapper {
|
||||
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 900;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
margin: 6px 0 6px 10px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
button + button {
|
||||
margin-left: 10px;
|
||||
}
|
100
packages/splitview-demo/src/stories/introduction.css
Normal file
100
packages/splitview-demo/src/stories/introduction.css
Normal file
@ -0,0 +1,100 @@
|
||||
.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;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
section {
|
||||
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
padding: 48px 20px;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 900;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
margin: 0 0 4px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1ea7fd;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 30px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.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 svg {
|
||||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
margin-right: 4px;
|
||||
vertical-align: top;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.tip-wrapper svg path {
|
||||
fill: #1ea7fd;
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
import {
|
||||
PanelCollection,
|
||||
PaneviewReact,
|
||||
PaneviewApi,
|
||||
PaneviewReadyEvent,
|
||||
IPaneviewPanelProps,
|
||||
SerializedPaneview,
|
||||
PanelConstraintChangeEvent,
|
||||
CompositeDisposable,
|
||||
PanelDimensionChangeEvent,
|
||||
ExpansionEvent,
|
||||
FocusEvent,
|
||||
ActiveEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Story, Meta } from '@storybook/react';
|
||||
import 'dockview/dist/styles.css';
|
||||
|
||||
const components: PanelCollection<IPaneviewPanelProps> = {
|
||||
default: (props) => {
|
||||
const [constraints, setConstraints] = React.useState<
|
||||
PanelConstraintChangeEvent
|
||||
>();
|
||||
const [dimensions, setDimensions] = React.useState<
|
||||
PanelDimensionChangeEvent
|
||||
>();
|
||||
const [expansionState, setExpansionState] = React.useState<
|
||||
ExpansionEvent
|
||||
>();
|
||||
const [active, setActive] = React.useState<ActiveEvent>();
|
||||
const [focus, setFocus] = React.useState<FocusEvent>();
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposables = new CompositeDisposable(
|
||||
props.api.onDidConstraintsChange(setConstraints),
|
||||
props.api.onDidDimensionsChange(setDimensions),
|
||||
props.api.onDidExpansionChange(setExpansionState),
|
||||
props.api.onDidActiveChange(setActive),
|
||||
props.api.onDidFocusChange(setFocus)
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposables.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const resize = () => {
|
||||
props.api.setSize({ size: 300 });
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
backgroundColor: props.color,
|
||||
boxSizing: 'border-box',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}
|
||||
>
|
||||
<div>Contraints:</div>
|
||||
<div>{`maximumSize: ${constraints?.maximumSize} minimumSize: ${constraints?.minimumSize}`}</div>
|
||||
<div>Dimesions:</div>
|
||||
<div>{`width: ${dimensions?.width} height: ${dimensions?.height}`}</div>
|
||||
<div>Expansion:</div>
|
||||
<div>{`expanded: ${expansionState?.isExpanded}`}</div>
|
||||
<div>Active:</div>
|
||||
<div>{`active: ${active?.isActive}`}</div>
|
||||
<div>Focus:</div>
|
||||
<div>{`focused: ${focus?.isFocused}`}</div>
|
||||
</div>
|
||||
<button onClick={resize}>Resize</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Deserialization = (props: {
|
||||
theme: string;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<PaneviewApi>();
|
||||
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.fromJSON({
|
||||
size: 100,
|
||||
views: [
|
||||
{
|
||||
size: 80,
|
||||
expanded: true,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
title: 'Panel 1',
|
||||
},
|
||||
},
|
||||
{
|
||||
size: 20,
|
||||
expanded: true,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
title: 'Panel 2',
|
||||
},
|
||||
},
|
||||
{
|
||||
size: 20,
|
||||
expanded: false,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
title: 'Panel 3',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
event.api.getPanel('panel2')?.api.setSize({ size: 60 });
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Paneview/Deserialization',
|
||||
component: Deserialization,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
||||
return (
|
||||
<div style={{ height: '100vh', fontFamily: 'Arial' }}>
|
||||
<Component />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
],
|
||||
args: { theme: 'dockview-theme-light', disableAutoResizing: false },
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['dockview-theme-dark', 'dockview-theme-light'],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Meta;
|
@ -77,122 +77,7 @@ const components: PanelCollection<IPaneviewPanelProps> = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Simple = (props: {
|
||||
theme: string;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<PaneviewApi>();
|
||||
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
params: { color: 'red' },
|
||||
title: 'Panel1',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
params: { color: 'green' },
|
||||
title: 'Panel 2',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
params: { color: 'purple' },
|
||||
title: 'Panel 3',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Deserialization = (props: {
|
||||
theme: string;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<PaneviewApi>();
|
||||
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.fromJSON({
|
||||
size: 100,
|
||||
views: [
|
||||
{
|
||||
size: 80,
|
||||
expanded: true,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
title: 'Panel 1',
|
||||
},
|
||||
},
|
||||
{
|
||||
size: 20,
|
||||
expanded: true,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
title: 'Panel 2',
|
||||
},
|
||||
},
|
||||
{
|
||||
size: 20,
|
||||
expanded: false,
|
||||
minimumSize: 100,
|
||||
data: {
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
title: 'Panel 3',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
event.api.getPanel('panel2')?.api.setSize({ size: 60 });
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const LocalStorageSave = (props: {
|
||||
export const Localstoragesave = (props: {
|
||||
theme: string;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
@ -271,8 +156,8 @@ export const LocalStorageSave = (props: {
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Paneview',
|
||||
component: Simple,
|
||||
title: 'Paneview/Localstoragesave',
|
||||
component: Localstoragesave,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
@ -0,0 +1,153 @@
|
||||
import {
|
||||
PanelCollection,
|
||||
PaneviewReact,
|
||||
PaneviewApi,
|
||||
PaneviewReadyEvent,
|
||||
IPaneviewPanelProps,
|
||||
SerializedPaneview,
|
||||
PanelConstraintChangeEvent,
|
||||
CompositeDisposable,
|
||||
PanelDimensionChangeEvent,
|
||||
ExpansionEvent,
|
||||
FocusEvent,
|
||||
ActiveEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Story, Meta } from '@storybook/react';
|
||||
import 'dockview/dist/styles.css';
|
||||
|
||||
const components: PanelCollection<IPaneviewPanelProps> = {
|
||||
default: (props) => {
|
||||
const [constraints, setConstraints] = React.useState<
|
||||
PanelConstraintChangeEvent
|
||||
>();
|
||||
const [dimensions, setDimensions] = React.useState<
|
||||
PanelDimensionChangeEvent
|
||||
>();
|
||||
const [expansionState, setExpansionState] = React.useState<
|
||||
ExpansionEvent
|
||||
>();
|
||||
const [active, setActive] = React.useState<ActiveEvent>();
|
||||
const [focus, setFocus] = React.useState<FocusEvent>();
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposables = new CompositeDisposable(
|
||||
props.api.onDidConstraintsChange(setConstraints),
|
||||
props.api.onDidDimensionsChange(setDimensions),
|
||||
props.api.onDidExpansionChange(setExpansionState),
|
||||
props.api.onDidActiveChange(setActive),
|
||||
props.api.onDidFocusChange(setFocus)
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposables.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const resize = () => {
|
||||
props.api.setSize({ size: 300 });
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
backgroundColor: props.color,
|
||||
boxSizing: 'border-box',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}
|
||||
>
|
||||
<div>Contraints:</div>
|
||||
<div>{`maximumSize: ${constraints?.maximumSize} minimumSize: ${constraints?.minimumSize}`}</div>
|
||||
<div>Dimesions:</div>
|
||||
<div>{`width: ${dimensions?.width} height: ${dimensions?.height}`}</div>
|
||||
<div>Expansion:</div>
|
||||
<div>{`expanded: ${expansionState?.isExpanded}`}</div>
|
||||
<div>Active:</div>
|
||||
<div>{`active: ${active?.isActive}`}</div>
|
||||
<div>Focus:</div>
|
||||
<div>{`focused: ${focus?.isFocused}`}</div>
|
||||
</div>
|
||||
<button onClick={resize}>Resize</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Simple = (props: {
|
||||
theme: string;
|
||||
disableAutoResizing: boolean;
|
||||
}) => {
|
||||
const api = React.useRef<PaneviewApi>();
|
||||
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.layout(window.innerWidth, window.innerHeight);
|
||||
api.current = event.api;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
params: { color: 'red' },
|
||||
title: 'Panel1',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
params: { color: 'green' },
|
||||
title: 'Panel 2',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel3',
|
||||
component: 'default',
|
||||
params: { color: 'purple' },
|
||||
title: 'Panel 3',
|
||||
minimumBodySize: 100,
|
||||
});
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
api.current?.layout(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
className={props.theme}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
disableAutoResizing={props.disableAutoResizing}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Paneview/Simple',
|
||||
component: Simple,
|
||||
decorators: [
|
||||
(Component) => {
|
||||
document.body.style.padding = '0px';
|
||||
return (
|
||||
<div style={{ height: '100vh', fontFamily: 'Arial' }}>
|
||||
<Component />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
],
|
||||
args: { theme: 'dockview-theme-light', disableAutoResizing: false },
|
||||
argTypes: {
|
||||
theme: {
|
||||
control: {
|
||||
type: 'select',
|
||||
options: ['dockview-theme-dark', 'dockview-theme-light'],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Meta;
|
||||
|
@ -291,7 +291,7 @@ export const LocalStorageSave = (props: {
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'Splitview',
|
||||
title: 'Splitview/Simple',
|
||||
component: Simple,
|
||||
decorators: [
|
||||
(Component) => {
|
Loading…
Reference in New Issue
Block a user