new icon display

This commit is contained in:
HeskeyBaozi 2018-09-01 16:16:11 +08:00 committed by 偏右
parent 2600d8a4ca
commit 2a54d80639
12 changed files with 312 additions and 57 deletions

View File

@ -11,35 +11,11 @@ Semantic vector graphics.
> Click the icon and copy the code.
### Directional Icons
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="direction" />, mountNode);
import IconDisplay from 'site/theme/template/IconDisplay';
ReactDOM.render(<IconDisplay />, mountNode);
```
### Suggested Icons
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="suggestion" />, mountNode);
```
### Application Icons
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
```
### Brand and Logos
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
```
## API
### Icon

View File

@ -16,32 +16,9 @@ toc: false
> 点击图标即可复制代码。
### 方向性图标
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="direction" />, mountNode);
```
### 提示建议性图标
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="suggestion" />, mountNode);
```
### 网站通用图标
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="other" />, mountNode);
```
### 品牌与标识
```__react
import IconSet from 'site/theme/template/IconSet';
ReactDOM.render(<IconSet className="icons" catigory="logo" />, mountNode);
import IconDisplay from 'site/theme/template/IconDisplay';
ReactDOM.render(<IconDisplay />, mountNode);
```
## API

View File

@ -95,6 +95,7 @@
"@types/prop-types": "^15.5.4",
"@types/react": "^16.0.0",
"@types/react-dom": "^16.0.0",
"@types/react-intl": "^2.3.10",
"@types/react-slick": "^0.23.2",
"@yesmeck/offline-plugin": "^5.0.5",
"ansi-styles": "^3.2.0",

View File

@ -88,5 +88,10 @@ module.exports = {
'app.publish.old-version-guide': 'If you need documentation of older version, please visit ',
'app.publish.old-version-tips': ', or switch version with the select at header navigation.',
'app.docs.color.pick-primary': 'Pick your primary color',
'app.docs.components.icon.pick-theme': 'Select the Icon Theme',
'app.docs.components.icon.category.direction': 'Directional Icons',
'app.docs.components.icon.category.suggestion': 'Suggested Icons',
'app.docs.components.icon.category.other': 'Application Icons',
'app.docs.components.icon.category.logo': 'Brand and Logos',
},
};

View File

@ -1,5 +1,5 @@
ul.anticons-list {
margin: 40px 0;
margin: 10px 0;
list-style: none;
overflow: hidden;
li {

View File

@ -0,0 +1,60 @@
import * as React from 'react';
import { ThemeType } from '../../../../components/icon';
import CopyableIcon from './CopyableIcon';
import { injectIntl, InjectedIntlProps } from 'react-intl';
import { CategoriesKeys } from './fields';
interface CategoryProps extends InjectedIntlProps {
title: CategoriesKeys;
icons: string[];
theme: ThemeType;
newIcons: string[];
}
interface CategoryState {
justCopied: string | null;
}
class Category extends React.Component<CategoryProps, CategoryState> {
state = {
justCopied: null,
};
onCopied = (type: string) => {
this.setState({ justCopied: type }, () => {
setTimeout(() => {
this.setState({ justCopied: null });
}, 2000);
});
}
render() {
const {
icons, title,
theme, newIcons,
intl: { messages },
} = this.props;
const items = icons.map((name) => {
return (
<CopyableIcon
key={name}
type={name}
theme={theme}
isNew={newIcons.indexOf(name) >= 0}
justCopied={this.state.justCopied}
onCopied={this.onCopied}
/>
);
});
return (
<div>
<h3>{messages[`app.docs.components.icon.category.${title}`]}</h3>
<ul className={'anticons-list'}>
{items}
</ul>
</div>
);
}
}
export default injectIntl(Category);

View File

@ -0,0 +1,34 @@
import * as React from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { Icon, Badge } from 'antd';
import { ThemeType } from '../../../../components/icon';
export interface CopyableIconProps {
type: string;
theme: ThemeType;
isNew: boolean;
justCopied: string | null;
onCopied: (type: string) => any;
}
const CopyableIcon: React.SFC<CopyableIconProps> = ({
type, theme, isNew, justCopied, onCopied,
}) => {
return (
<CopyToClipboard
text={`<Icon type="${type}" theme="${theme}" />`}
onCopy={() => onCopied(type)}
>
<li className={justCopied === type ? 'copied' : ''}>
<Icon type={type} theme={theme} />
<span className="anticon-class">
<Badge dot={isNew}>
{type}
</Badge>
</span>
</li>
</CopyToClipboard>
);
};
export default CopyableIcon;

View File

@ -0,0 +1,80 @@
export const categories = {
direction: [
'step-backward', 'step-forward', 'fast-backward',
'fast-forward', 'shrink', 'arrows-alt', 'down', 'up', 'left',
'right', 'caret-up', 'caret-down', 'caret-left', 'caret-right',
'up-circle', 'down-circle', 'left-circle', 'right-circle',
'double-right', 'double-left', 'verticle-left', 'verticle-right',
'forward', 'backward', 'rollback', 'enter', 'retweet',
'swap', 'swap-left', 'swap-right', 'arrow-up', 'arrow-down',
'arrow-left', 'arrow-right', 'play-circle',
'up-square', 'down-square', 'left-square', 'right-square',
'login', 'logout', 'menu-fold', 'menu-unfold',
],
suggestion: [
'question', 'question-circle',
'plus', 'plus-circle', 'pause',
'pause-circle', 'minus',
'minus-circle', 'plus-square', 'minus-square',
'info', 'info-circle',
'exclamation', 'exclamation-circle',
'close', 'close-circle', 'close-square',
'check', 'check-circle',
'check-square',
'clock-circle', 'warning',
],
other: [
'lock', 'unlock', 'area-chart', 'pie-chart', 'bar-chart',
'dot-chart', 'bars', 'book', 'calendar', 'cloud', 'cloud-download',
'code', 'copy', 'credit-card', 'delete', 'desktop',
'download', 'edit', 'ellipsis', 'file', 'file-text',
'file-unknown', 'file-pdf', 'file-word', 'file-excel',
'file-jpg', 'file-ppt', 'file-markdown', 'file-add',
'folder', 'folder-open', 'folder-add', 'hdd', 'frown',
'meh', 'smile', 'inbox',
'laptop', 'appstore', 'line-chart', 'link',
'mail', 'mobile', 'notification', 'paper-clip', 'picture',
'poweroff', 'reload', 'search', 'setting', 'share-alt',
'shopping-cart', 'tablet', 'tag', 'tags',
'to-top', 'upload', 'user', 'video-camera',
'home', 'loading', 'loading-3-quarters',
'cloud-upload',
'star', 'heart', 'environment',
'eye', 'camera', 'save', 'team',
'solution', 'phone', 'filter', 'exception', 'export',
'customer-service', 'qrcode', 'scan', 'like',
'dislike', 'message', 'pay-circle',
'calculator', 'pushpin',
'bulb', 'select', 'switcher', 'rocket', 'bell', 'disconnect',
'database', 'compass', 'barcode', 'hourglass', 'key',
'flag', 'layout', 'printer', 'sound', 'usb', 'skin', 'tool',
'sync', 'wifi', 'car', 'schedule', 'user-add', 'user-delete',
'usergroup-add', 'usergroup-delete', 'man', 'woman', 'shop',
'gift', 'idcard', 'medicine-box', 'red-envelope', 'coffee',
'copyright', 'trademark', 'safety', 'wallet', 'bank', 'trophy',
'contacts', 'global', 'shake', 'api', 'fork', 'dashboard', 'form',
'table', 'profile',
],
logo: [
'android', 'apple', 'windows',
'ie', 'chrome', 'github', 'aliwangwang',
'dingding',
'weibo-square', 'weibo-circle', 'taobao-circle', 'html5',
'weibo', 'twitter', 'wechat', 'youtube', 'alipay-circle',
'taobao', 'skype', 'qq', 'medium-workmark', 'gitlab', 'medium',
'linkedin', 'google-plus', 'dropbox', 'facebook', 'codepen',
'amazon', 'google', 'codepen-circle', 'alipay', 'ant-design',
'aliyun', 'zhihu', 'slack', 'slack-square', 'behance',
'behance-square', 'dribbble', 'dribbble-square',
'instagram', 'yuque',
],
};
export interface Categories {
direction: string[];
suggestion: string[];
other: string[];
logo: string[];
}
export type CategoriesKeys = keyof Categories;

View File

@ -1,21 +1,90 @@
import * as React from 'react';
import { ThemeType } from '../../../../components/icon';
import manifest from '@ant-design/icons/lib/manifest';
import { Manifest, ThemeType as ThemeFolderType } from '@ant-design/icons/lib/types';
import Category from './Category';
import { Radio, Icon } from 'antd';
import { RadioChangeEvent } from 'antd/lib/radio/interface';
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
import { categories, Categories, CategoriesKeys } from './fields';
import { injectIntl, InjectedIntlProps } from 'react-intl';
interface IconDisplayProps {
icons: Array<{ category: string, names: string[] }>;
interface IconDisplayProps extends InjectedIntlProps {
}
interface IconDisplayState {
theme: ThemeType;
}
export default class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
class IconDisplay extends React.Component<IconDisplayProps, IconDisplayState> {
static cagetories: Categories = categories;
static newIconNames: string[] = [];
static themeTypeMapper: { [key: string]: ThemeFolderType } = {
filled: 'fill',
outlined: 'outline',
twoTone: 'twotone',
};
state: IconDisplayState = {
theme: 'outlined',
};
getComputedDisplayList() {
return Object.keys(IconDisplay.cagetories)
.map(
(category: CategoriesKeys) => ({
category,
icons: IconDisplay.cagetories[category]
.filter((name) => manifest[IconDisplay.themeTypeMapper[this.state.theme]].indexOf(name) !== -1),
}),
)
.filter(({ icons }) => Boolean(icons.length));
}
handleChangeTheme = (e: RadioChangeEvent) => {
this.setState({
theme: e.target.value as ThemeType,
});
}
renderCategories(list: Array<{ category: string, icons: string[] }>) {
return list.map(({ category, icons }) => {
return (
<Category
key={category}
title={category}
icons={icons}
theme={this.state.theme}
newIcons={IconDisplay.newIconNames}
/>
);
});
}
render() {
// wip
return null;
const { intl: { messages } } = this.props;
const list = this.getComputedDisplayList();
return (
<div>
<h3>{messages['app.docs.components.icon.pick-theme']}</h3>
<Radio.Group value={this.state.theme} onChange={this.handleChangeTheme}>
<Radio.Button value="filled">
<Icon component={FilledIcon} /> Filled
</Radio.Button>
<Radio.Button value="outlined">
<Icon component={OutlinedIcon} /> Outlined
</Radio.Button>
<Radio.Button value="twoTone">
<Icon component={TwoToneIcon} /> Two Tone
</Radio.Button>
</Radio.Group>
{this.renderCategories(list)}
</div>
);
}
}
export default injectIntl(IconDisplay);

View File

@ -0,0 +1,46 @@
import * as React from 'react';
export const FilledIcon: React.SFC = (props: any) => {
const path = 'M864 64H160C107 64 64 107 64 160v' +
'704c0 53 43 96 96 96h704c53 0 96-43 96-96V16' +
'0c0-53-43-96-96-96z';
return (
<svg
{...props}
viewBox="0 0 1024 1024"
>
<path d={path} />
</svg>
);
};
export const OutlinedIcon: React.SFC = (props: any) => {
const path = 'M864 64H160C107 64 64 107 64 160v7' +
'04c0 53 43 96 96 96h704c53 0 96-43 96-96V160c' +
'0-53-43-96-96-96z m-12 800H172c-6.6 0-12-5.4-' +
'12-12V172c0-6.6 5.4-12 12-12h680c6.6 0 12 5.4' +
' 12 12v680c0 6.6-5.4 12-12 12z';
return (
<svg
{...props}
viewBox="0 0 1024 1024"
>
<path d={path} />
</svg>
);
};
export const TwoToneIcon: React.SFC = (props: any) => {
const path = 'M16 512c0 273.932 222.066 496 496 49' +
'6s496-222.068 496-496S785.932 16 512 16 16 238.' +
'066 16 512z m496 368V144c203.41 0 368 164.622 3' +
'68 368 0 203.41-164.622 368-368 368z';
return (
<svg
{...props}
viewBox="0 0 1024 1024"
>
<path d={path} />
</svg>
);
};

View File

@ -88,5 +88,10 @@ module.exports = {
'app.publish.old-version-guide': '如果您还需要使用旧版,请查阅 ',
'app.publish.old-version-tips': ',也可通过页面右上角的文档版本选择框进行切换。',
'app.docs.color.pick-primary': '选择你的主色',
'app.docs.components.icon.pick-theme': '选择图标主题风格',
'app.docs.components.icon.category.direction': '方向性图标',
'app.docs.components.icon.category.suggestion': '提示建议性图标',
'app.docs.components.icon.category.other': '网站通用图标',
'app.docs.components.icon.category.logo': '品牌和标识',
},
};

View File

@ -100,3 +100,5 @@ declare module 'intersperse';
declare module "raf";
declare module "react-lifecycles-compat";
declare module "react-copy-to-clipboard";