Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more tokens to theme set #5613

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions site/.dumi/theme/components/ColorPicker.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.color-picker-overlay {
// 重写颜色选择器样式

// 中间颜色滑轨部分
.flexbox-fix:nth-last-child(3) {
& > :last-child {
display: none;
}
}

// 中间 rgb 手动输入部分
.flexbox-fix:nth-last-child(2) {
input {
width: 100% !important;
color: rgba(0, 0, 0, 0.65);
text-align: center;
}
label {
color: rgba(0, 0, 0, 0.45) !important;
}
}

// 底部推荐色部分
.flexbox-fix:last-child {
& > div {
width: 18px !important;
height: 18px !important;
}
}
}
40 changes: 40 additions & 0 deletions site/.dumi/theme/components/ColorPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { SketchPicker } from 'react-color';
import { Dropdown } from 'antd';
import { BUILT_COLORS } from './builtins';

export function ColorPicker({ value, onChange, style = {}, className = '' }) {
function onColorChange(newColor) {
const {
rgb: { r, g, b, a },
} = newColor;
const alpha =
value === undefined || value.toLowerCase() === 'transparent' ? 1 : a;
onChange(`rgba(${r}, ${g}, ${b}, ${alpha})`);
}

return (
<Dropdown
overlay={
<SketchPicker
color={value}
className="config-color-picker-overlay"
onChangeComplete={onColorChange}
presetColors={BUILT_COLORS}
/>
}
trigger={['click', 'hover']}
>
<span
className={className}
style={{
background: value,
display: 'inline-block',
height: '100%',
cursor: 'pointer',
...style,
}}
></span>
</Dropdown>
);
}
13 changes: 13 additions & 0 deletions site/.dumi/theme/components/ConfigPanel.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,16 @@
margin-right: 8px;
}
}

.config-palette {
padding: 0px 0px !important;
width: 100%;
border-radius: 5px !important;
overflow: hidden;

& > span {
display: grid;
grid-template-columns: repeat(10, 10%);
height: 100%;
}
}
171 changes: 142 additions & 29 deletions site/.dumi/theme/components/ConfigPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
import * as React from 'react';
import { Button, Collapse, Radio } from 'antd';
import { Button, Collapse, Radio, Space, Divider, InputNumber } from 'antd';
import { UploadOutlined, CopyOutlined } from '@ant-design/icons';
import { stdlib } from '@antv/g2';
import { copyToClipboard } from '../utils/copyToBoard';
import { exportDataToLocal } from '../utils/exportDataToLocal';
import { ColorPicker } from './ColorPicker';
import {
BUILT_CATEGORIES,
BUILT_THEMES,
BUILT_COLOR_ATTRIBUTES,
BUILT_PADDING_ATTRIBUTES,
} from './builtins';
import './ConfigPanel.less';

const BUILT_THEMES = [
{ label: '默认风格', key: 'light' },
{ label: '暗色风格', key: 'dark' },
{ label: '学术风格', key: 'academy' },
];

function getG2Theme(theme: string | Record<string, any>) {
if (typeof theme === 'object') return theme;

const library = stdlib();
const themeToken = library[`theme.${theme}`]();
return themeToken;
}

const Operations = ({ theme }) => {
const Operations = ({ tokens }) => {
return (
<div className="config-panel-operations">
<div className="config-panel-title">Theme</div>
Expand All @@ -30,18 +22,15 @@ const Operations = ({ theme }) => {
type="primary"
className="config-panel-button"
onClick={() =>
exportDataToLocal(
JSON.stringify(getG2Theme(theme)),
'g2-theme.json',
)
exportDataToLocal(JSON.stringify(tokens), 'g2-theme.json')
}
>
导出
</Button>
<Button
icon={<CopyOutlined />}
className="config-panel-button"
onClick={() => copyToClipboard(JSON.stringify(getG2Theme(theme)))}
onClick={() => copyToClipboard(JSON.stringify(tokens))}
>
复制
</Button>
Expand All @@ -51,24 +40,148 @@ const Operations = ({ theme }) => {
};

export const ConfigPanel = (props) => {
const { theme, changeTheme, className = '' } = props;
const {
theme,
changeTheme,
tokens,
changeTokens,
changeSeed,
seed,
className = '',
} = props;
const { category10 } = tokens;
const encodePalette = (d) => d.join('-');
const decodePalette = (d) => d.split('-');

function onThemeChange(e) {
changeTheme(e.target.value);
}

function onPaletteChange(e) {
const { value } = e.target;
const palette = decodePalette(value);
const [defaultColor] = palette;
const { category20 } = tokens;
changeTokens({
category10: palette,
category20: [...palette, ...category20.slice(10)],
color: defaultColor,
});
}

function onColorChange(d, i) {
const { category10 } = tokens;
const newCategory10 = [...category10];
newCategory10.splice(i, 1, d);
onPaletteChange({ target: { value: newCategory10.join('-') } });
}

return (
<div className={`config-panel ${className}`}>
<Operations theme={theme} />
<Operations tokens={tokens} />
<Collapse collapsible="header" defaultActiveKey={['1']}>
<Collapse.Panel header="内置风格" key="1">
<Radio.Group
onChange={(e) => changeTheme(e.target.value)}
value={theme}
>
<Collapse.Panel header="风格" key="1">
<Radio.Group onChange={onThemeChange} value={theme}>
{BUILT_THEMES.map((d) => (
<Radio.Button value={d.key} key={d.key}>
{d.label}
</Radio.Button>
))}
</Radio.Group>
</Collapse.Panel>
<Collapse.Panel header="色板" key="2">
<Radio.Group
onChange={onPaletteChange}
value={encodePalette(category10)}
style={{ width: '100%' }}
>
<Space direction="vertical" style={{ width: '100%' }}>
{BUILT_CATEGORIES.map((category10) => (
<Radio.Button
value={encodePalette(category10)}
key={encodePalette(category10)}
className="config-palette"
>
{category10.map((d) => (
<span
style={{
background: d,
display: 'inline-block',
height: '100%',
}}
></span>
))}
</Radio.Button>
))}
</Space>
<Divider style={{ fontSize: 14, fontWeight: 'normal' }}>
自定义
</Divider>
<div
className="config-palette"
style={{
height: 32,
display: 'grid',
gridTemplateColumns: 'repeat(10, 10%)',
border: '1px solid #d9d9d9',
borderColor: BUILT_CATEGORIES.find(
(d) => encodePalette(d) === encodePalette(category10),
)
? '#d9d9d9'
: '#873bf4',
}}
>
{category10.map((d, i) => (
<ColorPicker value={d} onChange={(d) => onColorChange(d, i)} />
))}
</div>
</Radio.Group>
</Collapse.Panel>
<Collapse.Panel header="颜色" key="3">
<Space direction="vertical" style={{ width: '100%' }}>
{BUILT_COLOR_ATTRIBUTES.map((d) => (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<span>{d.name}</span>
<ColorPicker
value={seed[d.value]}
onChange={(color) => changeSeed(d.value, color)}
style={{
display: 'block',
height: 32,
width: 32,
borderRadius: 5,
border: '1px solid #d9d9d9',
}}
/>
</div>
))}
</Space>
</Collapse.Panel>
<Collapse.Panel header="间距" key="4">
<Space direction="vertical" style={{ width: '100%' }}>
{BUILT_PADDING_ATTRIBUTES.map((d) => (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<span>{d.name}</span>
<InputNumber
onChange={(value) => changeSeed(d.value, value)}
value={seed[d.value]}
/>
</div>
))}
</Space>
</Collapse.Panel>
</Collapse>
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions site/.dumi/theme/components/DemosView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Chart } from '@antv/g2';
import { examples } from '../examples';
import './DemosView.less';

const DemoContainer = ({ theme, className = '', render }) => {
const DemoContainer = ({ theme, className = '', render, tokens = {} }) => {
const domRef = React.useRef<HTMLDivElement | null>(null);
const chartRef = React.useRef<Chart | null>(null);

Expand All @@ -15,6 +15,7 @@ const DemoContainer = ({ theme, className = '', render }) => {
theme,
width: container.clientWidth,
height: container.clientHeight,
tokens,
});
}

Expand All @@ -26,7 +27,7 @@ const DemoContainer = ({ theme, className = '', render }) => {
chart.destroy();
init(theme);
}
}, [theme]);
}, [theme, tokens]);

React.useLayoutEffect(() => {
const el = domRef.current;
Expand All @@ -47,7 +48,7 @@ const DemoContainer = ({ theme, className = '', render }) => {
return <div ref={domRef} className={className} />;
};

export const DemosView = ({ theme, className = '' }) => {
export const DemosView = ({ theme, tokens, className = '' }) => {
function openExample(example) {
// @ts-ignore
window.open(`/examples/${example.link}`);
Expand All @@ -66,6 +67,7 @@ export const DemosView = ({ theme, className = '' }) => {
className="demo-container"
theme={theme}
render={example.render}
tokens={tokens}
/>
</div>
</Badge.Ribbon>
Expand Down
Loading
Loading