mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
docs: Update 4.0 site (#20290)
* init recommend block * init design pages * home frames * add background banner * hello, Hitu makes the animation * add media query * add images * update types * add declare * preload support * update ignore * additional ignore site Home lint * update ignore * add hover effect * adjust alt of bannber * adjust lang & card shadow * fix typo * adjust desc * hitu in english * article add link * Certainty is hitu * Meaning Hitu * Growth with Hitu * Natural Hitu * slow down of Natural * adjust speed of icons * New Meaning animation * adjust animation duration * update card link * update link * values doc * replace images * faster Growth * update values * fix lint * all slow down * adjust padding * update icons * adjust margin * update images * adjust montion * adjust by designer * update pages * update design prod * update articles * update site style * update doc * update images * update style * lint fix * adjust liner color * github text color update * adjust margin of title * mobile design * update design sub card * update style * less lint * update images * design card auto height * update img * update logo transition * adjust card style * adjust style to fix 184 * adjust nav style * category it * slow down of logo * update style * hide video link * hitu article * use img of hitu * update docs * style lint * update Hitu layout doc * update images * speed up logo * update link * clean up * clean up * update doc * adjust doc * update images
This commit is contained in:
parent
29b4b7004e
commit
abf215a982
@ -6,6 +6,7 @@ components/**/*.jsx
|
||||
# Docs templates
|
||||
site/theme/template/IconDisplay/*.js
|
||||
site/theme/template/IconDisplay/*.jsx
|
||||
site/theme/template/Home/**/*.jsx
|
||||
typings
|
||||
es/**/*
|
||||
lib/**/*
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -38,8 +38,12 @@ components/**/*.jsx
|
||||
!components/**/__tests__/**/*.js
|
||||
!components/**/__tests__/**/*.js.snap
|
||||
/.history
|
||||
*.tmp
|
||||
|
||||
# Docs templates
|
||||
site/theme/template/IconDisplay/*.js
|
||||
site/theme/template/IconDisplay/*.jsx
|
||||
site/theme/template/IconDisplay/fields.js
|
||||
*.tmp
|
||||
|
||||
site/theme/template/Home/**/*.jsx
|
||||
|
||||
|
@ -25,4 +25,4 @@ When part of the page is waiting for asynchronous data or during a rendering pro
|
||||
|
||||
- `Spin.setDefaultIndicator(indicator: ReactNode)`
|
||||
|
||||
You can define default spin element globally.
|
||||
You can define default spin element globally.
|
||||
|
@ -21,7 +21,10 @@ describe('Table.filter', () => {
|
||||
{
|
||||
text: 'Title',
|
||||
value: 'title',
|
||||
children: [{ text: 'Designer', value: 'designer' }, { text: 'Coder', value: 'coder' }],
|
||||
children: [
|
||||
{ text: 'Designer', value: 'designer' },
|
||||
{ text: 'Coder', value: 'coder' },
|
||||
],
|
||||
},
|
||||
],
|
||||
onFilter: filterFn,
|
||||
@ -468,7 +471,10 @@ describe('Table.filter', () => {
|
||||
// });
|
||||
|
||||
describe('should support value types', () => {
|
||||
[['Light', 93], ['Bamboo', false]].forEach(([text, value]) => {
|
||||
[
|
||||
['Light', 93],
|
||||
['Bamboo', false],
|
||||
].forEach(([text, value]) => {
|
||||
it(`${typeof value} type`, () => {
|
||||
const onFilter = jest.fn();
|
||||
const filters = [{ text, value }];
|
||||
@ -552,7 +558,10 @@ describe('Table.filter', () => {
|
||||
title="name"
|
||||
dataIndex="name"
|
||||
key="name"
|
||||
filters={[{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }]}
|
||||
filters={[
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
]}
|
||||
filteredValue={filters.name}
|
||||
onFilter={filterFn}
|
||||
/>
|
||||
@ -591,7 +600,10 @@ describe('Table.filter', () => {
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
filters: [{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }],
|
||||
filters: [
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
],
|
||||
onFilter: filterFn,
|
||||
filteredValue: ['Jack'],
|
||||
},
|
||||
@ -621,7 +633,10 @@ describe('Table.filter', () => {
|
||||
columns: [
|
||||
{
|
||||
...column,
|
||||
filters: [{ text: 'Jack', value: 'Jack' }, { text: 'Lucy', value: 'Lucy' }],
|
||||
filters: [
|
||||
{ text: 'Jack', value: 'Jack' },
|
||||
{ text: 'Lucy', value: 'Lucy' },
|
||||
],
|
||||
},
|
||||
],
|
||||
onChange: handleChange,
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 2
|
||||
title: Alignment
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 2
|
||||
title: 对齐
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: Visual
|
||||
category: Global Style
|
||||
order: 0
|
||||
title: Colors
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: 视觉
|
||||
category: 全局样式
|
||||
order: 0
|
||||
title: 色彩
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 3
|
||||
title: Contrast
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 3
|
||||
title: 对比
|
||||
---
|
||||
|
@ -1,7 +1,10 @@
|
||||
---
|
||||
category:
|
||||
zh-CN: 模式
|
||||
en-US: Patterns
|
||||
zh-CN: 设计模式
|
||||
en-US: Design Patterns
|
||||
type:
|
||||
zh-CN: 全局规则
|
||||
en-US: Global Rules
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 文案
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 5
|
||||
title: Make it Direct
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 5
|
||||
title: 直截了当
|
||||
---
|
||||
|
@ -9,7 +9,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
<div class="resource-cards">
|
||||
<a target="_blank" href="https://github.com/ant-design/ant-design/releases/download/resource/Ant.Design.Components.3.12.0.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/pKfDZnzocrbAOSzDQOQq.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*XsDPQrwQZwEAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -20,7 +20,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="https://github.com/ant-design/ant-design/releases/download/resource/Ant.Design.Mobile.Template.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="41" src="https://gw.alipayobjects.com/zos/rmsportal/rFMdPVzabtQwxONUuVFr.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*CBq9R5XenxEAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Mobile Components</span>
|
||||
@ -29,7 +29,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="https://github.com/ant-design/ant-design/releases/download/resource/Ant.Design.Pro.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/ibCZMxKsTUzDbwTEdcTC.svg">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*JL4NSrPh8QsAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design Pro</span>
|
||||
@ -38,7 +38,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="http://library.ant.design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="50" src="https://gw.alipayobjects.com/zos/rmsportal/TXrKQUJBTuwSTGimGYYn.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*7-yRTpL6l0MAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design Library</span>
|
||||
@ -47,7 +47,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="http://kitchen.alipay.com" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/ATYZYtJhchhONKObIwXT.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*JSzfToJBU_8AAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -59,7 +59,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="https://landing.ant.design/docs/download" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/EAHlyTmYeDtTkZIPbUnP.svg">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*On5cQ7NoNL8AAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -70,7 +70,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="http://ux.ant.design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="64" src="https://gw.alipayobjects.com/zos/rmsportal/yMULSUQQyhoEGrCXlovN.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*l_PmRLizBTMAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant UX</span>
|
||||
@ -79,7 +79,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="https://www.xiaopiu.com/topic/ant-design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="72" src="https://img.xiaopiu.com/userImages/img753167822272f8.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zPTWTLt72YIAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design Prototype (xiaopiu)</span>
|
||||
@ -100,7 +100,7 @@ Please find below some of the design resources and tools about Ant Design that w
|
||||
</a>
|
||||
<a target="_blank" href="https://store.framer.com/package/bhaveshchow/ant-design-system" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://raw.githubusercontent.com/bhaveshc20/antdesign-framer/master/framerant-icon.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*W5TbRLtV1YYAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
|
@ -11,7 +11,7 @@ title: 设计资源
|
||||
<div class="resource-cards">
|
||||
<a target="_blank" href="https://github.com/ant-design/ant-design/releases/download/resource/Ant.Design.Components.3.12.0.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/pKfDZnzocrbAOSzDQOQq.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*XsDPQrwQZwEAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -22,7 +22,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="http://p.tb.cn/rmsportal_3436_AntDesignMobile_20Template_20V1.0.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="41" src="https://gw.alipayobjects.com/zos/rmsportal/rFMdPVzabtQwxONUuVFr.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*CBq9R5XenxEAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Mobile Components</span>
|
||||
@ -31,7 +31,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="https://github.com/ant-design/ant-design/releases/download/resource/Ant.Design.Pro.sketch" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/ibCZMxKsTUzDbwTEdcTC.svg">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*JL4NSrPh8QsAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design Pro</span>
|
||||
@ -40,7 +40,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="http://library.ant.design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="50" src="https://gw.alipayobjects.com/zos/rmsportal/TXrKQUJBTuwSTGimGYYn.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*7-yRTpL6l0MAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design Library @Axure</span>
|
||||
@ -49,7 +49,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="http://kitchen.alipay.com" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/ATYZYtJhchhONKObIwXT.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*JSzfToJBU_8AAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -61,7 +61,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="https://landing.ant.design/docs/download-cn" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://gw.alipayobjects.com/zos/rmsportal/EAHlyTmYeDtTkZIPbUnP.svg">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*On5cQ7NoNL8AAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
@ -72,7 +72,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="http://ux.ant.design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="64" src="https://gw.alipayobjects.com/zos/rmsportal/yMULSUQQyhoEGrCXlovN.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*l_PmRLizBTMAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant UX</span>
|
||||
@ -81,7 +81,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="https://www.xiaopiu.com/topic/ant-design" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="72" src="https://img.xiaopiu.com/userImages/img753167822272f8.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zPTWTLt72YIAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">Ant Design 原型(xiaopiu)</span>
|
||||
@ -90,7 +90,7 @@ title: 设计资源
|
||||
</a>
|
||||
<a target="_blank" href="https://www.antforfigma.com" class="resource-card">
|
||||
<div class="resource-card-icon">
|
||||
<img width="65" src="https://antforfigma.com/images/antforfigma-icon.png">
|
||||
<img width="65" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*W5TbRLtV1YYAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
<div class="resource-card-content">
|
||||
<span class="resource-card-title">
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Patterns
|
||||
category: Design Patterns
|
||||
type: Global Rules
|
||||
order: 11
|
||||
title: Feedback
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 模式
|
||||
category: 设计模式
|
||||
type: 全局规则
|
||||
order: 11
|
||||
title: 反馈
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: Visual
|
||||
category: Global Style
|
||||
order: 3
|
||||
title: Font
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: 视觉
|
||||
category: 全局样式
|
||||
order: 3
|
||||
title: 字体
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: Visual
|
||||
category: Global Style
|
||||
order: 4
|
||||
title: Icons
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: 视觉
|
||||
category: 全局样式
|
||||
order: 4
|
||||
title: 图标
|
||||
---
|
||||
|
6
docs/spec/illustration.en-US.md
Normal file
6
docs/spec/illustration.en-US.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
order: 5
|
||||
title: Illustration
|
||||
---
|
||||
|
||||
### Translation is in progress
|
106
docs/spec/illustration.zh-CN.md
Normal file
106
docs/spec/illustration.zh-CN.md
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
order: 5
|
||||
title: 插画
|
||||
---
|
||||
|
||||
# HiTu 图形化
|
||||
|
||||
<div style="text-align:center;">
|
||||
<img alt="General" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*WzMpTIP8R6gAAAAAAAAAAABkARQnAQ" />
|
||||
</div>
|
||||
|
||||
## 项目背景
|
||||
|
||||
图形化是品牌识别度的关键核心元素,在互联网产品,线下物料中使用中无处不在。与单纯的文案信息不同,图形化在直观描述固有信息的同时塑造情感背景,使用户更具沉浸感和共情性。提升产品用户体验的同时来完成商业目标。图形化的风格缤纷复杂,插画师的个人风格明显,不同的设计师在图形化的工作协同中,风格很难复现,而单纯由一名插画师去完成整体业务的图形化也存在一定风险。所以图形化体系在保持品牌一致性和提升工作效率,规避风险上显得尤为重要。
|
||||
|
||||
<div style="text-align:center;">
|
||||
<img alt="Background" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*rSUBTL8hv9sAAAAAAAAAAABkARQnAQ" />
|
||||
</div>
|
||||
|
||||
## 设计原则
|
||||
|
||||
从最底层的设计价值观到最上层的设计方法,HiTu 沿袭了 Ant Design 的 ETCG 的设计思路,将图形化资产组件化,分可形成模板,合则可拼搭成案例。为设计值提供强大的灵活性和定制性。
|
||||
|
||||
<div style="text-align:center;">
|
||||
<img alt="Design principle" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*WKEzS5-_zYAAAAAAAAAAAABkARQnAQ" />
|
||||
</div>
|
||||
|
||||
#### HiTu 金字塔模型
|
||||
|
||||
基于科技,确定,自然,未来的四层品牌策略,我们将抽象的概念具象化。代表的技术底层的科技能力为产品,体验和未来提供技术支撑和可能性。所以图例一一对应,我们具象化了人物和产品,体验及未来之间的关系。他们之间不同的组合方式可以满足不同的业务场景诉求。
|
||||
|
||||
<div style="text-align:center;">
|
||||
<img alt="Pyramid model" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*K0AETKiR__EAAAAAAAAAAABkARQnAQ" />
|
||||
</div>
|
||||
|
||||
## 颜色
|
||||
|
||||
### 海兔色板
|
||||
|
||||
<img class="preview-img no-padding" align="right" description="海兔色板" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*5ZE6RrjW-jQAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
海兔的色彩配色体系是基于 Ant Design 色板的场景应用,与 UI 色彩体系的应用会有所不同。图形化的配色体系会相对更加的灵活可变。基于 Ant Design 的基础色板我们进行了明度的调整,扩大图形化设计的宽容度,使用选择时候更加高效易用,由于是出自 Ant Design 的色彩体系,和其他 UI 资产完美兼容。
|
||||
|
||||
### 海兔默认资产颜色
|
||||
|
||||
<img class="preview-img no-padding" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*t4D6QaFM2DAAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
通过搜资调研,我们发现在企业级产品中。色彩的使用上蓝色,白色会占很大的比重。我们选取了色板中最具科技感,且代表着探索,钻研感的极客蓝作为我们的主色。
|
||||
|
||||
<br />
|
||||
|
||||
<img class="preview-img no-padding" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*fI2hSI8v0bgAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
基于 Adobe Color 的三元取色工具,和 3D 立体马赛克球,结合我们自己的海兔色板。可以轻松得到了我们 Dedult 版本的基础色板。
|
||||
|
||||
<br />
|
||||
|
||||
# 设计资产
|
||||
|
||||
### 人物组件
|
||||
|
||||
<img class="preview-img" align="right" alt="基于自然的人物头身比例" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*09cDSb88sjgAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
基于自然的设计原则,我们不推荐使用 Q 班卡通和过于夸张艺术化的设计风格。相比之下,接近自然真人头人比例的风格更是我们所推荐的。
|
||||
|
||||
<br />
|
||||
|
||||
<img class="preview-img" align="right" alt="9 种常见职业角色设计" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*xjrVRoIZtYwAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
同时,我们结合情感化设计,将 9 种常见的职业角色进行人物设计吗。结合职业本身的一些特质,我们也赋予了他们不同气质特质,来满足各种业务场景的使用。
|
||||
|
||||
<br />
|
||||
|
||||
<img class="preview-img" align="right" alt="角色设计人物分解" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*uoxQS6xUq5UAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" alt="HiTu 骨骼系统" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*9-cATIWgPx8AAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" alt="人物姿态复用" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*F-QpQL91SvYAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
有了基础的人物设计,我们将人物进行分解,然后搭配设计好的骨骼系统。来为人物增加各种姿态动作的复用和延展。
|
||||
|
||||
<br />
|
||||
|
||||
### 元素组件
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*-LbbSads11EAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*FcRKRLwPIz4AAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
记忆点源于与众不同,专业感源于整齐划一。元素组件指代的是业务场景中一些业务元素,状态元素图形化的世界缤纷多变,我们希望在保持统一性的同时不去限时设计者的创意空间,元素组件的设计上,我们为了保持一定的韵律感,推荐设计师在 1024\*1024 的网格中绘制组件,且圆角的大小保持 8 的倍数关系。
|
||||
|
||||
<br />
|
||||
|
||||
# 设计应用
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*puHVQJEe-oIAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*W-PzSadIFeAAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*OJoaQ77tczIAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
<img class="preview-img" align="right" src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*IySSSoBaGPYAAAAAAAAAAABkARQnAQ" />
|
||||
|
||||
有了丰富的资产组件,我们应该如何使用呢?在 HiTu 的设计使用指引中,我推荐设计者在使用资产的过程中构建 Z 轴向的空间概念,将整幅画面拆分成前景,中景以及背景三个层次,在组件的排放时候,前景凸显重要的元素(如人,核心元素组件等),中间交代所处环境,背景则渲染烘托氛围,在颜色的使用和透明上也是前景的饱和度和透明度最高,逐级降低。
|
||||
|
||||
<br />
|
@ -5,22 +5,26 @@ title: Introduction
|
||||
---
|
||||
|
||||
<div style="text-align:center;margin:40px 0;">
|
||||
<img width="600" src="https://gw.alipayobjects.com/zos/rmsportal/lcamFWetlMgLkLmDUgmZ.png">
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*P0S-QIRUbsUAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
|
||||
In the process of internal desktop applications development, many different design specs and implementations would be involved, which might cause designers and developers difficulties and duplication and reduce the efficiency of development. After massive project practice and summaries, Ant Design, a design language for background applications, is refined by Ant UED Team, which aims to uniform the user interface specs for internal background projects, lower the unnecessary cost of design differences and implementation and liberate the resources of design and front-end development.
|
||||
Ant's enterprise-level products are an enormous and complex system with a large number and complex functions. Designers and developers often need to respond fast due to frequent changes and concurrency. Meanwhile, there are many similar pages and components in these products. Some stable and highly reusable content can obtain through abstraction.
|
||||
|
||||
Ant Design which is specially created for internal desktop applications, is committed to improving the experience of users and product designers. User interface designers and user experience designers, collectively, are considered as product designers, and the boundaries of product managers, interaction designers, visual designers, front-end developers and develop engineers are blurred. Taking advantage of unitary specifications, Ant Design makes design and prototype more simple and accessible for all project members, which comprehensively promotes experience and development efficiency of background applications and products.
|
||||
With the trend of commercialization, more and more enterprise-level products begin to pursue a better user experience. With such an ultimate goal, we (Ant Financial User Experience Department) have gradually polished a design system(Ant Design) for enterprise-level products through a huge quantity of project practices and summaries. Based on the four design values of 『 natural 』, 『certain』, 『meaningful』, and 『growing』, through modular solutions, reduce redundant production costs and allow designers to focus on better user experience.
|
||||
|
||||
---
|
||||
|
||||
## Guidelines and Resources
|
||||
|
||||
We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.
|
||||
We provide comprehensive design guidelines, best practices, design resources, and design tools to help designers produce high-quality product prototypes.
|
||||
|
||||
- [Principles](/docs/spec/proximity)
|
||||
- [Patterns](/docs/pattern/navigation)
|
||||
- [Resource Download](/docs/resource/download)
|
||||
- [Design value](/docs/spec/values)
|
||||
- [Design pattern](/docs/spec/overview)
|
||||
- [Visualization](/docs/spec/visual)
|
||||
- [Illustration](/docs/spec/illustration)
|
||||
- [Design resources](/docs/spec/download)
|
||||
- [Sketch toolbox](http://kitchen.alipay.com/)
|
||||
- [Articles](/docs/spec/article)
|
||||
|
||||
## Front-end Implementation
|
||||
|
||||
|
@ -5,23 +5,26 @@ title: 介绍
|
||||
---
|
||||
|
||||
<div style="text-align:center;margin:40px 0;">
|
||||
<img width="600" src="https://gw.alipayobjects.com/zos/rmsportal/lcamFWetlMgLkLmDUgmZ.png">
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*P0S-QIRUbsUAAAAAAAAAAABkARQnAQ">
|
||||
</div>
|
||||
|
||||
蚂蚁的企业级产品是一个庞大且复杂的体系。这类产品不仅量级巨大且功能复杂,而且变动和并发频繁,常常需要设计与开发能够快速的做出响应。同时这类产品中有存在很多类似的页面以及组件,可以通过抽象得到一些稳定且高复用性的内容。
|
||||
蚂蚁的企业级产品是一个庞大且复杂的系统,数量多且功能复杂,而且变动和并发频繁,常常需要设计者与开发者能快速做出响应。同时这类产品中有存在很多类似的页面以及组件,可以通过抽象得到一些稳定且高复用性的内容。
|
||||
|
||||
随着商业化的趋势,越来越多的企业级产品对更好的用户体验有了进一步的要求。带着这样的一个终极目标,我们(蚂蚁金服体验技术部)经过大量的项目实践和总结,逐步打磨出一个服务于企业级产品的设计体系 Ant Design。基于『确定』和『自然』的设计价值观,通过模块化的解决方案,降低冗余的生产成本,让设计者专注于更好的用户体验。
|
||||
随着商业化的趋势,越来越多的企业级产品对更好的用户体验有了进一步的要求。带着这样的一个终极目标,我们(蚂蚁金服体验技术部)经过大量项目实践和总结,逐步打磨出一个服务于企业级产品的设计体系 —— Ant Design。基于『自然』、『确定性』、『意义感』、『生长性』四大[设计价值观](/docs/spec/values),通过模块化解决方案,降低冗余的生产成本,让设计者专注于更好的用户体验。
|
||||
|
||||
---
|
||||
|
||||
## 设计资源
|
||||
|
||||
我们提供完善的设计原则、最佳实践和设计资源文件([Sketch](https://ant.design/docs/spec/download-cn) 和 [Axure](https://ant.design/docs/spec/download-cn)),来帮助业务快速设计出高质量的产品原型。
|
||||
我们提供完善的设计指引、最佳实践、设计资源和设计工具,来帮助设计者快速产出高质量产品原型。
|
||||
|
||||
- [设计原则](/docs/spec/proximity)
|
||||
- [设计价值观](/docs/spec/values)
|
||||
- [设计模式](/docs/spec/overview)
|
||||
- [可视化](/docs/spec/visual)
|
||||
- [插画](/docs/spec/illustration)
|
||||
- [设计资源](/docs/spec/download)
|
||||
- [Sketch 工具集](http://kitchen.alipay.com/)
|
||||
- [文章](/docs/spec/article)
|
||||
|
||||
## 前端实现
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 8
|
||||
title: Provide an Invitation
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 8
|
||||
title: 提供邀请
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: Visual
|
||||
category: Global Style
|
||||
order: 2
|
||||
title: Layout
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: 视觉
|
||||
category: 全局样式
|
||||
order: 2
|
||||
title: 布局
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 7
|
||||
title: Keep it Lightweight
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 7
|
||||
title: 简化交互
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 5
|
||||
order: 4
|
||||
title: Motion
|
||||
---
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 5
|
||||
order: 4
|
||||
title: 动效
|
||||
---
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Patterns
|
||||
category: Design Patterns
|
||||
type: Global Rules
|
||||
order: 8
|
||||
title: Navigation
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 模式
|
||||
category: 设计模式
|
||||
type: 全局规则
|
||||
order: 8
|
||||
title: 导航
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: Patterns
|
||||
category: Design Patterns
|
||||
order: 0
|
||||
title: Overview
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
category: 模式
|
||||
category: 设计模式
|
||||
order: 0
|
||||
title: 概览
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 1
|
||||
title: Proximity
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 1
|
||||
title: 亲密性
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 10
|
||||
title: React Immediately
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 10
|
||||
title: 即时反应
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 4
|
||||
title: Repetition
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 4
|
||||
title: 重复
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 6
|
||||
title: Stay on the Page
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 6
|
||||
title: 足不出户
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: Principles
|
||||
category: Design Patterns
|
||||
type: Principles
|
||||
order: 9
|
||||
title: Use Transition
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
category: 原则
|
||||
category: 设计模式
|
||||
type: 原则
|
||||
order: 9
|
||||
title: 巧用过渡
|
||||
---
|
||||
|
@ -4,33 +4,59 @@ order: 1
|
||||
title: Design Values
|
||||
---
|
||||
|
||||
Ant Design provides a practical evaluation of better design for both designers of Ant Design and designers who are using it. At the same time, it builds a foundation for design principles and design patterns which could provide guideline and general solutions for specified design goal.
|
||||
Ant Design Design values provide internal criteria for designers to evaluate design quality, inspire and arouse ant design's design principles and patterns, which in turn leads to providing guidance and general solutions for specific design problems.
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/mdn/miniapp_social/afts/img/A*8KqgSKde8PMAAAAAAAAAAABkARQnAQ" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*sGufTKB_F5QAAAAAAAAAAABkARQnAQ" alt="General" />
|
||||
</div>
|
||||
|
||||
Here is our design values:
|
||||
On the persistence of "design values", there are 4 features make Ant Design out of the ordinary:
|
||||
|
||||
## Nature
|
||||
## Natural
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/cdaxgaTMQCGTqjdlwwgt.png" alt="Nature" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ" alt="Natural" />
|
||||
</div>
|
||||
|
||||
As a part of nature, it will have deep influence on user behavior, and designers should draw inspiration from it and apply it to our daily design work. We have started exploring and will pursue nature as our future direction.
|
||||
The light-speed iteration of the digital world makes products more complex. However, human consciousness and attention resources are limited. Facing this design contradiction, the pursuit of "natural" interaction will be the consistent direction of Ant Design.
|
||||
|
||||
- The visual system plays the most important role in human perception and cognition. By refining the objective laws in nature and applying it to the interface design, a more layered product experience is created. In addition, hearing systems or tactile systems could be added in future to bring more dimensions and more real product experience. See visual language.
|
||||
- In the real product design, a series of methods such as behavior analysis, artificial intelligence and sensors could be applied to assist users to make effective decisions and reduce extra operations of users, so as to save users' mental and physical resources and make human-computer interaction more natural.
|
||||
- **Perception of nature:** according to cognitive psychology, about 80% of external information is obtained through visual channels. The most important visual elements in the interface design, including layout, colors, illustrations, icons, etc., should fully absorb the laws of nature, thereby reducing the user's cognitive cost and bringing authentic and smooth feelings. In some scenarios, opportunely adding other sensory channels such as hearing, touch can create a richer and more natural product experience.
|
||||
- **Act of nature:** In the interaction with the system, the designer should fully understand the relationship between users, system roles, and task objectives, and also contextually organize system functions and services. At the same time, a series of methods such as behavior analysis, artificial intelligence and sensors could be applied to assist users to make effective decisions and reduce extra operations of users, to save users' mental and physical resources and make human-computer interaction more natural.
|
||||
|
||||
## Certainty
|
||||
> To get to know the past and present of natural values, [please move to the column](https://zhuanlan.zhihu.com/p/44809866).
|
||||
|
||||
## Certain
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/ZxgRAMzXNrxHTcvMLchq.png" alt="Certainty" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*OCU3RKZrw8QAAAAAAAAAAABkARQnAQ" alt="Certain" />
|
||||
</div>
|
||||
|
||||
The designers needs to make better design decisions and create a high-definition and low-entropy atmosphere for developer team. Meanwhile, different designers could produce the same design output which fit business needs based on the same understanding of business requirements and design system.
|
||||
Interfaces are the medium of interaction between users and the system. They are the means rather than the purpose. Based on the pursuit of "natural" interaction, the product interface created by Ant Design should be high certainty and low cooperative entropy.
|
||||
|
||||
- **Keep restraint:** Don't make decision until we have to. Designers should focus on the valuable product features using minimal design elements to express. As Antoine de St.Exupery said: [“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”](https://www.goodreads.com/quotes/19905-perfection-is-achieved-not-when-there-is-nothing-more-to)
|
||||
- **Object-oriented:** Explore design rules and abstract them as "objects" to enhance the flexibility and maintainability of user interface design while reducing designer's subjective judgement and uncertainty of real world system. For example: color value conversion, spacing typesetting.
|
||||
- **Modular:** Encapsulate the complex or reusable parts could provide limited interfaces to interact with other modules, ultimately reducing overall system complexity, resulting in better reliability and maintainability. Designers can use existed resources or abstract their own reusable resources, save unnecessary and low additional design to keep their focus on where creativity most needed.
|
||||
- **Designer certainty:** Enterprise-level products are the product of divide and conquer. The more participants, the higher the entropy of cooperation. This is why low-efficiency design and difficult maintenance of the product system exists. By exploring the design rules and modular design ideas, designers are provided with simplified design rules, components and patterns to empower designers and reduce the cooperative entropy.
|
||||
- **Keep restraint:** Don't make a decision until we have to Designers should focus on valuable product features using minimal design elements to express. As Antoine de St. Exupery said: “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”
|
||||
- **Object-oriented:** Explore design rules and abstract them as "objects" to enhance the flexibility and maintainability of user interface design while reducing the designer's subjective judgment and uncertainty of the real-world system. For example color value conversion, spacing typesetting.
|
||||
- **Modular design:** Encapsulate the complex or reusable parts could provide limited interfaces to interact with other modules, ultimately reducing overall system complexity, thereby improving reliability and maintainability. Designers can use existed resources or abstract their reusable resources to save the unnecessary and low additional design to keep their focus on where creativity is most needed.
|
||||
- **User certainty:** User's daily work is completed through the collaboration of enterprise-level products. In addition to considering the design consists of a single product, good certainty is required to be maintained across products, terminals, and systems. Consistent appearance and interaction, maintaining a user-oriented familiarity, can reduce the difficulty of learning, cognitive and operating costs, and improve work efficiency.
|
||||
|
||||
## Meaningful
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*xOYlR4e8ihIAAAAAAAAAAABkARQnAQ" alt="Meaningful" />
|
||||
</div>
|
||||
|
||||
A product or function created by the designer is not only the needs of the user but carries a mission from the user. Product design should be based on the perspective of work to promote the achievement of the user's mission. Simultaneously, based on "nature" and "certainty", it regards the user's human needs and creates meaningful human-computer interaction for the work process.
|
||||
|
||||
- **Meaning of result:** **Clear goals, immediate feedback.** Understand the objectives, clearly disassemble the sub-objectives according to the use process, and let each interaction revolve around the achievement of the main objectives. Provide appropriate and immediate feedback for each action, so that users can understand the operation results. Besides, emotional design can be used to pacify users' negative emotions and enhance users' positive emotions.
|
||||
- **Meaning of process:** **Moderate challenge, full devotion.** Adjust the difficulty of work in different scenarios, make the function trigger at the right time to match the user's skill. If not necessary, do not add entities. Do not distract users, let users focus on task achievement, rather than the interface. Let the current work be neither to simple nor too complex. The challenges are moderate, but higher challenges are raised as the user's capabilities grow. It allows users to continue to immerse themselves in the flow of work and gain fulfilling work experience.
|
||||
|
||||
## Growing
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*pKz3TabovrEAAAAAAAAAAABkARQnAQ" alt="Growing" />
|
||||
</div>
|
||||
|
||||
The growth of enterprise-level product capabilities is accompanied by the evolution of user system roles. Designers should be responsible for the products they create and improve the discoverability of functions and values. Designers should design with the vision of development and consider the common growth of both ends of humans and computers.
|
||||
|
||||
- **Meaning of result:** Clear goals, immediate feedback. Understand the objectives, clearly disassemble the sub-objectives according to the use process, and let each interaction revolve around the achievement of the main objectives. Provide appropriate and immediate feedback for each action, so that users can understand the operation results. Besides, emotional design can be used to pacify users' negative emotions and enhance users' positive emotions.
|
||||
- **Meaning of process:** Moderate challenge, full devotion. Adjust the difficulty of work in different scenarios, make the function trigger at the right time to match the user's skill. If not necessary, do not add entities. Do not distract users, let users focus on task achievement, rather than the interface. Let the current work be neither to simple nor too complex. The challenges are moderate, but higher challenges are raised as the user's capabilities grow. It allows users to continue to immerse themselves in the flow of work and gain fulfilling work experience.
|
||||
|
@ -4,35 +4,59 @@ order: 1
|
||||
title: 设计价值观
|
||||
---
|
||||
|
||||
设计价值观为 Ant Design 的设计者以及基于 Ant Design 进行产品设计的设计者,提供评价设计好坏的内在标准,并提供有效的设计实践所遵循的规则。同时,它启示并激发了设计原则和设计模式,为具体的设计问题提供向导和一般解决方案。
|
||||
Ant Design 设计价值观为设计者提供评价设计好坏的内在标准,启示并激发了 Ant Design 设计原则和设计模式,进而为具体设计问题提供向导和一般解决方案。
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/bIJZFjriQqeMPYyUkSev.png" alt="总概" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*8mRLT7esgZYAAAAAAAAAAABkARQnAQ" alt="总概" />
|
||||
</div>
|
||||
|
||||
在『设计价值观』的坚持上,Ant Design 有两点与众不同:
|
||||
在『设计价值观』的坚持上,Ant Design 有四点与众不同:
|
||||
|
||||
## 自然
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/cdaxgaTMQCGTqjdlwwgt.png" alt="自然" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ" alt="自然" />
|
||||
</div>
|
||||
|
||||
作为一份子,自然界的方方面面都会对用户行为产生深远影响,设计者应该从其中汲取灵感,并运用到当下的设计工作中。我们已做了部分探索,并将追求『自然』作为我们未来持之以恒的方向。
|
||||
数字世界的光速迭代使得产品日益复杂,而人类意识和注意力资源有限。面对这种设计矛盾,追求「自然」交互将是 Ant Design 持之以恒的方向。
|
||||
|
||||
- 在行为的执行中,利用[行为分析](https://zhuanlan.zhihu.com/p/41952711)、人工智能、[传感器](https://zhuanlan.zhihu.com/p/52648777)、[元数据](https://zhuanlan.zhihu.com/p/43613398)等一系列方式,辅助用户有效决策、减少用户额外操作,从而节省用户脑力和体力,让人机交互行为更自然。
|
||||
- 在感知和认知中,视觉系统扮演着最重要的角色,通过提炼自然界中的客观规律并运用到界面设计中,从而创建更有层次产品体验;同时,适时加入听觉系统、触觉系统等,创建更多维、更真实的产品体验。详见视觉语言
|
||||
- **感知自然:**认知心理学所述,约 80% 外界信息通过视觉通道获取。界面设计中最重要的视觉要素,包括布局、色彩、插画、图标等,应充分汲取自然界规律,从而降低用户认知成本,带来真实流畅的感受。在一些场景下,适时加入听觉、触觉等其它感知通道,能创造更丰富自然的产品体验。
|
||||
- **行为自然:**在与系统的互动中,设计者应充分理解用户、系统角色、任务目标间的关系,场景化组织系统功能和服务。同时辅以行为分析、人工智能、传感器、元数据等策略,提供主动式服务,帮助用户决策、减少操作,从而节约用户脑力和体力,让人机交互行为更自然。
|
||||
|
||||
> 想了解自然价值观的前世今生,[请移步至专栏](https://zhuanlan.zhihu.com/p/44809866)。
|
||||
|
||||
## 确定
|
||||
## 确定性
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/ZxgRAMzXNrxHTcvMLchq.png" alt="确定" />
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*OCU3RKZrw8QAAAAAAAAAAABkARQnAQ" alt="确定" />
|
||||
</div>
|
||||
|
||||
『设计者』需要做出更好的设计决策,给予研发团队一种高确定性、低熵值的研发状态。同时,不同设计者在充分理解业务述求后,基于 Ant Design 体系都会有相同且符合当前业务特性的设计产出。
|
||||
界面是用户与系统交互的媒介,是手段而非目的。在追求「自然」交互基础上,通过 Ant Design 创造的产品界面应是高确定性、低合作熵的状态。
|
||||
|
||||
- **保持克制:** 能做,但想清楚了不做。设计者应当聚焦在最有价值产品功能打磨,并用尽可能少的设计元素将其表达。正如 Antoine de St.Exupery 所说:完美不在于无以复加,而在于无可删减,万事莫不如此。
|
||||
- **面向对象的方法:** 探索设计规律,并将其抽象成『对象』,增强界面设计的灵活性和可维护性,同时也减少『设计者』的主观干扰,从而降低系统的不确定性。例如:色值换算、间距排版。
|
||||
- **模块化设计:** 将复杂或者重复出现的局部封装成模块,提供有限接口与其他模块互动,最终全面减少系统的复杂度,进而增进可靠性以及可维护性。设计者可运用现有的组件/模板或者自行抽象可复用的组件/模板,节约无谓的设计且保持系统一致性,让『设计者』把创造力专注在最需要的地方。
|
||||
- **设计者确定:**企业级产品都是分工合作的产物,参与者越多合作熵越高,这是一切设计工作低效、产品系统不易维护的来源。通过探索设计规律、模块化设计思路,来为设计者提供足够精简的设计规则、组件、模式等,赋能设计者、降低合作熵。
|
||||
- 保持克制: 能做,但想清楚了不做。设计者应当聚焦在最有价值产品功能打磨,并用尽可能少的设计元素将其表达。正如 Antoine de St.Exupery 所说:完美不在于无以复加,而在于无可删减,万事莫不如此。
|
||||
- 面向对象的方法: 探索设计规律,并将其抽象成『对象』,增强界面设计的灵活性和可维护性,同时也减少『设计者』的主观干扰,从而降低系统的不确定性。例如:色值换算、间距排版。
|
||||
- 模块化设计: 将复杂或者重复出现的局部封装成模块,提供有限接口与其他模块互动,最终全面减少系统的复杂度,进而增进可靠性以及可维护性。设计者可运用现有的组件/模板或者自行抽象可复用的组件/模板,节约无谓的设计且保持系统一致性,让『设计者』把创造力专注在最需要的地方。
|
||||
- **用户确定:**用户日常工作是通过诸多企业级产品的协同来完成的,除了考虑单一产品的设计一致性,更应当在跨产品、跨终端、跨系统间保持良好的确定性。一致的外观和交互,保持面向用户的熟悉感,能提升易学行,降低认知和操作成本,提升工作效率。
|
||||
|
||||
## 意义感
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*xOYlR4e8ihIAAAAAAAAAAABkARQnAQ" alt="意义感" />
|
||||
</div>
|
||||
|
||||
一个产品或功能被设计者创造出来不只是用户的需要,而更多是承载用户的某个工作使命。产品设计应充分站在工作视角,促成用户使命的达成;同时,在「自然」、「确定」之上,兼顾用户的人性需求,为工作过程创造富有意义感的人机交互。
|
||||
|
||||
- **结果的意义:\*\***明确目标,即时反馈。\*\*洞悉工作目标,根据使用流程拆解明确的子目标,让每个交互行为都围绕着主目标的达成;为每个行为,辅以恰当、即时的反馈,让用户对操作结果了然于胸。此外,可通过情感化设计,适度安抚用户负面情感,强化用户正面情感。
|
||||
- **过程的意义:\*\***挑战适中,全情投入。\*\*调整不同场景下的工作难度,让功能适时适地触发,以匹配用户能力;如无必要,勿增实体,不分散用户注意力,让用户专注于任务达成,而非界面。让当下的工作既不过于简单,亦不过于复杂,挑战适中,并随着用户能力的成长提出更高的挑战,能让用户持续沉浸在工作的心流中,获得富有成就感的工作体验。
|
||||
|
||||
## 生长性
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*pKz3TabovrEAAAAAAAAAAABkARQnAQ" alt="Growth" />
|
||||
</div>
|
||||
|
||||
企业级产品功能的增长与用户系统角色的演变相生相伴。设计者应为自己创造的产品负责,提升功能、价值的可发现性。用发展的眼光做设计,充分考虑人、机两端的共同生长。
|
||||
|
||||
- **价值连接:**产品的增长依赖于用户的群体扩大和深度使用,而用户的成长又依赖于产品功能的壮大。设计者应建立系统设计思维,洞悉产品功能的价值,探索用户在不同场景下的需求,在价值和需求间建立连接。让产品价值被发现,帮助用户建立更有效、更高效的工作方式。
|
||||
- **人机共生:**产品功能和用户需求的更多连接,让人机互动更加紧密,用户和系统共生。产品设计时,不应将用户和系统独立开来,应作为一个动态发展的共同体来思考,确保其足够的灵活、包容,充满生命力。
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 4
|
||||
order: 3
|
||||
title: Visualization
|
||||
---
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 4
|
||||
order: 3
|
||||
title: 可视化
|
||||
---
|
||||
|
||||
@ -9,7 +9,7 @@ title: 可视化
|
||||
|
||||
## 设计资源
|
||||
|
||||
我们提供完善的设计原则 & 指引和设计资源文件(Sketch),此外还提供了一份完整的图表用法说明,来帮助用户快速理解图表并设计出高质量的可视化图表。
|
||||
AntV 提供完善的设计原则 & 指引和设计资源文件(Sketch),此外还提供了一份完整的图表用法说明,来帮助用户快速理解图表并设计出高质量的可视化图表。
|
||||
|
||||
- [设计原则](https://antv.vision/zh/docs/specification/principles/basic)
|
||||
- [设计资源](https://antv.vision/zh/docs/specification/resources)
|
||||
@ -17,7 +17,7 @@ title: 可视化
|
||||
|
||||
## 前端实现
|
||||
|
||||
我们基于原生 JavaScipt 封装了一套 AntV 的组件库,其包含高交互基础图表库 G2Plot,专注解决流程与关系分析的图表库 G6,适于移动端应用的图表库 F2 等,也欢迎社区其他框架的实现版本。
|
||||
AntV 基于原生 JavaScipt 封装了一套 AntV 的组件库,其包含高交互基础图表库 G2Plot,专注解决流程与关系分析的图表库 G6,适于移动端应用的图表库 F2 等,也欢迎社区其他框架的实现版本。
|
||||
|
||||
- [G2 可视化引擎](https://g2.antv.vision/zh)
|
||||
- [G2Plot 开箱即用的图表库](https://g2plot.antv.vision/zh) 🔥
|
||||
|
@ -139,6 +139,7 @@
|
||||
"devDependencies": {
|
||||
"@ant-design/bisheng-plugin": "^2.0.1",
|
||||
"@ant-design/colors": "^3.2.2",
|
||||
"@ant-design/hitu": "^0.0.0-alpha.13",
|
||||
"@ant-design/tools": "^8.0.4",
|
||||
"@packtracker/webpack-plugin": "^2.0.1",
|
||||
"@qixian.cs/github-contributors-list": "^1.0.3",
|
||||
|
@ -42,18 +42,17 @@ module.exports = {
|
||||
themeConfig: {
|
||||
categoryOrder: {
|
||||
'Ant Design': 0,
|
||||
原则: 1,
|
||||
Principles: 1,
|
||||
视觉: 2,
|
||||
Visual: 2,
|
||||
模式: 3,
|
||||
Patterns: 3,
|
||||
全局样式: 1,
|
||||
'Global Style': 1,
|
||||
设计模式: 2,
|
||||
'Design Patterns': 2,
|
||||
其他: 6,
|
||||
Other: 6,
|
||||
Components: 100,
|
||||
组件: 100,
|
||||
},
|
||||
typeOrder: {
|
||||
// Component
|
||||
General: 0,
|
||||
Layout: 1,
|
||||
Navigation: 2,
|
||||
@ -70,6 +69,12 @@ module.exports = {
|
||||
反馈: 5,
|
||||
其他: 6,
|
||||
废弃: 7,
|
||||
|
||||
// Design
|
||||
原则: 1,
|
||||
Principles: 1,
|
||||
全局规则: 2,
|
||||
'Global Rules': 2,
|
||||
},
|
||||
docVersions: {
|
||||
'0.9.x': 'http://09x.ant.design',
|
||||
|
@ -30,32 +30,34 @@ module.exports = {
|
||||
'app.demo.riddle': 'Open in Riddle',
|
||||
'app.home.slogan': "The world's second most popular React UI framework",
|
||||
'app.home.introduce':
|
||||
'A design system with values of Nature and Determinacy for better user experience of enterprise applications',
|
||||
'app.home.design-language': 'Design Language',
|
||||
'app.home.solution': 'Solution',
|
||||
'app.home.components-explain':
|
||||
'Based on the Ant Design language, we have provided a suite of out-of-the-box with high quality for developing and serving enterprise background applications, including the official React UI library and Angular, Vue implementations',
|
||||
'app.home.product-pro-slogan': 'Out-of-the-box front-end / Design solution',
|
||||
'app.home.product-mobile-slogan':
|
||||
"antd-mobile is the implementation of Ant Design's mobile specification",
|
||||
'app.home.product-landing-slogan':
|
||||
'Landing Pages templates and specifications based of Ant Design language',
|
||||
'app.home.product-antv-slogan':
|
||||
'Simple, professional, with unlimited possibilities for data visualization solutions',
|
||||
'app.home.tool-title': 'Tools & Resources',
|
||||
'app.home.tool-package-title': 'Ant Design Resources',
|
||||
'app.home.tool-package-content': 'Ant Design Resources Download',
|
||||
'app.home.tool-library-title': 'Axure Library',
|
||||
'app.home.tool-library-content': 'Beautifully visual Axure library',
|
||||
'app.home.tool-kitchen-title': 'Kitchen',
|
||||
'app.home.tool-kitchen-content': 'A Sketch tools for designers',
|
||||
'app.home.getting-started': 'Getting Started',
|
||||
'Enterprise-level product design system to create an efficient and enjoyable work experience.',
|
||||
'app.home.recommend': 'Recommend',
|
||||
'app.home.recommend.yuque': 'Yuque, our favorite documentation tool',
|
||||
'app.home.recommend.antv.g2plot': 'G2Plot, the new charting library',
|
||||
'app.home.more': 'Learn more',
|
||||
'app.home.more-mobile-react': 'Ant Design Mobile of React',
|
||||
'app.home.more-mobile-angular': 'Ant Design Mobile of Angular',
|
||||
'app.home.popularize': 'Popularize',
|
||||
'app.home.design-and-framework': 'Design language and framework',
|
||||
'app.home.design-values': 'Design values',
|
||||
'app.home.design-values-description':
|
||||
'This is an internal criterion for Ant Design to evaluate good design. Based on the assumption that "everyone pursues pleasure at work", we have added the two values of "Sense of Meaning" and "Growth" on the basis of "Determinism" and "Nature" to guide each designer to do better Judgment and decision making.',
|
||||
'app.home.certainty': 'Certain',
|
||||
'app.home.meaningful': 'Meaningful',
|
||||
'app.home.growth': 'Growing',
|
||||
'app.home.natural': 'Natural',
|
||||
'app.home.design-guide': 'Design guide',
|
||||
'app.home.components': 'components',
|
||||
'app.home.detail': 'Detail',
|
||||
'app.home.global-style': 'Global style',
|
||||
'app.home.design-patterns': 'Design patterns',
|
||||
'app.home.more': 'Learn More',
|
||||
'app.home.play-video': 'Play video',
|
||||
'app.home.getting-started': 'Getting Started',
|
||||
'app.home.design-language': 'Design Language',
|
||||
'app.home.product-antv-slogan': 'A new generation of data visualization solution',
|
||||
'app.home.product-pro-slogan': 'Out-of-box UI solution for enterprise applications',
|
||||
'app.home.product-mobile-slogan': 'Mobile UI components with Ant Design',
|
||||
'app.home.product-hitu': 'Hitu',
|
||||
'app.home.product-hitu-slogan': 'A new generation of graphical solutions',
|
||||
'app.home.product-kitchen-slogan': 'A Sketch toolset to enhance designers',
|
||||
'app.home.product-icons-slogan': 'A set of premium icons',
|
||||
'app.home.view-more': 'More articles',
|
||||
'app.footer.repo': 'GitHub Repository',
|
||||
'app.footer.awesome': 'Awesome Ant Design',
|
||||
'app.footer.course': 'Ant Design Practical Tutorial',
|
||||
|
@ -58,7 +58,7 @@ a {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ant-menu-item-group-title {
|
||||
> .ant-menu-item-group > .ant-menu-item-group-title {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 13px;
|
||||
@ -77,10 +77,22 @@ a {
|
||||
> .ant-menu-item,
|
||||
> .ant-menu-submenu > .ant-menu-submenu-title,
|
||||
> .ant-menu-item-group > .ant-menu-item-group-title,
|
||||
> .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item {
|
||||
> .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item,
|
||||
&.ant-menu-inline > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item {
|
||||
padding-left: 40px !important;
|
||||
}
|
||||
|
||||
// Nest Category > Type > Article
|
||||
&.ant-menu-inline {
|
||||
.ant-menu-item-group-title {
|
||||
padding-left: 56px;
|
||||
}
|
||||
|
||||
.ant-menu-item-group-list > .ant-menu-item {
|
||||
padding-left: 80px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu-item-group:first-child {
|
||||
.ant-menu-item-group-title {
|
||||
margin-top: 0;
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import '../../../components/style/themes/default.less';
|
||||
|
||||
@header-height: 64px;
|
||||
@menu-item-border: 2px;
|
||||
|
||||
@ -25,6 +27,66 @@
|
||||
.ant-menu-item-active .header-link {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
// ===================== Home Page =====================
|
||||
&.home-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
max-width: 1200px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
|
||||
#logo {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.header-lang-button {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
// Adjust github button style
|
||||
.github-btn {
|
||||
float: right;
|
||||
height: auto;
|
||||
margin: 20px 0 0 16px;
|
||||
|
||||
.gh-btn {
|
||||
height: auto;
|
||||
padding: 1px 4px;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
|
||||
.gh-ico {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gh-text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.gh-count {
|
||||
height: auto;
|
||||
padding: 4px 8px;
|
||||
font-weight: normal;
|
||||
background: #fff;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#logo {
|
||||
@ -149,3 +211,9 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.github-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -1,472 +1,2 @@
|
||||
@home-bg-color: #2f54eb;
|
||||
@home-text-color: #314659;
|
||||
|
||||
.home-page-wrapper {
|
||||
position: relative; // will-change: transform;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
color: @home-text-color;
|
||||
font-family: Avenir, @font-family, sans-serif;
|
||||
|
||||
.page {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
padding: 0 24px;
|
||||
h2 {
|
||||
margin: 140px auto 100px;
|
||||
color: @home-text-color;
|
||||
font-weight: 400;
|
||||
font-size: 38px;
|
||||
line-height: 46px;
|
||||
text-align: center;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
p {
|
||||
will-change: transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.banner-bg {
|
||||
&-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
bottom: -200px;
|
||||
left: 0%;
|
||||
width: 120%;
|
||||
height: 200px;
|
||||
background: @home-bg-color;
|
||||
transform: rotate(-4deg);
|
||||
transform-origin: 0;
|
||||
}
|
||||
|
||||
.banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 576px;
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: initial;
|
||||
}
|
||||
.text-wrapper {
|
||||
width: 54%;
|
||||
min-width: 420px;
|
||||
max-width: 560px;
|
||||
min-height: 400px;
|
||||
color: @home-text-color;
|
||||
> * {
|
||||
will-change: transform;
|
||||
}
|
||||
h1 {
|
||||
margin: 8px 0 28px;
|
||||
font-weight: 600;
|
||||
font-size: 68px;
|
||||
font-family: Avenir, @font-family, sans-serif;
|
||||
line-height: 76px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
p {
|
||||
color: @home-text-color;
|
||||
font-size: 20px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 26px;
|
||||
width: 46%;
|
||||
max-width: 482px;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-btns {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 520px;
|
||||
margin-top: 24px;
|
||||
|
||||
.banner-btn {
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
padding: 0 24px;
|
||||
font-size: 16px;
|
||||
font-family: Avenir, @font-family, sans-serif;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border: 1px solid @home-bg-color;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.banner-btn.components {
|
||||
color: #fff;
|
||||
background: @home-bg-color;
|
||||
}
|
||||
|
||||
.banner-btn.language {
|
||||
color: @home-bg-color;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-promote {
|
||||
max-width: 100%;
|
||||
margin: 48px 0 24px 0;
|
||||
|
||||
.ant-divider-inner-text {
|
||||
padding: 0 12px;
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @home-text-color;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s;
|
||||
|
||||
.anticon {
|
||||
position: relative;
|
||||
left: 0;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: @home-bg-color;
|
||||
|
||||
.anticon {
|
||||
left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
g {
|
||||
transform-origin: 50%;
|
||||
transform-box: fill-box;
|
||||
}
|
||||
}
|
||||
|
||||
/** page1 **/
|
||||
|
||||
.page1 {
|
||||
min-height: 784px;
|
||||
background: @home-bg-color;
|
||||
background: linear-gradient(to bottom, rgba(47, 84, 235, 1) 0%, rgba(58, 64, 212, 1) 100%);
|
||||
h2 {
|
||||
color: #fff !important;
|
||||
}
|
||||
&-block {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
max-width: 160px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
h3 {
|
||||
color: #fff;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
}
|
||||
p {
|
||||
color: #fff;
|
||||
}
|
||||
&:hover .page1-image {
|
||||
box-shadow: 0 6px 10px rgba(5, 26, 180, 0.35);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
&-image {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 46px auto 40px;
|
||||
background: #fff;
|
||||
border-radius: 100%;
|
||||
transition: transform 0.45s @ease-out, box-shadow 0.45s @ease-out;
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&-point-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
overflow: inherit !important;
|
||||
}
|
||||
}
|
||||
|
||||
/** page2 **/
|
||||
|
||||
.page2 {
|
||||
min-height: 1110px;
|
||||
padding-top: 1px;
|
||||
overflow: initial;
|
||||
background: #eff3f6;
|
||||
.page {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
h2 {
|
||||
margin-bottom: 112px;
|
||||
}
|
||||
}
|
||||
&-content {
|
||||
background: @home-bg-color;
|
||||
box-shadow: 0 12px 20px #d8e0e6;
|
||||
}
|
||||
&-components,
|
||||
&-product {
|
||||
min-height: 670px;
|
||||
}
|
||||
&-components {
|
||||
position: initial;
|
||||
padding: 56px;
|
||||
color: #fff;
|
||||
line-height: 32px;
|
||||
background: @home-bg-color;
|
||||
h3 {
|
||||
margin: 0 auto 32px;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
}
|
||||
.components-button-wrapper {
|
||||
position: absolute;
|
||||
bottom: 48px;
|
||||
left: 56px;
|
||||
a {
|
||||
display: block;
|
||||
margin-top: 16px;
|
||||
color: #fff;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-product {
|
||||
padding: 48px 56px;
|
||||
background: #fff;
|
||||
.product-block {
|
||||
margin-bottom: 24px;
|
||||
color: @home-text-color;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
.block-text-wrapper {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
.block-text-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid @site-border-color-split;
|
||||
h4 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
white-space: nowrap;
|
||||
.new {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
display: inline-block;
|
||||
padding: 0 2px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
background: #f5222d;
|
||||
border-radius: 4px;
|
||||
transform: translate(~'calc(100% + 4px)', -50%); // 手机回行处理
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin-bottom: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.more {
|
||||
display: inline-block;
|
||||
color: @home-bg-color;
|
||||
line-height: 22px;
|
||||
vertical-align: top;
|
||||
i {
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.more-mobile-react,
|
||||
.more-mobile-angular {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: @home-bg-color;
|
||||
}
|
||||
}
|
||||
.block-image-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 104px;
|
||||
img {
|
||||
display: block;
|
||||
max-width: 80%;
|
||||
}
|
||||
&.right {
|
||||
justify-content: flex-end;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.product-block:hover {
|
||||
h4 {
|
||||
color: @home-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parallax-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
&.bottom {
|
||||
z-index: 0;
|
||||
}
|
||||
&.top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 220px;
|
||||
svg {
|
||||
overflow: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** page3 **/
|
||||
|
||||
.page3 {
|
||||
min-height: 556px;
|
||||
&-block {
|
||||
padding: 24px 12px;
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: @home-text-color;
|
||||
}
|
||||
&:hover {
|
||||
h3 {
|
||||
color: @home-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-img-wrapper,
|
||||
&-text-wrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
&-text-wrapper {
|
||||
margin-top: 2px;
|
||||
// max-width: 182px;
|
||||
margin-left: 32px;
|
||||
line-height: 24px;
|
||||
h3 {
|
||||
margin-bottom: 4px;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
.parallax-bg.top {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** video **/
|
||||
|
||||
.new-version-video {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: #fbfbfb;
|
||||
.vidoe-wrap {
|
||||
width: 100%;
|
||||
background: url('https://gw.alipayobjects.com/zos/rmsportal/gEeRuETmbpAYRaeilexm.jpg') repeat-x;
|
||||
background-size: cover;
|
||||
video {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.banner-1024 {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
transition: all 0.4s;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-16px) scale(1.01);
|
||||
}
|
||||
}
|
||||
|
||||
.github-btn-large {
|
||||
height: 40px;
|
||||
font-family: Avenir, @font-family, sans-serif;
|
||||
line-height: 40px;
|
||||
|
||||
.gh-btn,
|
||||
.gh-count {
|
||||
height: 40px;
|
||||
padding: 9px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.gh-count {
|
||||
margin-left: 10px;
|
||||
|
||||
&::after {
|
||||
border-width: 7px 6px 7px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@supports (-moz-appearance: meterbar) {
|
||||
.en-us .banner-btn {
|
||||
line-height: 38px !important;
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@
|
||||
padding-bottom: 24px;
|
||||
img {
|
||||
display: inline;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
.slick-dots {
|
||||
|
@ -126,7 +126,18 @@ class MainContent extends Component {
|
||||
if (menuItem.children) {
|
||||
return (
|
||||
<SubMenu title={menuItem.title} key={menuItem.title}>
|
||||
{menuItem.children.map(child => this.generateMenuItem(false, child, footerNavIcons))}
|
||||
{menuItem.children.map(child => {
|
||||
if (child.type === 'type') {
|
||||
return (
|
||||
<Menu.ItemGroup title={child.title} key={child.title}>
|
||||
{child.children
|
||||
.sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0))
|
||||
.map(leaf => this.generateMenuItem(false, leaf, footerNavIcons))}
|
||||
</Menu.ItemGroup>
|
||||
);
|
||||
}
|
||||
return this.generateMenuItem(false, child, footerNavIcons);
|
||||
})}
|
||||
</SubMenu>
|
||||
);
|
||||
}
|
||||
|
@ -1,133 +0,0 @@
|
||||
import React from 'react';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import ScrollParallax from 'rc-scroll-anim/lib/ScrollParallax';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import GitHubButton from 'react-github-button';
|
||||
import { Button, Divider } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import BannerImage from './BannerImage';
|
||||
import * as utils from '../utils';
|
||||
|
||||
const loop = {
|
||||
duration: 3000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
};
|
||||
|
||||
const Banner = ({ isMobile }) => {
|
||||
const { locale } = useIntl();
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
return (
|
||||
<div className="home-page-wrapper banner-wrapper" id="banner">
|
||||
<div className="banner-bg-wrapper">
|
||||
<svg width="400px" height="576px" viewBox="0 0 400 576" fill="none">
|
||||
<TweenOne
|
||||
component="g"
|
||||
animation={[
|
||||
{ opacity: 0, type: 'from' },
|
||||
{ ...loop, y: 15 },
|
||||
]}
|
||||
>
|
||||
<ellipse cx="100" cy="100" rx="6" ry="6" stroke="#2F54EB" strokeWidth="1.6" />
|
||||
</TweenOne>
|
||||
<TweenOne
|
||||
component="g"
|
||||
animation={[
|
||||
{ opacity: 0, type: 'from' },
|
||||
{ ...loop, y: -15 },
|
||||
]}
|
||||
>
|
||||
<g transform="translate(200 450)">
|
||||
<g style={{ transformOrigin: '50% 50%', transform: 'rotate(-340deg)' }}>
|
||||
<rect stroke="#FADB14" strokeWidth="1.6" width="9" height="9" />
|
||||
</g>
|
||||
</g>
|
||||
</TweenOne>
|
||||
</svg>
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
className="banner-bg"
|
||||
animation={{ playScale: [1, 1.5], rotate: 0 }}
|
||||
/>
|
||||
</div>
|
||||
<QueueAnim className="banner page" type="alpha" delay={150}>
|
||||
{isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<BannerImage />
|
||||
</div>
|
||||
)}
|
||||
<QueueAnim className="text-wrapper" key="text" type="bottom">
|
||||
<h1 key="h1">Ant Design</h1>
|
||||
<p key="p">
|
||||
<FormattedMessage id="app.home.introduce" />
|
||||
</p>
|
||||
<div className="banner-btns" key="buttons">
|
||||
<Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN)}>
|
||||
<Button type="primary" className="banner-btn components">
|
||||
<FormattedMessage id="app.home.getting-started" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
to={utils.getLocalizedPathname('/docs/spec/introduce', isZhCN)}
|
||||
style={{ marginLeft: 16 }}
|
||||
>
|
||||
<Button className="banner-btn language">
|
||||
<FormattedMessage id="app.home.design-language" />
|
||||
</Button>
|
||||
</Link>
|
||||
{!isMobile && (
|
||||
<GitHubButton
|
||||
style={{ marginLeft: 16 }}
|
||||
size="large"
|
||||
type="stargazers"
|
||||
namespace="ant-design"
|
||||
repo="ant-design"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
key="promote"
|
||||
className="banner-promote"
|
||||
style={{
|
||||
width: isZhCN ? 412 : 522,
|
||||
}}
|
||||
>
|
||||
<Divider>
|
||||
<FormattedMessage id="app.home.recommend" />
|
||||
</Divider>
|
||||
<a
|
||||
href="https://github.com/antvis/G2Plot?from=antd"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={() => {
|
||||
if (window.gtag) {
|
||||
window.gtag('event', '点击', {
|
||||
event_category: '首页推广',
|
||||
event_label: `https://github.com/antvis/G2Plot?from=antd`,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<img src="https://antv.vision/icons/icon-512x512.png" alt="AntV logo" />
|
||||
<FormattedMessage id="app.home.recommend.antv.g2plot" />
|
||||
<RightOutlined style={{ marginLeft: 6, fontSize: 12, opacity: 0.6 }} />
|
||||
</a>
|
||||
</div>
|
||||
</QueueAnim>
|
||||
{!isMobile && (
|
||||
<div className="img-wrapper" key="image">
|
||||
<ScrollParallax
|
||||
location="banner"
|
||||
component={BannerImage}
|
||||
animation={{ playScale: [1, 1.5], y: 80 }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</QueueAnim>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Banner;
|
35
site/theme/template/Home/Banner/Background.less
Normal file
35
site/theme/template/Home/Banner/Background.less
Normal file
@ -0,0 +1,35 @@
|
||||
@import '../../../../../components/style/themes/default.less';
|
||||
|
||||
.home-banner-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
> * {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
> svg {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.home-banner-background {
|
||||
> img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
186
site/theme/template/Home/Banner/Background.tsx
Normal file
186
site/theme/template/Home/Banner/Background.tsx
Normal file
@ -0,0 +1,186 @@
|
||||
import * as React from 'react';
|
||||
import Hitu from '@ant-design/hitu';
|
||||
import './Background.less';
|
||||
|
||||
const RANDOM_OFFSET = 20;
|
||||
const TOTAL_FRAMES = 500;
|
||||
|
||||
function randomFrames(x: number, y: number): any[] {
|
||||
const common = { x, y, cubic: Hitu.CUBIC_EASE_IN_OUT };
|
||||
|
||||
return [
|
||||
{
|
||||
frame: 0,
|
||||
...common,
|
||||
},
|
||||
{
|
||||
frame: TOTAL_FRAMES / 2,
|
||||
...common,
|
||||
x: x - Math.random() * RANDOM_OFFSET * 2 + RANDOM_OFFSET,
|
||||
y: y - Math.random() * RANDOM_OFFSET * 2 + RANDOM_OFFSET,
|
||||
},
|
||||
{
|
||||
frame: TOTAL_FRAMES,
|
||||
...common,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const ShadowSize = 30;
|
||||
|
||||
// =================================== Circle 1 ===================================
|
||||
const CircleSize1 = 140;
|
||||
const Circle1 = () => (
|
||||
<svg>
|
||||
<defs>
|
||||
<filter id="banner-circle-shadow-1">
|
||||
<feDropShadow dx="10" dy="10" stdDeviation="10" floodColor="rgba(0,0,0,0.05)" />
|
||||
</filter>
|
||||
<linearGradient id="banner-circle-fill-1" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style={{ stopColor: '#FAFCFE' }} />
|
||||
<stop offset="100%" style={{ stopColor: '#F9FCFE' }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle
|
||||
cx={CircleSize1 + ShadowSize}
|
||||
cy={CircleSize1 + ShadowSize}
|
||||
r={CircleSize1}
|
||||
fill="url(#banner-circle-fill-1)"
|
||||
filter="url(#banner-circle-shadow-1)"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
Circle1.width = (CircleSize1 + ShadowSize) * 2;
|
||||
Circle1.height = (CircleSize1 + ShadowSize) * 2;
|
||||
|
||||
// =================================== Circle 2 ===================================
|
||||
const CircleSize2 = 200;
|
||||
const Circle2 = () => (
|
||||
<svg>
|
||||
<defs>
|
||||
<filter id="banner-circle-shadow-2">
|
||||
<feDropShadow dx="10" dy="10" stdDeviation="10" floodColor="rgba(0,0,0,0.05)" />
|
||||
</filter>
|
||||
<linearGradient id="banner-circle-fill-2" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style={{ stopColor: '#FAFCFE' }} />
|
||||
<stop offset="100%" style={{ stopColor: '#F9FCFE' }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle
|
||||
cx={CircleSize2 + ShadowSize}
|
||||
cy={CircleSize2 + ShadowSize}
|
||||
r={CircleSize2}
|
||||
fill="url(#banner-circle-fill-2)"
|
||||
filter="url(#banner-circle-shadow-2)"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
Circle2.width = (CircleSize2 + ShadowSize) * 2;
|
||||
Circle2.height = (CircleSize2 + ShadowSize) * 2;
|
||||
|
||||
// ==================================== Rect 1 ====================================
|
||||
const ReactSize1 = 90;
|
||||
const React1 = () => (
|
||||
<svg>
|
||||
<defs>
|
||||
<filter id="banner-rect-shadow-1">
|
||||
<feDropShadow dx="10" dy="10" stdDeviation="10" floodColor="rgba(0,0,0,0.05)" />
|
||||
</filter>
|
||||
<linearGradient id="banner-rect-fill-1" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style={{ stopColor: '#F8FBFF' }} />
|
||||
<stop offset="100%" style={{ stopColor: '#F9FCFF' }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect
|
||||
x={ShadowSize}
|
||||
y={ShadowSize}
|
||||
width={ReactSize1 * 2}
|
||||
height={ReactSize1 * 2}
|
||||
fill="url(#banner-rect-fill-1)"
|
||||
filter="url(#banner-rect-shadow-1)"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
React1.width = (ReactSize1 + ShadowSize) * 2;
|
||||
React1.height = (ReactSize1 + ShadowSize) * 2;
|
||||
|
||||
// ================================== Diamond 1 ===================================
|
||||
const DiamondSize1 = 180;
|
||||
const Diamond1 = () => {
|
||||
const start = ShadowSize;
|
||||
const center = ShadowSize + DiamondSize1;
|
||||
const end = ShadowSize + DiamondSize1 * 2;
|
||||
|
||||
return (
|
||||
<svg>
|
||||
<defs>
|
||||
<filter id="banner-diamond-shadow-1">
|
||||
<feDropShadow dx="10" dy="10" stdDeviation="10" floodColor="rgba(0,0,0,0.05)" />
|
||||
</filter>
|
||||
<linearGradient id="banner-diamond-fill-1" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style={{ stopColor: '#F8FBFF' }} />
|
||||
<stop offset="100%" style={{ stopColor: '#F9FCFF' }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<path
|
||||
d={`M ${start} ${center} ${center} ${start} ${end} ${center} ${center} ${end} Z`}
|
||||
fill="url(#banner-diamond-fill-1)"
|
||||
filter="url(#banner-diamond-shadow-1)"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
Diamond1.width = (DiamondSize1 + ShadowSize) * 2;
|
||||
Diamond1.height = (DiamondSize1 + ShadowSize) * 2;
|
||||
|
||||
export default function Background() {
|
||||
const [circleFrames, setCircleFrames] = React.useState<any[]>(randomFrames(550, 200));
|
||||
const [circle2Frames, setCircle2Frames] = React.useState<any[]>(randomFrames(0, 448));
|
||||
const [reactFrames, setReactFrames] = React.useState<any[]>(randomFrames(1400, 300));
|
||||
const [diamondFrames, setDiamondFrames] = React.useState<any[]>(randomFrames(1100, 0));
|
||||
|
||||
return (
|
||||
<div className="home-banner-background">
|
||||
<img
|
||||
alt="background"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*_fCZRqKuJBgAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
<Hitu
|
||||
width={1440}
|
||||
height={448}
|
||||
frames={TOTAL_FRAMES}
|
||||
onFrame={frame => {
|
||||
if (frame === 0) {
|
||||
setCircleFrames(randomFrames(550, 200));
|
||||
setCircle2Frames(randomFrames(0, 448));
|
||||
setReactFrames(randomFrames(1400, 300));
|
||||
setDiamondFrames(randomFrames(1100, 0));
|
||||
}
|
||||
}}
|
||||
shapes={[
|
||||
{
|
||||
type: 'shape',
|
||||
source: Circle1,
|
||||
frames: circleFrames,
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: Circle2,
|
||||
frames: circle2Frames,
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: React1,
|
||||
frames: reactFrames,
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: Diamond1,
|
||||
frames: diamondFrames,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
43
site/theme/template/Home/Banner/Logo.less
Normal file
43
site/theme/template/Home/Banner/Logo.less
Normal file
@ -0,0 +1,43 @@
|
||||
@import '../../../../../components/style/themes/default.less';
|
||||
|
||||
.home-card-logo {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
max-width: 490px;
|
||||
margin: 0 32px;
|
||||
cursor: pointer;
|
||||
|
||||
.home-card-logo-icon {
|
||||
position: absolute;
|
||||
top: -35px;
|
||||
left: 334px;
|
||||
display: none;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.home-banner-mini {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
.home-banner-normal {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.home-card-logo {
|
||||
height: 90px;
|
||||
vertical-align: top;
|
||||
|
||||
.home-banner-mini {
|
||||
display: none;
|
||||
}
|
||||
.home-banner-normal {
|
||||
display: block;
|
||||
}
|
||||
.home-card-logo-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
114
site/theme/template/Home/Banner/Logo.tsx
Normal file
114
site/theme/template/Home/Banner/Logo.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
import * as React from 'react';
|
||||
import Hitu from '@ant-design/hitu';
|
||||
import { HiTuRefObject } from '@ant-design/hitu/lib/HiTu';
|
||||
import './Logo.less';
|
||||
import { preLoad } from '../util';
|
||||
|
||||
const ICON_IMAGES = [
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/fef2f3d5-9326-48e3-a8f3-a99584efd425.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/95736b64-de90-4fcd-bae9-a827091a247d.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/7002f57b-bf16-4640-8373-2c4cfcfa7f8c.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/29aa8cd8-de97-42b8-a370-f901be43e18a.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/d7bc5cdf-07f9-4ddf-8135-78d3cc6ca009.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/8737ccb7-3b5d-40ca-ae36-6a904047caa4.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/1fdf5981-2d9d-4315-bb84-4590d5c5b989.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/b9d17ebc-2af1-4926-ba1b-c1376ddaa479.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/dcb1b8f8-becd-4f90-ba32-574260a7b18d.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/ba0958ce-b194-4910-84de-7e3274742dbb.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/ad510b94-5f85-4b30-b929-2e3a34ad673c.svg',
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/43d010fa-71ac-44e3-8475-bb77d95c331c.svg',
|
||||
];
|
||||
|
||||
preLoad(ICON_IMAGES);
|
||||
|
||||
const AntDesign = () => (
|
||||
<svg>
|
||||
<circle cx="16" cy="16" r="9" fill="#F74455" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
AntDesign.width = 32;
|
||||
AntDesign.height = 32;
|
||||
|
||||
const ICONS = ICON_IMAGES.map(href => {
|
||||
function Icon() {
|
||||
return (
|
||||
<svg viewBox="0 0 32 32">
|
||||
{/* Image size will follow outer svg size, let's cut to half here */}
|
||||
<image href={href} height="16" width="16" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
Icon.width = 32;
|
||||
Icon.height = 32;
|
||||
|
||||
return Icon;
|
||||
});
|
||||
|
||||
export default function Logo() {
|
||||
const hituRef = React.useRef<HiTuRefObject>(null);
|
||||
const [loop, setLoop] = React.useState(false);
|
||||
const [iconIndex, setIconIndex] = React.useState(-1);
|
||||
const Icon = ICONS[iconIndex] || AntDesign;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="home-card-logo"
|
||||
onMouseEnter={() => {
|
||||
setLoop(true);
|
||||
if (hituRef.current) {
|
||||
hituRef.current.triggerMotion(true);
|
||||
}
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setLoop(false);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt="Ant Design"
|
||||
src="https://gw.alipayobjects.com/zos/basement_prod/80e7d303-aa05-4c2d-94e9-2255ab5cea6c.svg"
|
||||
className="home-banner-mini"
|
||||
/>
|
||||
<img
|
||||
width="490"
|
||||
height="87"
|
||||
alt="Ant Design"
|
||||
src="https://gw.alipayobjects.com/zos/basement_prod/5b153736-dfe3-4a73-9454-68607c8103e4.svg"
|
||||
className="home-banner-normal"
|
||||
/>
|
||||
<Hitu
|
||||
ref={hituRef}
|
||||
width={64}
|
||||
height={64}
|
||||
className="home-card-logo-icon"
|
||||
loop={loop}
|
||||
defaultPlay={false}
|
||||
frames={6}
|
||||
onFrame={frame => {
|
||||
if (frame === 5) {
|
||||
const newIndex = (iconIndex + 1) % ICONS.length;
|
||||
setIconIndex(newIndex);
|
||||
}
|
||||
}}
|
||||
shapes={[
|
||||
{
|
||||
type: 'shape',
|
||||
source: Icon,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
x: 32,
|
||||
y: 32,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
opacity: 1,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
90
site/theme/template/Home/Banner/index.less
Normal file
90
site/theme/template/Home/Banner/index.less
Normal file
@ -0,0 +1,90 @@
|
||||
@import '../../../../../components/style/themes/default.less';
|
||||
|
||||
@home-color: #0170fe;
|
||||
|
||||
.home-banner {
|
||||
position: relative;
|
||||
height: 512px;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(rgba(255, 255, 255, 0.5), rgba(235, 245, 255, 0.58)),
|
||||
linear-gradient(150deg, #fbfcfd, #f8fcff);
|
||||
|
||||
&-holder {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-top: 160px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
margin: 16px 0 0;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.banner-video {
|
||||
display: none;
|
||||
margin: 20px auto 0;
|
||||
color: @home-color;
|
||||
}
|
||||
|
||||
&-operations {
|
||||
margin-top: 72px;
|
||||
white-space: nowrap;
|
||||
|
||||
button {
|
||||
height: auto;
|
||||
margin: 0 8px;
|
||||
padding: 8px 24px;
|
||||
font-size: 14px;
|
||||
border-color: @home-color;
|
||||
|
||||
&:hover {
|
||||
border-color: @home-color;
|
||||
}
|
||||
|
||||
&.ant-btn-primary {
|
||||
background: @home-color;
|
||||
}
|
||||
|
||||
&:not(.ant-btn-primary) {
|
||||
color: @home-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.home-banner {
|
||||
height: 448px;
|
||||
|
||||
&-holder {
|
||||
margin-top: 130px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
font-size: 16px;
|
||||
|
||||
p {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.video {
|
||||
margin: 8px auto;
|
||||
}
|
||||
|
||||
&-operations {
|
||||
margin-top: 40px;
|
||||
|
||||
button {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
site/theme/template/Home/Banner/index.tsx
Normal file
49
site/theme/template/Home/Banner/index.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import * as React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { PlayCircleFilled } from '@ant-design/icons';
|
||||
import Background from './Background';
|
||||
import { getLocalizedPathname } from '../../utils';
|
||||
import Logo from './Logo';
|
||||
|
||||
import './index.less';
|
||||
|
||||
export default function Banner() {
|
||||
const { locale } = useIntl();
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
|
||||
return (
|
||||
<div className="home-banner">
|
||||
<Background />
|
||||
|
||||
<div className="home-banner-holder">
|
||||
<div className="home-banner-content">
|
||||
<div>
|
||||
<Logo />
|
||||
</div>
|
||||
<p>
|
||||
<FormattedMessage id="app.home.introduce" />
|
||||
</p>
|
||||
|
||||
<a className="banner-video">
|
||||
<PlayCircleFilled /> <FormattedMessage id="app.home.play-video" />
|
||||
</a>
|
||||
|
||||
<div className="home-banner-content-operations">
|
||||
<Link to={getLocalizedPathname('/docs/react/introduce', isZhCN)}>
|
||||
<Button type="primary" shape="round">
|
||||
<FormattedMessage id="app.home.getting-started" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to={getLocalizedPathname('/docs/spec/introduce', isZhCN)}>
|
||||
<Button shape="round" ghost>
|
||||
<FormattedMessage id="app.home.design-language" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
import React from 'react';
|
||||
import TweenOne from 'rc-tween-one';
|
||||
import PathPlugin from 'rc-tween-one/lib/plugin/PathPlugin';
|
||||
import moment from 'moment';
|
||||
|
||||
TweenOne.plugins.push(PathPlugin);
|
||||
const duration = 7000;
|
||||
const ease = 'easeInOutSine';
|
||||
const p =
|
||||
'M123.5,89.5 C148,82.5 239.5,48.5 230,17.5 C220.5,-13.5 127,6 99.5,13.5 C72,21 -9.5,56.5 1.5,84.5 C12.5,112.5 99,96.5 123.5,89.5 Z';
|
||||
const easePath =
|
||||
'M0,100 C7.33333333,89 14.3333333,81.6666667 21,78 C25.3601456,75.6019199 29.8706084,72.9026327 33,70 C37.0478723,66.2454406 39.3980801,62.0758689 42.5,57 C48,46.5 61.5,32.5 70,28 C77.5,23.5 81.5,20 86.5,16 C89.8333333,13.3333333 94.3333333,8 100,0';
|
||||
const loop = {
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
duration,
|
||||
ease,
|
||||
};
|
||||
const animate = {
|
||||
path: {
|
||||
path: { x: p, y: p },
|
||||
duration: 5000,
|
||||
repeat: -1,
|
||||
ease: TweenOne.easing.path(easePath, { lengthPixel: 400 }),
|
||||
},
|
||||
rotate: {
|
||||
...loop,
|
||||
rotate: 15,
|
||||
},
|
||||
rotateR: {
|
||||
...loop,
|
||||
rotate: -15,
|
||||
},
|
||||
yGroup: {
|
||||
...loop,
|
||||
y: 24,
|
||||
},
|
||||
track: {
|
||||
...loop,
|
||||
rotate: 15,
|
||||
},
|
||||
rotateY: {
|
||||
...loop,
|
||||
y: 24,
|
||||
rotate: 15,
|
||||
},
|
||||
y: {
|
||||
...loop,
|
||||
y: 15,
|
||||
duration: 3000,
|
||||
},
|
||||
yR: {
|
||||
...loop,
|
||||
y: -15,
|
||||
duration: 3000,
|
||||
},
|
||||
};
|
||||
|
||||
function TweenOneG(props) {
|
||||
return <TweenOne component="g" {...props} />;
|
||||
}
|
||||
|
||||
export default function BannerImage() {
|
||||
if (moment().format('YYYY-MM-DD') === '2018-10-24') {
|
||||
return (
|
||||
<a
|
||||
href="https://1024.yuque.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="banner-1024"
|
||||
>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/BaqKyDBXRAzoncSoBQGU.svg" alt="1024" />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<svg width="482px" height="500px" viewBox="0 0 482 500">
|
||||
<defs>
|
||||
<path
|
||||
d="M151,55 C129.666667,62.6666667 116,74.3333333 110,90 C104,105.666667 103,118.5 107,128.5 L225.5,96 C219.833333,79 209.666667,67 195,60 C180.333333,53 165.666667,51.3333333 151,55 L137,0 L306.5,6.5 L306.5,156 L227,187.5 L61.5,191 C4.5,175 -12.6666667,147.833333 10,109.5 C32.6666667,71.1666667 75,34.6666667 137,0 L151,55 Z"
|
||||
id="mask"
|
||||
/>
|
||||
</defs>
|
||||
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd" transform="translate(0, 30)">
|
||||
<g id="Group-7" transform="translate(56.000000, 124)">
|
||||
<TweenOneG animation={animate.rotateY}>
|
||||
<image
|
||||
id="cc2"
|
||||
alt="globe"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/DJWUmdpxcQakQHwhPjzf.png"
|
||||
width="124px"
|
||||
height="130px"
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
<g id="Group-8" transform="translate(127.000000, 82)">
|
||||
<TweenOneG animation={animate.rotateR}>
|
||||
<image
|
||||
id="cc1"
|
||||
alt="globe"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/DEaRdiYbAyVNRelJpwXx.png"
|
||||
width="195px"
|
||||
height="163px"
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
<g id="Group-13" transform="translate(0.000000, 41.000000)">
|
||||
<TweenOneG animation={animate.y}>
|
||||
<ellipse
|
||||
fillOpacity="0.4"
|
||||
fill="#2F54EB"
|
||||
opacity="0.3"
|
||||
cx="390"
|
||||
cy="25.9920529"
|
||||
rx="6"
|
||||
ry="5.99205288"
|
||||
/>
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.yR, delay: 100 }}>
|
||||
<circle fillOpacity="0.4" fill="#2F54EB" opacity="0.3" cx="402" cy="3" r="3" />
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.y, delay: 100 }}>
|
||||
<ellipse
|
||||
stroke="#13C2C2"
|
||||
strokeWidth="1.6"
|
||||
cx="419"
|
||||
cy="313.994702"
|
||||
rx="4"
|
||||
ry="3.99470192"
|
||||
/>
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.yR, delay: 150 }}>
|
||||
<rect
|
||||
fill="#FFE600"
|
||||
opacity="0.6"
|
||||
transform="translate(285.224453, 179.218136) rotate(-340.000000) translate(-285.224453, -179.218136) "
|
||||
x="277.244453"
|
||||
y="171.248705"
|
||||
width="15.96"
|
||||
height="15.9388607"
|
||||
rx="3.6"
|
||||
/>
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.y, delay: 200 }}>
|
||||
<rect
|
||||
stroke="#F5222D"
|
||||
strokeWidth="1.6"
|
||||
transform="translate(184.000000, 18.000000) rotate(8.000000) translate(-184.000000, -18.000000) "
|
||||
x="176.8"
|
||||
y="10.8"
|
||||
width="14.4"
|
||||
height="14.4"
|
||||
rx="3.6"
|
||||
/>
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.yR, delay: 200 }}>
|
||||
<path
|
||||
d="M11.6005591,127.582431 L14.1769733,132.010943 C15.1767883,133.729492 14.5941396,135.933161 12.8755911,136.932976 C12.325874,137.25279 11.7012453,137.421269 11.0652659,137.421269 L5.91243747,137.421269 C3.92421237,137.421269 2.31243747,135.809494 2.31243747,133.821269 C2.31243747,133.185289 2.48091636,132.560661 2.80073009,132.010943 L5.37714432,127.582431 C6.37695929,125.863883 8.58062832,125.281234 10.2991769,126.281049 C10.8384011,126.594758 11.2868499,127.043207 11.6005591,127.582431 Z"
|
||||
stroke="#13C2C2"
|
||||
strokeWidth="1.6"
|
||||
transform="translate(8.489147, 131.606717) rotate(18.000000) translate(-8.489147, -131.606717) "
|
||||
/>
|
||||
</TweenOneG>
|
||||
<TweenOneG animation={{ ...animate.y, delay: 300 }}>
|
||||
<path
|
||||
d="M168.708021,336.081114 L171.995111,342.213024 C172.516977,343.186539 172.150843,344.398784 171.177328,344.920649 C170.88673,345.076428 170.562126,345.157945 170.232408,345.157945 L163.658227,345.157945 C162.553657,345.157945 161.658227,344.262514 161.658227,343.157945 C161.658227,342.828226 161.739744,342.503622 161.895523,342.213024 L165.182613,336.081114 C165.704478,335.1076 166.916723,334.741466 167.890238,335.263331 C168.237419,335.449442 168.52191,335.733933 168.708021,336.081114 Z"
|
||||
stroke="#2F54EB"
|
||||
strokeWidth="1.6"
|
||||
transform="translate(166.945513, 340.091794) rotate(18.000000) translate(-166.945513, -340.091794) "
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
<TweenOneG animation={{ ...animate.loop, ...animate.yGroup }}>
|
||||
<g id="Group-15" transform="translate(373.000000, 204.000000)" strokeWidth="1.35">
|
||||
<path
|
||||
d="M19.8372093,0.173184358 L1.82452431,52.3407821"
|
||||
id="Path-2-Copy-5"
|
||||
stroke="#000000"
|
||||
/>
|
||||
<ellipse
|
||||
id="Oval-9-Copy-14"
|
||||
stroke="#0D1A26"
|
||||
fill="#FFFFFF"
|
||||
cx="2.27484144"
|
||||
cy="50.9916201"
|
||||
rx="1.35095137"
|
||||
ry="1.34916201"
|
||||
/>
|
||||
</g>
|
||||
<g id="Group-9" transform="translate(322.000000, 107.000000)">
|
||||
<TweenOneG style={{ transformOrigin: '50px 40px' }} animation={animate.rotateR}>
|
||||
<image
|
||||
id="cc3"
|
||||
alt="globe"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/cCmuVrmQIJYlrhFjiPDZ.png"
|
||||
width="160px"
|
||||
height="66px"
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
<g id="Group-12" transform="translate(271.000000, 2)">
|
||||
<TweenOneG style={{ transformOrigin: '125px 200px' }} animation={animate.rotate}>
|
||||
<image
|
||||
id="cc0"
|
||||
alt="globe"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/TOElddMOrCWlgZvWTJna.png"
|
||||
width="184px"
|
||||
height="293px"
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
</TweenOneG>
|
||||
<g id="Group-14" transform="translate(150.000000, 230.000000)">
|
||||
<g id="Group-22" transform="translate(62.000000, 7.000000)">
|
||||
<image
|
||||
id="cc4"
|
||||
alt="globe"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/FpKOqFadwoFFIZFExjaf.png"
|
||||
width="151px"
|
||||
height="234px"
|
||||
/>
|
||||
</g>
|
||||
<mask id="mask-2">
|
||||
<use xlinkHref="#mask" fill="white" transform="translate(-42, -33)" />
|
||||
</mask>
|
||||
<g mask="url(#mask-2)">
|
||||
<TweenOneG animation={animate.track} style={{ transformOrigin: '122.7px 58px' }}>
|
||||
<g transform="translate(-16, -52)">
|
||||
<g transform="translate(16, 52)">
|
||||
<path
|
||||
d="M83.1700911,35.9320015 C63.5256194,37.9279025 44.419492,43.1766434 25.8517088,51.6782243 C14.3939956,57.7126276 7.77167019,64.8449292 7.77167019,72.4866248 C7.77167019,94.1920145 61.1993389,111.787709 127.105708,111.787709 C193.012078,111.787709 246.439746,94.1920145 246.439746,72.4866248 C246.439746,55.2822262 212.872939,40.6598106 166.13127,35.3351955"
|
||||
id="line-s"
|
||||
stroke="#0D1A26"
|
||||
strokeWidth="1.35"
|
||||
strokeLinecap="round"
|
||||
transform="translate(127.105708, 73.561453) rotate(-16.000000) translate(-127.105708, -73.561453) "
|
||||
/>
|
||||
</g>
|
||||
<TweenOneG animation={animate.path}>
|
||||
<image
|
||||
alt="globe"
|
||||
id="id2"
|
||||
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/IauKICnGjGnotJBEyCRK.png"
|
||||
x="16"
|
||||
y="62"
|
||||
width="26px"
|
||||
height="26px"
|
||||
/>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
</TweenOneG>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
61
site/theme/template/Home/DesignPage/Certainty.tsx
Normal file
61
site/theme/template/Home/DesignPage/Certainty.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import * as React from 'react';
|
||||
import Hitu from '@ant-design/hitu';
|
||||
import { Shape, FrameInfo } from '@ant-design/hitu/lib/interface';
|
||||
import InteractiveIcon from './InteractiveIcon';
|
||||
|
||||
function Rect() {
|
||||
return <rect x="0" y="0" width="14" height="14" fill="#0170FE" />;
|
||||
}
|
||||
|
||||
Rect.width = 14;
|
||||
Rect.height = 14;
|
||||
|
||||
function getFrames(x: number, y: number): FrameInfo[] {
|
||||
const delay = (x + y) * 5 + 1;
|
||||
|
||||
const position = {
|
||||
x: x * (14 + 12) + 21,
|
||||
y: y * (14 + 12) + 21,
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
frame: 0,
|
||||
rotate: 0,
|
||||
...position,
|
||||
},
|
||||
{
|
||||
frame: delay,
|
||||
rotate: 0,
|
||||
...position,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
{
|
||||
frame: 15 + delay,
|
||||
scaleX: 1.3,
|
||||
scaleY: 1.3,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
{
|
||||
frame: 30 + delay,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const shapes: Shape[] = [];
|
||||
|
||||
for (let x = 0; x < 4; x += 1) {
|
||||
for (let y = 0; y < 4; y += 1) {
|
||||
shapes.push({
|
||||
type: 'shape',
|
||||
source: Rect,
|
||||
frames: getFrames(x, y),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default function Certainty() {
|
||||
return <InteractiveIcon shapes={shapes} />;
|
||||
}
|
101
site/theme/template/Home/DesignPage/Growth.tsx
Normal file
101
site/theme/template/Home/DesignPage/Growth.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
import * as React from 'react';
|
||||
import Hitu from '@ant-design/hitu';
|
||||
import { Shape, FrameInfo } from '@ant-design/hitu/lib/interface';
|
||||
import InteractiveIcon from './InteractiveIcon';
|
||||
|
||||
function Arrow() {
|
||||
return (
|
||||
<path
|
||||
fill="#FFB200"
|
||||
d="M81.8274462,0.126276923 L81.8274462,19.3203692 L75.7661538,19.3203692 L75.7666925,9.85015287 C58.6630313,32.8286615 33.5224908,52.4154208 0.389745066,68.6317684 L1.32871492e-12,68.8209231 L0.00109197241,62.0542198 C30.7061773,46.7059243 54.0774442,28.4225755 70.1546362,7.22315635 L70.7125099,6.48245893 L70.931,6.18727692 L62.6333538,6.18756923 L62.6333538,0.126276923 L81.8274462,0.126276923 Z"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Arrow.width = 84;
|
||||
Arrow.height = 70;
|
||||
|
||||
function Rect() {
|
||||
return <rect x="0" y="0" width="10" height="10" fill="#FFD75A" />;
|
||||
}
|
||||
|
||||
Rect.width = 10;
|
||||
Rect.height = 10;
|
||||
|
||||
const rectShared: Partial<FrameInfo> = {
|
||||
originX: 0,
|
||||
originY: 1,
|
||||
y: 98,
|
||||
};
|
||||
|
||||
const rectDistance = Rect.width + 9;
|
||||
function getRectFrames(scaleY: number, index: number): FrameInfo[] {
|
||||
const delay = index * 3;
|
||||
|
||||
return [
|
||||
{
|
||||
frame: 0,
|
||||
scaleY,
|
||||
...rectShared,
|
||||
x: 18 + rectDistance * index,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
{
|
||||
frame: 1 + delay,
|
||||
scaleY: 0,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
{
|
||||
frame: 30 + delay,
|
||||
scaleY: scaleY * 1.05,
|
||||
},
|
||||
{
|
||||
frame: 40 + delay,
|
||||
scaleY: scaleY * 0.95,
|
||||
},
|
||||
{
|
||||
frame: 50 + delay,
|
||||
scaleY,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const shapes: Shape[] = [
|
||||
{
|
||||
type: 'shape',
|
||||
source: Arrow,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
originX: 0,
|
||||
originY: 0,
|
||||
x: 20,
|
||||
y: 12,
|
||||
opacity: 1,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
{
|
||||
frame: 1,
|
||||
y: 17,
|
||||
opacity: 0,
|
||||
},
|
||||
{
|
||||
frame: 30,
|
||||
y: 12,
|
||||
opacity: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
[1.2, 2.1, 3.1, 4.5, 6].forEach((scaleY, index) => {
|
||||
shapes.push({
|
||||
type: 'shape',
|
||||
source: Rect,
|
||||
frames: getRectFrames(scaleY, index),
|
||||
});
|
||||
});
|
||||
|
||||
export default function Meaningful() {
|
||||
return <InteractiveIcon shapes={shapes} />;
|
||||
}
|
45
site/theme/template/Home/DesignPage/InteractiveIcon.tsx
Normal file
45
site/theme/template/Home/DesignPage/InteractiveIcon.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import * as React from 'react';
|
||||
import Hitu, { HiTuRefObject } from '@ant-design/hitu';
|
||||
import { Shape } from '@ant-design/hitu/lib/interface';
|
||||
|
||||
const HOVER_LOOP = false;
|
||||
|
||||
export interface InteractiveIconProps {
|
||||
shapes: Shape[];
|
||||
debug?: boolean;
|
||||
frames?: number;
|
||||
}
|
||||
|
||||
export default function InteractiveIcon({ shapes, debug, frames }: InteractiveIconProps) {
|
||||
const hituRef = React.useRef<HiTuRefObject>(null);
|
||||
const [loop, setLoop] = React.useState(false);
|
||||
|
||||
return (
|
||||
<span
|
||||
onMouseEnter={() => {
|
||||
if (HOVER_LOOP) {
|
||||
setLoop(true);
|
||||
}
|
||||
|
||||
if (hituRef.current) {
|
||||
hituRef.current.triggerMotion(true);
|
||||
}
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setLoop(false);
|
||||
}}
|
||||
>
|
||||
<Hitu
|
||||
debug={debug}
|
||||
loop={loop}
|
||||
defaultPlay={false}
|
||||
ref={hituRef}
|
||||
frames={frames || 120}
|
||||
width={120}
|
||||
height={120}
|
||||
style={{ width: 120, height: 120 }}
|
||||
shapes={shapes}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
86
site/theme/template/Home/DesignPage/Meaningful.tsx
Normal file
86
site/theme/template/Home/DesignPage/Meaningful.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import * as React from 'react';
|
||||
import Hitu from '@ant-design/hitu';
|
||||
import { Shape } from '@ant-design/hitu/lib/interface';
|
||||
import InteractiveIcon from './InteractiveIcon';
|
||||
|
||||
function Heart() {
|
||||
return (
|
||||
<path
|
||||
fill="#F74455"
|
||||
d="M24.7788462,5.41153846 C24.3923077,4.51442308 23.8384615,3.7125 23.1375,3.02307692 C22.4365385,2.33653846 21.6230769,1.8 20.7144231,1.42211538 C19.7769231,1.03269231 18.7846154,0.836538462 17.7605769,0.836538462 C16.3384615,0.836538462 14.9509615,1.22596154 13.7451923,1.96153846 C13.4567308,2.1375 13.1826923,2.33076923 12.9230769,2.54134615 C12.6634615,2.33076923 12.3894231,2.1375 12.1009615,1.96153846 C10.8951923,1.22596154 9.50769231,0.836538462 8.08557692,0.836538462 C7.06153846,0.836538462 6.06923077,1.03269231 5.13173077,1.42211538 C4.22596154,1.79711538 3.40961538,2.33653846 2.70865385,3.02307692 C2.00480769,3.7125 1.45384615,4.51442308 1.06730769,5.41153846 C0.666346154,6.34326923 0.461538462,7.33269231 0.461538462,8.35096154 C0.461538462,9.31153846 0.657692308,10.3125 1.04711538,11.3307692 C1.37307692,12.1817308 1.84038462,13.0644231 2.4375,13.9557692 C3.38365385,15.3663462 4.68461538,16.8375 6.3,18.3288462 C8.97692308,20.8009615 11.6278846,22.5086538 11.7403846,22.5778846 L12.4240385,23.0163462 C12.7269231,23.2096154 13.1163462,23.2096154 13.4192308,23.0163462 L14.1028846,22.5778846 C14.2153846,22.5057692 16.8634615,20.8009615 19.5432692,18.3288462 C21.1586538,16.8375 22.4596154,15.3663462 23.4057692,13.9557692 C24.0028846,13.0644231 24.4730769,12.1817308 24.7961538,11.3307692 C25.1855769,10.3125 25.3817608,9.31153846 25.3817608,8.35096154 C25.3846154,7.33269231 25.1798077,6.34326923 24.7788462,5.41153846 Z"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Heart.width = 26;
|
||||
Heart.height = 24;
|
||||
|
||||
function Circle() {
|
||||
return <circle cx={36} cy={36} r="30" stroke="#F74455" strokeWidth={12} fill="rgba(0,0,0,0)" />;
|
||||
}
|
||||
|
||||
Circle.width = 72;
|
||||
Circle.height = 72;
|
||||
|
||||
const center = { x: 60, y: 60 };
|
||||
|
||||
const shapes: Shape[] = [
|
||||
{
|
||||
type: 'shape',
|
||||
source: Circle,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
scaleX: 1.3,
|
||||
scaleY: 1.3,
|
||||
opacity: 0.4,
|
||||
...center,
|
||||
},
|
||||
{
|
||||
frame: 20,
|
||||
scaleX: 1.5,
|
||||
scaleY: 1.5,
|
||||
opacity: 0,
|
||||
},
|
||||
{
|
||||
frame: 21,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
opacity: 0,
|
||||
},
|
||||
{
|
||||
frame: 40,
|
||||
scaleX: 1.3,
|
||||
scaleY: 1.3,
|
||||
opacity: 0.4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: Circle,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
...center,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: Heart,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
...center,
|
||||
cubic: Hitu.CUBIC_EASE,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default function Meaningful() {
|
||||
return <InteractiveIcon shapes={shapes} frames={60} />;
|
||||
}
|
124
site/theme/template/Home/DesignPage/Natural.tsx
Normal file
124
site/theme/template/Home/DesignPage/Natural.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
import * as React from 'react';
|
||||
import Hitu, { Shape } from '@ant-design/hitu';
|
||||
import InteractiveIcon from './InteractiveIcon';
|
||||
|
||||
const CenterLeaf = () => (
|
||||
<g transform="translate(-21, 0)">
|
||||
<path
|
||||
fill="#1AC2C4"
|
||||
d="M28.2905357,39.3895069 C19.5022967,30.5689999 19.0276854,22.2248468 26.8667019,14.3570476 L40.9119428,0.260236443 L41.1921968,3.90798505e-14 L41.4726726,0.260236443 L55.5179135,14.3570476 C63.2785398,22.1461688 62.8909795,30.4021645 54.3552327,39.1250346 L54.0940797,39.3895069 L41.1924185,52.3384615 L28.2905357,39.3895069 Z"
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
CenterLeaf.width = 40;
|
||||
CenterLeaf.height = 52;
|
||||
|
||||
const LeftLeaf = () => (
|
||||
<g>
|
||||
<path
|
||||
transform="scale(-1 1) translate(-38 0)"
|
||||
d="M5.09459142e-12,19.103307 C5.09459142e-12,6.367769 5.67998275,9.23705556e-14 17.0399482,9.23705556e-14 L37.3937073,9.23705556e-14 L37.7846452,0.0151941192 L37.8,0.406292705 L37.8,20.7600518 C37.8,32.0064176 31.5589496,37.6858323 19.0768488,37.798296 L18.696693,37.8 L5.09459142e-12,37.8 L5.09459142e-12,19.103307 Z"
|
||||
fill="#199598"
|
||||
/>
|
||||
<path
|
||||
d="M37.8,37.8 L19.103307,37.8 L18.7231512,37.7982398 C6.38129872,37.6870398 0.141036235,32.1332859 0.00236373579,21.1369781 L1.4814816e-12,20.7599955 L1.4814816e-12,0.406236487 L0.0153547541,0.0151379008 L37.8,37.8 Z"
|
||||
fill="#1AC2C4"
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
LeftLeaf.width = 38;
|
||||
LeftLeaf.height = 38;
|
||||
|
||||
const RightLeaf = () => (
|
||||
<g>
|
||||
<path
|
||||
transform="translate(-45 -50)"
|
||||
fill="#32A7A7"
|
||||
d="M82.4631296,49.9151931 L82.8540675,49.9303872 L82.8694223,50.3214858 L82.8694223,70.6752449 C82.8694223,81.9216107 76.6283719,87.6010254 64.1462711,87.7134891 L63.7661153,87.7151931 L45.0694223,87.7151931 L45.0694223,69.0185001 C45.0694223,56.2829621 50.749405,49.9151931 62.1093705,49.9151931 L82.4631296,49.9151931 Z M76.7205394,56 L62.7205993,56 C54.9068664,56 51,60.3799469 51,69.1398408 L51,69.1398408 L51,82 L63.8601592,82 L64.121642,81.9988279 C72.707214,81.921472 77,78.0149962 77,70.2794007 L77,70.2794007 L77,56.2794606 L76.9894385,56.010451 L76.7205394,56 Z"
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
RightLeaf.width = 38;
|
||||
RightLeaf.height = 38;
|
||||
|
||||
const shapes: Shape[] = [
|
||||
{
|
||||
type: 'shape',
|
||||
source: CenterLeaf,
|
||||
frames: [
|
||||
{ frame: 0, originY: 1, x: 60, y: 62, rotate: 0 },
|
||||
{ frame: 30, rotate: -7 },
|
||||
{ frame: 60, rotate: 9 },
|
||||
{ frame: 90, rotate: -7 },
|
||||
{ frame: 120, rotate: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: LeftLeaf,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
originX: 1,
|
||||
originY: 1,
|
||||
x: 56,
|
||||
y: 96,
|
||||
cubic: Hitu.CUBIC_EASE_IN_OUT,
|
||||
},
|
||||
{
|
||||
frame: 30,
|
||||
rotate: -4,
|
||||
|
||||
cubic: Hitu.CUBIC_EASE_IN_OUT,
|
||||
},
|
||||
{
|
||||
frame: 60,
|
||||
rotate: 6,
|
||||
cubic: Hitu.CUBIC_EASE_IN_OUT,
|
||||
},
|
||||
{
|
||||
frame: 90,
|
||||
rotate: -4,
|
||||
},
|
||||
{
|
||||
frame: 120,
|
||||
rotate: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'shape',
|
||||
source: RightLeaf,
|
||||
frames: [
|
||||
{
|
||||
frame: 0,
|
||||
originX: 0,
|
||||
originY: 1,
|
||||
x: 64,
|
||||
y: 96,
|
||||
},
|
||||
{
|
||||
frame: 30,
|
||||
rotate: -4,
|
||||
cubic: Hitu.CUBIC_EASE_IN_OUT,
|
||||
},
|
||||
{
|
||||
frame: 60,
|
||||
rotate: 6,
|
||||
cubic: Hitu.CUBIC_EASE_IN_OUT,
|
||||
},
|
||||
{
|
||||
frame: 90,
|
||||
rotate: -4,
|
||||
},
|
||||
{
|
||||
frame: 120,
|
||||
rotate: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default function Natural() {
|
||||
return <InteractiveIcon shapes={shapes} frames={80} />;
|
||||
}
|
175
site/theme/template/Home/DesignPage/index.less
Normal file
175
site/theme/template/Home/DesignPage/index.less
Normal file
@ -0,0 +1,175 @@
|
||||
@import '../../../../../components/style/themes/default.less';
|
||||
|
||||
.design-card {
|
||||
position: relative;
|
||||
min-height: 278px;
|
||||
padding: 32px 40px;
|
||||
color: #697b8c;
|
||||
line-height: 2;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
|
||||
&.main-card {
|
||||
background-image: url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*i1EySrFVZvAAAAAAAAAAAABkARQnAQ);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
color: #0d1a26;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2f54eb;
|
||||
}
|
||||
|
||||
.design-card-detail {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.design-values {
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
display: none;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&.sub-card {
|
||||
padding: 0;
|
||||
|
||||
.card-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 40px 0 32px 40px;
|
||||
|
||||
ul {
|
||||
margin-top: auto;
|
||||
|
||||
li {
|
||||
margin-top: 16px;
|
||||
|
||||
a {
|
||||
color: #2f54eb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.design-mini-panel {
|
||||
.ant-card-meta-title {
|
||||
color: #0d1a26;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
padding: 16px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.ant-card-meta-description {
|
||||
color: #697b8c;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.design-card {
|
||||
&.sub-card {
|
||||
background-image: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.design-card {
|
||||
height: 478px;
|
||||
padding: 24px 16px;
|
||||
|
||||
&.main-card {
|
||||
height: auto;
|
||||
padding-bottom: 16px;
|
||||
background-image: url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*a8u5Q4QIJzcAAAAAAAAAAABkARQnAQ);
|
||||
}
|
||||
|
||||
h3.ant-typography {
|
||||
margin-bottom: 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.design-card-detail {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-top: 12px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.design-values {
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.sub-card {
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: left 50% bottom 0% !important;
|
||||
background-size: contain !important;
|
||||
|
||||
h3.ant-typography {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.card-info {
|
||||
padding: 24px 16px 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: auto;
|
||||
|
||||
li {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.design-card-img-col {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.design-mini-panels {
|
||||
margin-top: -23px !important;
|
||||
|
||||
.design-mini-panel {
|
||||
.ant-card-body {
|
||||
padding: 16px 16px 20px;
|
||||
|
||||
.ant-card-meta-title {
|
||||
margin-bottom: 4px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
284
site/theme/template/Home/DesignPage/index.tsx
Normal file
284
site/theme/template/Home/DesignPage/index.tsx
Normal file
@ -0,0 +1,284 @@
|
||||
import * as React from 'react';
|
||||
import { Row, Col, Typography, Card } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { getLocalizedPathname } from '../../utils';
|
||||
import './index.less';
|
||||
import Certainty from './Certainty';
|
||||
import Meaningful from './Meaningful';
|
||||
import Growth from './Growth';
|
||||
import Natural from './Natural';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
interface PanelProps {
|
||||
img: string;
|
||||
title: React.ReactNode;
|
||||
description: string;
|
||||
href?: string;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
const MINI_LIST: PanelProps[] = [
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*ZhzDQLMyYlYAAAAAAAAAAABkARQnAQ',
|
||||
title: 'AntV',
|
||||
description: 'app.home.product-antv-slogan',
|
||||
href: 'https://antv.vision',
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*I-ygS5prYksAAAAAAAAAAABkARQnAQ',
|
||||
title: 'Ant Design Pro',
|
||||
description: 'app.home.product-pro-slogan',
|
||||
href: 'https://pro.ant.design/',
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*mb-WQILTlSEAAAAAAAAAAABkARQnAQ',
|
||||
title: 'Ant Design Mobile',
|
||||
description: 'app.home.product-mobile-slogan',
|
||||
href: 'https://mobile.ant.design/',
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*PrLWSpmWZmIAAAAAAAAAAABkARQnAQ',
|
||||
title: <FormattedMessage id="app.home.product-hitu" />,
|
||||
description: 'app.home.product-hitu-slogan',
|
||||
link: '/docs/spec/illustration',
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*MaL2SYtHPuMAAAAAAAAAAABkARQnAQ',
|
||||
title: 'Kitchen',
|
||||
description: 'app.home.product-kitchen-slogan',
|
||||
href: 'https://kitchen.alipay.com/',
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*T_HeSIJ30IIAAAAAAAAAAABkARQnAQ',
|
||||
title: 'Icons',
|
||||
description: 'app.home.product-icons-slogan',
|
||||
link: '/components/icon/',
|
||||
},
|
||||
];
|
||||
|
||||
const MiniPanel = ({
|
||||
title,
|
||||
img,
|
||||
description,
|
||||
href,
|
||||
link,
|
||||
isZhCN,
|
||||
}: PanelProps & { isZhCN: boolean }) => {
|
||||
let content = (
|
||||
<Card
|
||||
hoverable
|
||||
className="design-mini-panel"
|
||||
cover={<img alt={typeof title === 'string' ? title : 'Hitu'} src={img} />}
|
||||
>
|
||||
<Card.Meta title={title} description={<FormattedMessage id={description} />} />
|
||||
</Card>
|
||||
);
|
||||
|
||||
if (href) {
|
||||
content = (
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
{content}
|
||||
</a>
|
||||
);
|
||||
} else if (link) {
|
||||
content = <Link to={getLocalizedPathname(link, isZhCN)}>{content}</Link>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Col xs={24} sm={8}>
|
||||
{content}
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
export default function DesignPage() {
|
||||
const { locale } = useIntl();
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
|
||||
return (
|
||||
<div style={{ marginBottom: -28 }}>
|
||||
{/* ***************************** Group 1 ***************************** */}
|
||||
<Row gutter={[40, 40]}>
|
||||
{/* *********************** Design Values *********************** */}
|
||||
<Col span={24}>
|
||||
<div className="design-card main-card">
|
||||
<Title level={3}>
|
||||
<FormattedMessage id="app.home.design-values" />
|
||||
</Title>
|
||||
|
||||
<Row align="stretch">
|
||||
<Col xs={24} sm={8}>
|
||||
<FormattedMessage id="app.home.design-values-description" />
|
||||
|
||||
<Link
|
||||
className="design-card-detail"
|
||||
to={getLocalizedPathname('/docs/spec/values', isZhCN)}
|
||||
>
|
||||
<FormattedMessage id="app.home.detail" />
|
||||
<RightOutlined />
|
||||
</Link>
|
||||
</Col>
|
||||
<Col xs={24} sm={16}>
|
||||
<Row className="design-values">
|
||||
<Col xs={12} sm={6}>
|
||||
<img
|
||||
alt="certainty"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*43rfS4dD0MUAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
<Certainty />
|
||||
<h4>
|
||||
<FormattedMessage id="app.home.certainty" />
|
||||
</h4>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<img
|
||||
alt="meaningful"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*abGUQKUocSMAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
<Meaningful />
|
||||
<h4>
|
||||
<FormattedMessage id="app.home.meaningful" />
|
||||
</h4>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<img
|
||||
alt="growth"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*NvhsRKmTLwUAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
<Growth />
|
||||
<h4>
|
||||
<FormattedMessage id="app.home.growth" />
|
||||
</h4>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<img
|
||||
alt="natural"
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*cY0tTr8q3Y4AAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
<Natural />
|
||||
<h4>
|
||||
<FormattedMessage id="app.home.natural" />
|
||||
</h4>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
{/* *********************** Design Guides *********************** */}
|
||||
<Col xs={24} sm={12}>
|
||||
<div
|
||||
className="design-card sub-card"
|
||||
style={{
|
||||
background: '#E6F1FF',
|
||||
backgroundImage:
|
||||
'url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*0oaHSYRcnT4AAAAAAAAAAABkARQnAQ)',
|
||||
}}
|
||||
>
|
||||
<Row>
|
||||
<Col xs={24} sm={9} className="card-info">
|
||||
<Title level={3}>
|
||||
<FormattedMessage id="app.home.design-guide" />
|
||||
</Title>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Link to={getLocalizedPathname('/docs/spec/colors', isZhCN)}>
|
||||
<FormattedMessage id="app.home.global-style" />
|
||||
<RightOutlined />
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to={getLocalizedPathname('/docs/spec/overview', isZhCN)}>
|
||||
<FormattedMessage id="app.home.design-patterns" />
|
||||
<RightOutlined />
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</Col>
|
||||
<Col
|
||||
xs={24}
|
||||
sm={15}
|
||||
className="design-card-img-col"
|
||||
style={{ alignSelf: 'flex-end', textAlign: 'right' }}
|
||||
>
|
||||
<img
|
||||
alt="design guide"
|
||||
style={{ maxHeight: 278, maxWidth: '100%' }}
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*5PRzTL4pwuYAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
{/* ************************* Component ************************* */}
|
||||
<Col xs={24} sm={12}>
|
||||
<div
|
||||
className="design-card sub-card"
|
||||
style={{
|
||||
background: '#DEF6FF',
|
||||
backgroundImage:
|
||||
'url(https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*TLJTT78n7rMAAAAAAAAAAABkARQnAQ)',
|
||||
}}
|
||||
>
|
||||
<Row>
|
||||
<Col xs={24} sm={9} className="card-info">
|
||||
<Title level={3}>
|
||||
<FormattedMessage id="app.home.components" />
|
||||
</Title>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<Link to={getLocalizedPathname('/docs/react/introduce', isZhCN)}>
|
||||
Ant Design of React
|
||||
<RightOutlined />
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://ng.ant.design/" target="_blank" rel="noopener noreferrer">
|
||||
Ant Design of Angular
|
||||
<RightOutlined />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue.ant.design/" target="_blank" rel="noopener noreferrer">
|
||||
Ant Design of Vue
|
||||
<RightOutlined />
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</Col>
|
||||
<Col xs={24} sm={15} style={{ alignSelf: 'flex-end', textAlign: 'right' }}>
|
||||
<img
|
||||
alt="components"
|
||||
className="design-card-img-col"
|
||||
style={{ maxHeight: 278, maxWidth: '100%' }}
|
||||
src="https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*8VDFTbQn4UAAAAAAAAAAAABkARQnAQ"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* ***************************** Group 2 ***************************** */}
|
||||
<Row
|
||||
style={{ marginTop: 40 }}
|
||||
gutter={[
|
||||
{ xs: 32, sm: 40 },
|
||||
{ xs: 32, sm: 40 },
|
||||
]}
|
||||
className="design-mini-panels"
|
||||
>
|
||||
{MINI_LIST.map(panel => (
|
||||
<MiniPanel key={panel.description} {...panel} isZhCN={isZhCN} />
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
64
site/theme/template/Home/MorePage.less
Normal file
64
site/theme/template/Home/MorePage.less
Normal file
@ -0,0 +1,64 @@
|
||||
@import '../../../../components/style/themes/default.less';
|
||||
|
||||
.more-card {
|
||||
.ant-card-cover {
|
||||
padding: 24px 24px 0 24px;
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
color: #314659;
|
||||
}
|
||||
|
||||
.ant-card-meta-detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 170px;
|
||||
|
||||
.ant-card-meta-title {
|
||||
margin-bottom: 16px;
|
||||
color: #0d1a26;
|
||||
font-weight: 400;
|
||||
white-space: normal;
|
||||
text-overflow: initial;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.ant-card-meta-description {
|
||||
flex: auto;
|
||||
color: #697b8c;
|
||||
}
|
||||
}
|
||||
|
||||
.more-card-source {
|
||||
float: right;
|
||||
|
||||
> img {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.more-card {
|
||||
.ant-card-cover {
|
||||
margin-bottom: 12px;
|
||||
padding: 16px 16px 0 16px;
|
||||
|
||||
img {
|
||||
height: 184px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-card-meta-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
padding: 16px;
|
||||
|
||||
.ant-card-meta-detail {
|
||||
min-height: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
site/theme/template/Home/MorePage.tsx
Normal file
82
site/theme/template/Home/MorePage.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import * as React from 'react';
|
||||
import { Card, Row, Col } from 'antd';
|
||||
import './MorePage.less';
|
||||
|
||||
interface MoreProps {
|
||||
title: string;
|
||||
description: string;
|
||||
date: string;
|
||||
img: string;
|
||||
source: 'zhihu' | 'yuque';
|
||||
href: string;
|
||||
}
|
||||
|
||||
const SourceImages = {
|
||||
zhihu: 'https://gw.alipayobjects.com/zos/basement_prod/5f4e1fd0-d255-4309-b181-a3715a720ebe.svg',
|
||||
yuque: 'https://gw.alipayobjects.com/zos/basement_prod/53e7a5b8-c9f4-45a4-8378-cbf50f2dd0d0.svg',
|
||||
};
|
||||
|
||||
const MORE_LIST: MoreProps[] = [
|
||||
{
|
||||
title: 'Ant Design 1.0 背后的故事:把艺术变成技术',
|
||||
description: '本文将跟大家分享 Ant Design 1.0 诞生背后的故事,还原 3-4 年前那些事、那些人。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*Cu8LRZW_AqgAAAAAAAAAAABkARQnAQ',
|
||||
date: '2019-11-07',
|
||||
source: 'yuque',
|
||||
href: 'https://www.yuque.com/lyndon/daylesson/xw45g0',
|
||||
},
|
||||
{
|
||||
title: '「人机自然交互」Ant Design 设计价值观解析',
|
||||
description: '为何选择「自然」作为设计价值观?本文会详细阐述这背后的思考和实践。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*V-w4Q6EvVWsAAAAAAAAAAABkARQnAQ',
|
||||
date: '2019-09-26',
|
||||
source: 'zhihu',
|
||||
href: 'https://zhuanlan.zhihu.com/p/44809866',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design 色板生成算法演进之路',
|
||||
description:
|
||||
'「确定」 作为设计价值观之一,在调色板中发挥得淋漓尽致,既做到设计有迹可循,也提高代码的可维护性。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*2iP4TLjiZMwAAAAAAAAAAABkARQnAQ',
|
||||
date: '2018-03-13',
|
||||
source: 'zhihu',
|
||||
href: 'https://zhuanlan.zhihu.com/p/32422584',
|
||||
},
|
||||
{
|
||||
title: '2019,优雅的 AntV 来了',
|
||||
description:
|
||||
'对可视化系统而言,设计正是把不确定的海量、高维、非结构化的数据用准确、有效的方式传递。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*_9JJSpF6T6oAAAAAAAAAAABkARQnAQ',
|
||||
date: '2019-11-25',
|
||||
source: 'zhihu',
|
||||
href: 'https://zhuanlan.zhihu.com/p/93620507',
|
||||
},
|
||||
];
|
||||
|
||||
const MoreCard = ({ title, description, date, img, source, href }: MoreProps) => {
|
||||
return (
|
||||
<Col xs={24} sm={6}>
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
<Card hoverable cover={<img alt={title} src={img} />} className="more-card">
|
||||
<Card.Meta title={title} description={description} />
|
||||
<div>
|
||||
{date}
|
||||
<span className="more-card-source">
|
||||
<img src={SourceImages[source]} alt={source} />
|
||||
</span>
|
||||
</div>
|
||||
</Card>
|
||||
</a>
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
export default function MorePage() {
|
||||
return (
|
||||
<Row gutter={[24, 32]}>
|
||||
{MORE_LIST.map(more => (
|
||||
<MoreCard key={more.title} {...more} />
|
||||
))}
|
||||
</Row>
|
||||
);
|
||||
}
|
@ -1,321 +0,0 @@
|
||||
import React from 'react';
|
||||
import { TweenOneGroup } from 'rc-tween-one';
|
||||
import QueueAnim from 'rc-queue-anim';
|
||||
import { Row, Col } from 'antd';
|
||||
import ScrollOverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import * as utils from '../utils';
|
||||
|
||||
const page1Data = [
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/URIeCOKLMAbRXaeXoNqN.svg',
|
||||
name: '设计价值观',
|
||||
nameEn: 'Design Values',
|
||||
to: '/docs/spec/values',
|
||||
svgBg: (
|
||||
<svg
|
||||
width="213px"
|
||||
height="303px"
|
||||
viewBox="0 0 213 303"
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
>
|
||||
<circle id="Oval-12-Copy-6" fill="#1D39C4" opacity="0.45" cx="60" cy="157" r="25" />
|
||||
<circle id="Oval-12-Copy" fill="#1D39C4" opacity="0.35" cx="167.5" cy="65.5" r="11.5" />
|
||||
<rect stroke="#1D39C4" opacity="0.7" x="0.5" y="54.5" width="14" height="14" rx="1" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="195.5" cy="117.5" r="3.5" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="117" cy="2" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="82" cy="36" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="26.5" cy="102.5" r="1.5" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="180.5" cy="8.5" r="4.5" />
|
||||
<g
|
||||
id="Group-18"
|
||||
transform="translate(197.000000, 157.000000)"
|
||||
opacity="0.7"
|
||||
stroke="#1D39C4"
|
||||
>
|
||||
<path d="M10.7320508,3 L15.0621778,10.5 C15.6144626,11.4565852 15.2867123,12.6797661 14.330127,13.2320508 C14.0260886,13.4075875 13.6812003,13.5 13.330127,13.5 L4.66987298,13.5 C3.56530348,13.5 2.66987298,12.6045695 2.66987298,11.5 C2.66987298,11.1489267 2.76228551,10.8040384 2.93782217,10.5 L7.26794919,3 C7.82023394,2.04341475 9.04341475,1.71566444 10,2.26794919 C10.3040384,2.44348586 10.5565141,2.69596158 10.7320508,3 Z" />
|
||||
</g>
|
||||
<g
|
||||
id="Group-17"
|
||||
transform="translate(124.000000, 284.000000)"
|
||||
opacity="0.65"
|
||||
stroke="#1D39C4"
|
||||
>
|
||||
<path
|
||||
d="M13.7320508,6 L18.0621778,13.5 C18.6144626,14.4565852 18.2867123,15.6797661 17.330127,16.2320508 C17.0260886,16.4075875 16.6812003,16.5 16.330127,16.5 L7.66987298,16.5 C6.56530348,16.5 5.66987298,15.6045695 5.66987298,14.5 C5.66987298,14.1489267 5.76228551,13.8040384 5.93782217,13.5 L10.2679492,6 C10.8202339,5.04341475 12.0434148,4.71566444 13,5.26794919 C13.3040384,5.44348586 13.5565141,5.69596158 13.7320508,6 Z"
|
||||
transform="translate(12.000000, 11.140576) rotate(25.000000) translate(-12.000000, -11.140576) "
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/qXncdwwUTTgUFnsbCNCE.svg',
|
||||
name: '视觉',
|
||||
nameEn: 'Visual',
|
||||
to: '/docs/spec/colors',
|
||||
svgBg: (
|
||||
<svg
|
||||
width="207px"
|
||||
height="295px"
|
||||
viewBox="0 0 207 295"
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
>
|
||||
<rect stroke="#1D39C4" opacity="0.7" x="192.5" y="62.5" width="14" height="14" rx="1" />
|
||||
<circle id="Oval-12-Copy-2" fill="#1D39C4" opacity="0.45" cx="21.5" cy="90.5" r="21.5" />
|
||||
<circle id="Oval-12-Copy-3" fill="#1D39C4" opacity="0.35" cx="162.5" cy="163.5" r="14.5" />
|
||||
<rect
|
||||
stroke="#1D39C4"
|
||||
opacity="0.7"
|
||||
transform="translate(77.500000, 287.500000) rotate(30.000000) translate(-77.500000, -287.500000) "
|
||||
x="72.5"
|
||||
y="282.5"
|
||||
width="10"
|
||||
height="10"
|
||||
rx="1"
|
||||
/>
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="164.5" cy="117.5" r="3.5" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="96" cy="2" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="141" cy="36" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="34.5" cy="142.5" r="1.5" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="24.5" cy="30.5" r="4.5" />
|
||||
<g
|
||||
id="Group-19"
|
||||
transform="translate(12.000000, 173.000000)"
|
||||
opacity="0.7"
|
||||
stroke="#1D39C4"
|
||||
>
|
||||
<path
|
||||
d="M13.5216765,6.597413 L17.8518036,14.097413 C18.4040883,15.0539982 18.076338,16.2771791 17.1197527,16.8294638 C16.8157143,17.0050005 16.4708261,17.097413 16.1197527,17.097413 L7.45949871,17.097413 C6.35492921,17.097413 5.45949871,16.2019825 5.45949871,15.097413 C5.45949871,14.7463397 5.55191124,14.4014514 5.7274479,14.097413 L10.0575749,6.597413 C10.6098597,5.64082775 11.8330405,5.31307744 12.7896257,5.86536219 C13.0936641,6.04089886 13.3461399,6.29337458 13.5216765,6.597413 Z"
|
||||
transform="translate(11.789626, 11.737989) rotate(40.000000) translate(-11.789626, -11.737989) "
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/YFXXZocxAgjReehpPNbX.svg',
|
||||
name: '可视化',
|
||||
nameEn: 'Visualization',
|
||||
to: '/docs/spec/visual',
|
||||
svgBg: (
|
||||
<svg
|
||||
width="215px"
|
||||
height="286px"
|
||||
viewBox="0 0 215 286"
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
style={{ transform: 'translateX(-30px)' }}
|
||||
>
|
||||
<circle id="Oval-12-Copy-4" fill="#1D39C4" opacity="0.35" cx="77" cy="152" r="10" />
|
||||
<circle id="Oval-12-Copy-5" fill="#1D39C4" opacity="0.45" cx="194.5" cy="74.5" r="20.5" />
|
||||
<rect stroke="#1D39C4" opacity="0.7" x="0.5" y="99.5" width="13" height="13" rx="1" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="44.5" cy="117.5" r="3.5" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="132" cy="2" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="177" cy="36" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="147.5" cy="182.5" r="1.5" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="172" cy="182" r="7" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="110" cy="280" r="5" />
|
||||
<g id="Group-20" transform="translate(70.000000, 23.000000)" opacity="0.7" stroke="#1D39C4">
|
||||
<path
|
||||
d="M13.0221683,6.597413 L16.8974466,13.309592 C17.4497314,14.2661772 17.1219811,15.489358 16.1653958,16.0416428 C15.8613574,16.2171794 15.5164692,16.309592 15.1653958,16.309592 L7.41483918,16.309592 C6.31026968,16.309592 5.41483918,15.4141615 5.41483918,14.309592 C5.41483918,13.9585186 5.5072517,13.6136304 5.68278837,13.309592 L9.55806669,6.597413 C10.1103514,5.64082775 11.3335323,5.31307744 12.2901175,5.86536219 C12.5941559,6.04089886 12.8466316,6.29337458 13.0221683,6.597413 Z"
|
||||
transform="translate(11.290118, 11.262929) rotate(40.000000) translate(-11.290118, -11.262929) "
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
img: 'https://gw.alipayobjects.com/zos/rmsportal/VPuetGsvJuYBwoDkZWFW.svg',
|
||||
name: '动效',
|
||||
nameEn: 'Animation',
|
||||
to: '/docs/spec/motion',
|
||||
svgBg: (
|
||||
<svg
|
||||
width="193px"
|
||||
height="286px"
|
||||
viewBox="0 0 193 286"
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
style={{ transform: 'translateY(-20px)' }}
|
||||
>
|
||||
<circle id="Oval-12-Copy-4" fill="#1D39C4" opacity="0.35" cx="71" cy="65" r="10" />
|
||||
<circle id="Oval-12-Copy-5" fill="#1D39C4" opacity="0.45" cx="172.5" cy="154.5" r="20.5" />
|
||||
<rect stroke="#1D39C4" opacity="0.7" x="0.5" y="99.5" width="13" height="13" rx="1" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="44.5" cy="117.5" r="3.5" />
|
||||
<circle fill="#1D39C4" opacity="0.5" cx="132" cy="2" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="39" cy="34" r="2" />
|
||||
<circle fill="#1D39C4" opacity="0.6" cx="147.5" cy="182.5" r="1.5" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="55" cy="177" r="7" />
|
||||
<circle stroke="#1D39C4" opacity="0.65" cx="110" cy="280" r="5" />
|
||||
<g
|
||||
id="Group-21"
|
||||
transform="translate(171.000000, 25.000000)"
|
||||
opacity="0.7"
|
||||
stroke="#1D39C4"
|
||||
>
|
||||
<path
|
||||
d="M12.833668,6.38747836 L16.7089463,13.0996573 C17.2612311,14.0562426 16.9334808,15.2794234 15.9768955,15.8317081 C15.6728571,16.0072448 15.3279688,16.0996573 14.9768955,16.0996573 L7.22633886,16.0996573 C6.12176936,16.0996573 5.22633886,15.2042268 5.22633886,14.0996573 C5.22633886,13.748584 5.31875139,13.4036957 5.49428806,13.0996573 L9.36956638,6.38747836 C9.92185113,5.43089311 11.1450319,5.1031428 12.1016172,5.65542755 C12.4056556,5.83096421 12.6581313,6.08343994 12.833668,6.38747836 Z"
|
||||
transform="translate(11.101617, 11.052994) rotate(40.000000) translate(-11.101617, -11.052994) "
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const getTransformXY = t => {
|
||||
const s = t.replace(/[a-z()]/g, '').split(',');
|
||||
return {
|
||||
x: s[0],
|
||||
y: s[1],
|
||||
};
|
||||
};
|
||||
|
||||
const svgToXY = page1Data.map(item => {
|
||||
const c = item.svgBg.props.children;
|
||||
return c.map(child => {
|
||||
const p = child.props;
|
||||
const trnasformXY = p.transform ? getTransformXY(p.transform) : {};
|
||||
return {
|
||||
x: parseFloat(p.x || p.cx || trnasformXY.x),
|
||||
y: parseFloat(p.y || p.cy || trnasformXY.y),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
export default class Page1 extends React.PureComponent {
|
||||
state = {
|
||||
hoverKey: null,
|
||||
};
|
||||
|
||||
leave = {
|
||||
opacity: 0,
|
||||
duration: 300,
|
||||
x: 100,
|
||||
y: 150,
|
||||
ease: 'easeInBack',
|
||||
};
|
||||
|
||||
onMouseOver = key => {
|
||||
this.setState({
|
||||
hoverKey: key,
|
||||
});
|
||||
};
|
||||
|
||||
onMouseOut = () => {
|
||||
this.setState({
|
||||
hoverKey: null,
|
||||
});
|
||||
};
|
||||
|
||||
getEnter = (i, e) => {
|
||||
const ii = e.index;
|
||||
const r = Math.random() * 2 - 1;
|
||||
const y = Math.random() * 10 + 10;
|
||||
const delay = Math.round(Math.random() * (ii * 30));
|
||||
const pos = svgToXY[i][ii];
|
||||
return [
|
||||
{ x: 100, y: 150, duration: 0 },
|
||||
{
|
||||
delay,
|
||||
opacity: 1,
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
ease: 'easeOutBack',
|
||||
duration: 300,
|
||||
},
|
||||
{
|
||||
y: r > 0 ? `+=${y}` : `-=${y}`,
|
||||
duration: Math.random() * 1000 + 2000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
getSvgChild = child =>
|
||||
child.map((item, i) => {
|
||||
const props = { ...item.props };
|
||||
if (item.type === 'g') {
|
||||
props.transform = null;
|
||||
} else {
|
||||
['x', 'y', 'cx', 'cy'].forEach(str => {
|
||||
if (str in props) {
|
||||
props[str] = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
return <g key={i.toString()}>{React.cloneElement(item, props)}</g>;
|
||||
});
|
||||
|
||||
render() {
|
||||
const { locale, isMobile } = this.props;
|
||||
const { hoverKey } = this.state;
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
const children = page1Data.map((item, i) => {
|
||||
const isHover = item.nameEn === hoverKey;
|
||||
return (
|
||||
<Col key={item.nameEn} md={6} xs={24}>
|
||||
<TweenOneGroup
|
||||
className="page1-point-wrapper"
|
||||
enter={e => this.getEnter(i, e)}
|
||||
leave={this.leave}
|
||||
{...item.svgBg.props}
|
||||
component="svg"
|
||||
resetStyle={false}
|
||||
exclusive
|
||||
>
|
||||
{(isMobile || isHover) && this.getSvgChild(item.svgBg.props.children)}
|
||||
</TweenOneGroup>
|
||||
<QueueAnim
|
||||
className="page1-block"
|
||||
type="bottom"
|
||||
component={Link}
|
||||
componentProps={{ to: utils.getLocalizedPathname(item.to, isZhCN) }}
|
||||
onMouseEnter={() => {
|
||||
this.onMouseOver(item.nameEn);
|
||||
}}
|
||||
onMouseLeave={this.onMouseOut}
|
||||
>
|
||||
<div className="page1-image">
|
||||
<img src={item.img} alt="icon" />
|
||||
</div>
|
||||
<h3>{isZhCN ? item.name : item.nameEn}</h3>
|
||||
</QueueAnim>
|
||||
</Col>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="home-page-wrapper page1">
|
||||
<div className="page">
|
||||
<h2>
|
||||
<FormattedMessage id="app.home.design-language" />
|
||||
</h2>
|
||||
<ScrollOverPack playScale="0.3">
|
||||
<QueueAnim
|
||||
component={Row}
|
||||
key="queue"
|
||||
type="bottom"
|
||||
ease={['easeOutQuart', 'easeInQuart']}
|
||||
leaveReverse
|
||||
>
|
||||
{children}
|
||||
</QueueAnim>
|
||||
</ScrollOverPack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -139,11 +139,21 @@ export default function Page2({ isMobile, locale }) {
|
||||
const mobileContent = (
|
||||
<div className="components-button-wrapper">
|
||||
<p key="p">{item.slogan}</p>
|
||||
<a className="more-mobile-react" href="https://mobile.ant.design" target="_blank" rel="noopener noreferrer">
|
||||
<a
|
||||
className="more-mobile-react"
|
||||
href="https://mobile.ant.design"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<FormattedMessage id="app.home.more-mobile-react" />
|
||||
<Icon type="right" />
|
||||
</a>
|
||||
<a className="more-mobile-angular" href="http://ng.mobile.ant.design" target="_blank" rel="noopener noreferrer">
|
||||
<a
|
||||
className="more-mobile-angular"
|
||||
href="http://ng.mobile.ant.design"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<FormattedMessage id="app.home.more-mobile-angular" />
|
||||
<Icon type="right" />
|
||||
</a>
|
||||
|
104
site/theme/template/Home/RecommendPage.less
Normal file
104
site/theme/template/Home/RecommendPage.less
Normal file
@ -0,0 +1,104 @@
|
||||
@import '../../../../components/style/themes/default.less';
|
||||
|
||||
.recommend-block {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 192px;
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
background-clip: cover;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 0, 0.25) 30%,
|
||||
rgba(0, 0, 0, 0.5) 100%
|
||||
);
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.recommend-popularize {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0 8px;
|
||||
color: #314659;
|
||||
line-height: 28px;
|
||||
background: #ffd75a;
|
||||
border-radius: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.recommend-content {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 0 20px 24px;
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.3s;
|
||||
|
||||
.ant-typography {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
h4 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 0 20px 24px;
|
||||
transform: translateY(-100%);
|
||||
transition: padding 0.3s;
|
||||
}
|
||||
|
||||
p {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s, margin 0.3s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.recommend-block {
|
||||
h4.ant-typography {
|
||||
padding: 0 16px 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.recommend-block {
|
||||
&-main {
|
||||
height: 408px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.recommend-content {
|
||||
transform: translateY(0);
|
||||
|
||||
h4 {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
site/theme/template/Home/RecommendPage.tsx
Normal file
94
site/theme/template/Home/RecommendPage.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Row, Col, Typography } from 'antd';
|
||||
import './RecommendPage.less';
|
||||
|
||||
const { Title, Paragraph } = Typography;
|
||||
|
||||
interface Recommend {
|
||||
title: string;
|
||||
img: string;
|
||||
href: string;
|
||||
popularize?: boolean;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const LIST: Recommend[] = [
|
||||
{
|
||||
title: '语雀·我们都喜欢的文档工具',
|
||||
description:
|
||||
'「语雀」致力于打造新一代 Office,是一个「专业的云端知识库」。在阿里内部已是 10 万员工进行文档编写、知识沉淀的标配。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*2_q2TZo-_zoAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://www.yuque.com/dashboard',
|
||||
popularize: true,
|
||||
},
|
||||
{
|
||||
title: 'AntV·让数据栩栩如生',
|
||||
description:
|
||||
'AntV 是蚂蚁金服全新一代数据可视化解决方案,致力于提供一套简单方便、专业可靠、无限可能的数据可视化最佳实践。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*6C3USLyLwh4AAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://antv.vision/zh',
|
||||
},
|
||||
{
|
||||
title: 'Kitchen·让你的设计秀色可餐',
|
||||
description: '一款为设计者提升工作效率的 Sketch 工具集',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*2b-XQJuyRSwAAAAAAAAAAABkARQnAQ',
|
||||
href: 'https://kitchen.alipay.com/',
|
||||
},
|
||||
];
|
||||
|
||||
interface RecommendBlockProps extends Recommend {
|
||||
main?: boolean;
|
||||
img: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
const RecommendBlock = ({
|
||||
main,
|
||||
title,
|
||||
popularize,
|
||||
description,
|
||||
img,
|
||||
href,
|
||||
}: RecommendBlockProps) => {
|
||||
return (
|
||||
<a
|
||||
className={classNames('recommend-block', main && 'recommend-block-main')}
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img src={img} alt={title} />
|
||||
{popularize && (
|
||||
<span className="recommend-popularize">
|
||||
<FormattedMessage id="app.home.popularize" />
|
||||
</span>
|
||||
)}
|
||||
<div className="recommend-content">
|
||||
<Title level={4}>{title}</Title>
|
||||
<Paragraph>{description}</Paragraph>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default function RecommendPage() {
|
||||
return (
|
||||
<Row gutter={[24, 24]} style={{ marginBottom: -36 }}>
|
||||
<Col xs={24} sm={14}>
|
||||
<RecommendBlock {...LIST[0]} main />
|
||||
</Col>
|
||||
<Col xs={24} sm={10}>
|
||||
<Row gutter={[24, 24]}>
|
||||
<Col span={24}>
|
||||
<RecommendBlock {...LIST[1]} />
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<RecommendBlock {...LIST[2]} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
import React from 'react';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import PropTypes from 'prop-types';
|
||||
import Banner from './Banner';
|
||||
import Page1 from './Page1';
|
||||
import Page2 from './Page2';
|
||||
import Page3 from './Page3';
|
||||
import Footer from '../Layout/Footer';
|
||||
|
||||
// To store style which is only for Home and has conflicts with others.
|
||||
function getStyle() {
|
||||
return `
|
||||
.main-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
#header {
|
||||
box-shadow: none;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
margin: 20px auto 0;
|
||||
padding: 0 24px;
|
||||
}
|
||||
#header,
|
||||
#header .ant-select-selection,
|
||||
#header .ant-menu {
|
||||
background: transparent;
|
||||
}
|
||||
#header #logo {
|
||||
padding: 0;
|
||||
}
|
||||
#header #nav .ant-menu-item {
|
||||
border-color: transparent;
|
||||
}
|
||||
#header #nav .ant-menu-submenu {
|
||||
border-color: transparent;
|
||||
}
|
||||
#header #nav .ant-menu-item.hide-in-home-page {
|
||||
display: none;
|
||||
}
|
||||
#header .ant-row > div:last-child .header-lang-button {
|
||||
margin-right: 0;
|
||||
}
|
||||
.rc-footer-container {
|
||||
max-width: 1200px;
|
||||
padding: 80px 0;
|
||||
}
|
||||
|
||||
.rc-footer-bottom-container {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.rc-footer-columns {
|
||||
justify-content: space-around;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/prefer-stateless-function
|
||||
class Home extends React.Component {
|
||||
static contextTypes = {
|
||||
isMobile: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const { isMobile } = this.context;
|
||||
const childProps = { ...this.props, isMobile, locale: intl.locale };
|
||||
return (
|
||||
<>
|
||||
<style dangerouslySetInnerHTML={{ __html: getStyle() }} /> {/* eslint-disable-line */}
|
||||
<Helmet encodeSpecialCharacters={false}>
|
||||
<title>{`Ant Design - ${intl.formatMessage({ id: 'app.home.slogan' })}`}</title>
|
||||
</Helmet>
|
||||
<Banner {...childProps} />
|
||||
<Page1 {...childProps} />
|
||||
<Page2 {...childProps} />
|
||||
<Page3 {...childProps} />
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(Home);
|
42
site/theme/template/Home/index.less
Normal file
42
site/theme/template/Home/index.less
Normal file
@ -0,0 +1,42 @@
|
||||
@import '../../../../components/style/themes/default.less';
|
||||
|
||||
.home-container {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
&.ant-typography {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-card-hoverable:hover {
|
||||
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.08),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.home-block-content {
|
||||
margin: 88px 24px 124px;
|
||||
|
||||
h2.ant-typography {
|
||||
margin-bottom: 56px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.home-container {
|
||||
.home-block-content {
|
||||
margin-top: 64px;
|
||||
margin-bottom: 96px;
|
||||
|
||||
h2.ant-typography {
|
||||
margin-bottom: 44px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
site/theme/template/Home/index.tsx
Normal file
78
site/theme/template/Home/index.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import * as React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Typography } from 'antd';
|
||||
import { Link } from 'bisheng/router';
|
||||
import Banner from './Banner';
|
||||
import RecommendPage from './RecommendPage';
|
||||
import DesignPage from './DesignPage';
|
||||
import MorePage from './MorePage';
|
||||
import Footer from '../Layout/Footer';
|
||||
import { getLocalizedPathname } from '../utils';
|
||||
import './index.less';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
function getStyle() {
|
||||
return `
|
||||
.rc-footer-container {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.rc-footer-columns {
|
||||
max-width: 1208px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
interface BlockContentProps {
|
||||
title: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
}
|
||||
|
||||
const BlockContent: React.FC<BlockContentProps> = ({ title, children, extra }) => (
|
||||
<div className="home-block-content">
|
||||
<Title level={2} style={{ fontWeight: 'lighter', color: '#314659' }}>
|
||||
{title}
|
||||
|
||||
{extra && (
|
||||
<div style={{ float: 'right', fontSize: 16, fontWeight: 200, paddingTop: 12 }}>{extra}</div>
|
||||
)}
|
||||
</Title>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function Home() {
|
||||
const { locale } = useIntl();
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
|
||||
return (
|
||||
<div className="home-container">
|
||||
<style dangerouslySetInnerHTML={{ __html: getStyle() }} /> {/* eslint-disable-line */}
|
||||
<Banner />
|
||||
<div style={{ maxWidth: 1256, margin: '0 auto' }}>
|
||||
<BlockContent title={<FormattedMessage id="app.home.recommend" />}>
|
||||
<RecommendPage />
|
||||
</BlockContent>
|
||||
|
||||
<BlockContent title={<FormattedMessage id="app.home.design-and-framework" />}>
|
||||
<DesignPage />
|
||||
</BlockContent>
|
||||
|
||||
<BlockContent
|
||||
title={<FormattedMessage id="app.home.more" />}
|
||||
extra={
|
||||
<Link to={getLocalizedPathname('/docs/spec/article', isZhCN)}>
|
||||
<FormattedMessage id="app.home.view-more" />
|
||||
</Link>
|
||||
}
|
||||
>
|
||||
<MorePage />
|
||||
</BlockContent>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/* eslint no-undef: 0 */
|
||||
import React from 'react';
|
||||
import ScrollParallax from 'rc-scroll-anim/lib/ScrollParallax';
|
||||
|
||||
function ParallaxG(props) {
|
||||
return <ScrollParallax component="g" {...props} />;
|
||||
}
|
||||
|
||||
export default function svgBgToParallax(children, i = 0) {
|
||||
const svgChildren = React.Children.toArray(children).map((child, ii) => (
|
||||
<ParallaxG
|
||||
key={ii.toString()}
|
||||
location="page2"
|
||||
animation={{
|
||||
y: Math.random() * -200 - 30 - i * 20,
|
||||
playScale: [0, Math.random() + 2],
|
||||
}}
|
||||
>
|
||||
{child}
|
||||
</ParallaxG>
|
||||
));
|
||||
return svgChildren;
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
// 图处预加载;
|
||||
const div = document.createElement('div');
|
||||
div.style.display = 'none';
|
||||
document.body.appendChild(div);
|
||||
[
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/DJWUmdpxcQakQHwhPjzf.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/DEaRdiYbAyVNRelJpwXx.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/cCmuVrmQIJYlrhFjiPDZ.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/TOElddMOrCWlgZvWTJna.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/FpKOqFadwoFFIZFExjaf.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/IauKICnGjGnotJBEyCRK.png',
|
||||
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/URIeCOKLMAbRXaeXoNqN.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/qXncdwwUTTgUFnsbCNCE.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/YFXXZocxAgjReehpPNbX.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/VPuetGsvJuYBwoDkZWFW.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/eYNnmGagLWdrkdMHVUuA.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/EPaPtDVGnJhyqyBAUZMl.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/GobRAKexhfTSJdLFzDFY.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/slVtnOCcgeAcLEPwtewY.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/UtBesTOkoZsBUxPqfDlZ.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/VrADJaRPMnFjmtmIhObV.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/MnLEmwjipfhzPUmBJnJE.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/dyNuxLOZtvjoHSVisbhQ.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/qggKjIGNFlVmMpwDUXPU.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/dgjVqwkJvptQEtlfctvk.svg',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/vUxYuDdsbBBcMDxSGmwc.svg',
|
||||
].forEach(src => {
|
||||
const img = new Image();
|
||||
img.src = src;
|
||||
div.appendChild(img);
|
||||
});
|
||||
}
|
15
site/theme/template/Home/util.tsx
Normal file
15
site/theme/template/Home/util.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
|
||||
export function preLoad(list: string[]) {
|
||||
if (typeof window !== 'undefined') {
|
||||
// 图处预加载;
|
||||
const div = document.createElement('div');
|
||||
div.style.display = 'none';
|
||||
document.body.appendChild(div);
|
||||
list.forEach(src => {
|
||||
const img = new Image();
|
||||
img.src = src;
|
||||
div.appendChild(img);
|
||||
});
|
||||
}
|
||||
}
|
4
site/theme/template/Layout/Footer.d.ts
vendored
Normal file
4
site/theme/template/Layout/Footer.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import * as React from 'react';
|
||||
|
||||
declare function Footer(): JSX.Element;
|
||||
export default Footer;
|
@ -4,7 +4,21 @@ import { Modal, message } from 'antd';
|
||||
import { Link } from 'bisheng/router';
|
||||
import RcFooter from 'rc-footer';
|
||||
import { presetPalettes } from '@ant-design/colors';
|
||||
import Icon from '../Icon';
|
||||
import {
|
||||
AntDesignOutlined,
|
||||
MediumOutlined,
|
||||
TwitterOutlined,
|
||||
ZhihuOutlined,
|
||||
UsergroupAddOutlined,
|
||||
GithubOutlined,
|
||||
HistoryOutlined,
|
||||
ProfileOutlined,
|
||||
BugOutlined,
|
||||
IssuesCloseOutlined,
|
||||
BookOutlined,
|
||||
MessageOutlined,
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { isLocalStorageNameSupported, loadScript, getLocalizedPathname } from '../utils';
|
||||
import ColorPicker from '../Color/ColorPicker';
|
||||
|
||||
@ -116,44 +130,44 @@ class Footer extends React.Component {
|
||||
title: <FormattedMessage id="app.footer.community" />,
|
||||
items: [
|
||||
{
|
||||
icon: <Icon type="ant-design" />,
|
||||
icon: <AntDesignOutlined />,
|
||||
title: <FormattedMessage id="app.footer.awesome" />,
|
||||
url: 'https://github.com/websemantics/awesome-ant-design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="medium" />,
|
||||
icon: <MediumOutlined />,
|
||||
title: 'Medium',
|
||||
url: 'http://medium.com/ant-design/',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="twitter" style={{ color: '#1DA1F2' }} />,
|
||||
icon: <TwitterOutlined style={{ color: '#1DA1F2' }} />,
|
||||
title: 'Twitter',
|
||||
url: 'http://twitter.com/antdesignui',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="zhihu" style={{ color: '#0084ff' }} />,
|
||||
icon: <ZhihuOutlined style={{ color: '#0084ff' }} />,
|
||||
title: <FormattedMessage id="app.footer.zhihu" />,
|
||||
url: 'http://zhuanlan.zhihu.com/antdesign',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="zhihu" style={{ color: '#0084ff' }} />,
|
||||
icon: <ZhihuOutlined style={{ color: '#0084ff' }} />,
|
||||
title: <FormattedMessage id="app.footer.zhihu.xtech" />,
|
||||
url: 'http://zhuanlan.zhihu.com/xtech',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="zhihu" style={{ color: '#0084ff' }} />,
|
||||
icon: <ZhihuOutlined style={{ color: '#0084ff' }} />,
|
||||
title: 'SEE Conf',
|
||||
description: <FormattedMessage id="app.footer.seeconf" />,
|
||||
url: 'https://seeconf.antfin.com/',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="usergroup-add" />,
|
||||
icon: <UsergroupAddOutlined />,
|
||||
title: <FormattedMessage id="app.footer.work_with_us" />,
|
||||
url: getLocalizedPathname('/docs/spec/work-with-us', isZhCN),
|
||||
LinkComponent: Link,
|
||||
@ -164,61 +178,61 @@ class Footer extends React.Component {
|
||||
title: <FormattedMessage id="app.footer.help" />,
|
||||
items: [
|
||||
{
|
||||
icon: <Icon type="github" />,
|
||||
icon: <GithubOutlined />,
|
||||
title: 'GitHub',
|
||||
url: 'https://github.com/ant-design/ant-design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="history" />,
|
||||
icon: <HistoryOutlined />,
|
||||
title: <FormattedMessage id="app.footer.change-log" />,
|
||||
url: getLocalizedPathname('/changelog', isZhCN),
|
||||
LinkComponent: Link,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="profile" />,
|
||||
icon: <ProfileOutlined />,
|
||||
title: <FormattedMessage id="app.footer.faq" />,
|
||||
url: getLocalizedPathname('/docs/react/faq', isZhCN),
|
||||
LinkComponent: Link,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="bug" />,
|
||||
icon: <BugOutlined />,
|
||||
title: <FormattedMessage id="app.footer.bug-report" />,
|
||||
url: 'https://new-issue.ant.design/',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="issues-close" />,
|
||||
icon: <IssuesCloseOutlined />,
|
||||
title: <FormattedMessage id="app.footer.issues" />,
|
||||
url: 'https://github.com/ant-design/ant-design/issues',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="book" />,
|
||||
icon: <BookOutlined />,
|
||||
title: <FormattedMessage id="app.footer.course" />,
|
||||
url: 'https://www.yuque.com/ant-design/course',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="message" />,
|
||||
icon: <MessageOutlined />,
|
||||
title: <FormattedMessage id="app.footer.discuss-cn" />,
|
||||
url: 'https://gitter.im/ant-design/ant-design',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="message" />,
|
||||
icon: <MessageOutlined />,
|
||||
title: <FormattedMessage id="app.footer.discuss-en" />,
|
||||
url: 'https://gitter.im/ant-design/ant-design-english',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="question-circle" />,
|
||||
icon: <QuestionCircleOutlined />,
|
||||
title: <FormattedMessage id="app.footer.stackoverflow" />,
|
||||
url: 'http://stackoverflow.com/questions/tagged/antd',
|
||||
openExternal: true,
|
||||
},
|
||||
{
|
||||
icon: <Icon type="question-circle" />,
|
||||
icon: <QuestionCircleOutlined />,
|
||||
title: <FormattedMessage id="app.footer.segmentfault" />,
|
||||
url: 'https://segmentfault.com/t/antd',
|
||||
openExternal: true,
|
||||
@ -328,7 +342,6 @@ class Footer extends React.Component {
|
||||
})
|
||||
.then(() => {
|
||||
hide();
|
||||
Icon.setTwoToneColor({ primaryColor: color });
|
||||
message.success(messages['app.footer.primary-color-changed']);
|
||||
this.setState({ color });
|
||||
});
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import GitHubButton from 'react-github-button';
|
||||
import { Link } from 'bisheng/router';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { SearchOutlined, MenuOutlined } from '@ant-design/icons';
|
||||
import { Select, Menu, Row, Col, Popover, Input, Button, Badge } from 'antd';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import * as utils from '../utils';
|
||||
import { version as antdVersion } from '../../../../package.json';
|
||||
|
||||
@ -120,8 +120,9 @@ class Header extends React.Component {
|
||||
{version}
|
||||
</Option>
|
||||
));
|
||||
const module = location.pathname
|
||||
.replace(/(^\/|\/$)/g, '')
|
||||
|
||||
const pathname = location.pathname.replace(/(^\/|\/$)/g, '');
|
||||
const module = pathname
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
.join('/');
|
||||
@ -129,15 +130,21 @@ class Header extends React.Component {
|
||||
if (location.pathname === 'changelog') {
|
||||
activeMenuItem = 'docs/react';
|
||||
}
|
||||
|
||||
const isHome = ['', 'index', 'index-cn'].includes(pathname);
|
||||
|
||||
const isZhCN = locale === 'zh-CN';
|
||||
|
||||
const headerClassName = classNames({
|
||||
clearfix: true,
|
||||
'home-header': isHome,
|
||||
});
|
||||
|
||||
const menu = [
|
||||
isHome ? (
|
||||
<GitHubButton key="github" type="stargazers" namespace="ant-design" repo="ant-design" />
|
||||
) : null,
|
||||
<Button
|
||||
ghost
|
||||
size="small"
|
||||
onClick={this.handleLangChange}
|
||||
className="header-lang-button"
|
||||
@ -164,11 +171,13 @@ class Header extends React.Component {
|
||||
id="nav"
|
||||
key="nav"
|
||||
>
|
||||
<Menu.Item key="home" className="hide-in-home-page">
|
||||
<Link to={utils.getLocalizedPathname('/', isZhCN)}>
|
||||
<FormattedMessage id="app.header.menu.home" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
{isHome ? null : (
|
||||
<Menu.Item key="home" className="hide-in-home-page">
|
||||
<Link to={utils.getLocalizedPathname('/', isZhCN)}>
|
||||
<FormattedMessage id="app.header.menu.home" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Item key="docs/spec">
|
||||
<Link to={utils.getLocalizedPathname('/docs/spec/introduce', isZhCN)}>
|
||||
<FormattedMessage id="app.header.menu.spec" />
|
||||
@ -254,7 +263,7 @@ class Header extends React.Component {
|
||||
arrowPointAtCenter
|
||||
onVisibleChange={this.onMenuVisibleChange}
|
||||
>
|
||||
<Icon className="nav-phone-icon" type="menu" onClick={this.handleShowMenu} />
|
||||
<MenuOutlined className="nav-phone-icon" onClick={this.handleShowMenu} />
|
||||
</Popover>
|
||||
)}
|
||||
<Row>
|
||||
@ -272,7 +281,7 @@ class Header extends React.Component {
|
||||
</Col>
|
||||
<Col xxl={20} xl={19} lg={19} md={19} sm={0} xs={0}>
|
||||
<div id="search-box">
|
||||
<Icon type="search" />
|
||||
<SearchOutlined />
|
||||
<Input
|
||||
ref={ref => {
|
||||
this.searchInput = ref;
|
||||
|
12
site/theme/template/utils.d.ts
vendored
Normal file
12
site/theme/template/utils.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
export = Util;
|
||||
export as namespace Util;
|
||||
|
||||
declare namespace Util {
|
||||
function getMenuItems(...args: any[]): string;
|
||||
function isZhCN(pathname: string): boolean;
|
||||
function getLocalizedPathname(path: string, isChinese: boolean): string;
|
||||
function ping(callback: Function): string;
|
||||
function isLocalStorageNameSupported(): boolean;
|
||||
function loadScript(src: string): void;
|
||||
function getMetaDescription(jml: any): any;
|
||||
}
|
@ -7,10 +7,23 @@ export function getMenuItems(moduleData, locale, categoryOrder, typeOrder) {
|
||||
const menuItems = [];
|
||||
const sortFn = (a, b) => (a.order || 0) - (b.order || 0);
|
||||
menuMeta.sort(sortFn).forEach(meta => {
|
||||
// Format
|
||||
if (meta.category) {
|
||||
meta.category = meta.category[locale] || meta.category;
|
||||
}
|
||||
if (meta.type) {
|
||||
meta.type = meta.type[locale] || meta.type;
|
||||
}
|
||||
if (meta.title) {
|
||||
meta.title = meta.title[locale] || meta.title;
|
||||
}
|
||||
|
||||
if (!meta.category) {
|
||||
menuItems.push(meta);
|
||||
return;
|
||||
}
|
||||
|
||||
// Component
|
||||
if (meta.category === 'Components' && meta.type) {
|
||||
let type = menuItems.find(i => i.title === meta.type);
|
||||
if (!type) {
|
||||
@ -25,27 +38,50 @@ export function getMenuItems(moduleData, locale, categoryOrder, typeOrder) {
|
||||
type.children.push(meta);
|
||||
return;
|
||||
}
|
||||
const category = meta.category[locale] || meta.category;
|
||||
let group = menuItems.find(i => i.title === category);
|
||||
|
||||
let group = menuItems.find(i => i.title === meta.category);
|
||||
|
||||
if (!group) {
|
||||
group = {
|
||||
type: 'category',
|
||||
title: category,
|
||||
title: meta.category,
|
||||
children: [],
|
||||
order: categoryOrder[category],
|
||||
order: categoryOrder[meta.category],
|
||||
};
|
||||
menuItems.push(group);
|
||||
}
|
||||
group.children.push(meta);
|
||||
});
|
||||
return menuItems
|
||||
.map(i => {
|
||||
if (i.children) {
|
||||
i.children = i.children.sort(sortFn);
|
||||
|
||||
if (meta.type) {
|
||||
let type = group.children.filter(i => i.title === meta.type)[0];
|
||||
if (!type) {
|
||||
type = {
|
||||
type: 'type',
|
||||
title: meta.type,
|
||||
children: [],
|
||||
order: typeOrder[meta.type],
|
||||
};
|
||||
group.children.push(type);
|
||||
}
|
||||
return i;
|
||||
})
|
||||
.sort(sortFn);
|
||||
type.children.push(meta);
|
||||
} else {
|
||||
group.children.push(meta);
|
||||
}
|
||||
});
|
||||
|
||||
function nestSort(list) {
|
||||
return list.sort(sortFn).map(item => {
|
||||
if (item.children) {
|
||||
return {
|
||||
...item,
|
||||
children: nestSort(item.children),
|
||||
};
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
return nestSort(menuItems);
|
||||
}
|
||||
|
||||
export function isZhCN(pathname) {
|
||||
|
@ -29,30 +29,34 @@ module.exports = {
|
||||
'app.demo.stackblitz': '在 Stackblitz 中打开',
|
||||
'app.demo.riddle': '在 Riddle 中打开',
|
||||
'app.home.slogan': '一个 UI 设计语言',
|
||||
'app.home.introduce':
|
||||
'服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。',
|
||||
'app.home.design-language': '设计语言',
|
||||
'app.home.solution': '解决方案',
|
||||
'app.home.components-explain':
|
||||
'基于 Ant Design 设计语言,我们提供了开箱即用的高质量 React 和 Angular 组件实现,用于开发和服务于企业级中后台产品。',
|
||||
'app.home.product-pro-slogan': '开箱即用的中台前端/设计解决方案',
|
||||
'app.home.product-mobile-slogan': 'antd-mobile 是 Ant Design 移动规范的实现',
|
||||
'app.home.product-antv-slogan': '简单、专业、拥有无限可能的数据可视化解决方案',
|
||||
'app.home.product-landing-slogan': '基于 Ant Design 设计语言的 Landing 模板与规范',
|
||||
'app.home.tool-title': '工具和资源',
|
||||
'app.home.tool-package-title': 'Ant Design 资源包',
|
||||
'app.home.tool-package-content': 'Ant Design 相关设计资源下载',
|
||||
'app.home.tool-library-title': 'Axure Library',
|
||||
'app.home.tool-library-content': '一套精美得像视觉稿的 Axure 组件库',
|
||||
'app.home.tool-kitchen-title': 'Kitchen',
|
||||
'app.home.tool-kitchen-content': '一个为设计师提效的 Sketch 工具集',
|
||||
'app.home.introduce': '企业级产品设计体系,创造高效愉悦的工作体验',
|
||||
'app.home.recommend': '精彩推荐',
|
||||
'app.home.popularize': '推广',
|
||||
'app.home.design-and-framework': '设计语言与研发框架',
|
||||
'app.home.design-values': '设计价值观',
|
||||
'app.home.design-values-description':
|
||||
'这是 Ant Design 评价设计好坏的内在标准。基于「每个人都追求快乐工作」这一假定,我们在「确定性」和「自然」的基础上,新增「意义感」和「生长性」两个价值观,指引每个设计者做更好地判断和决策。',
|
||||
'app.home.certainty': '确定性',
|
||||
'app.home.meaningful': '意义感',
|
||||
'app.home.growth': '生长性',
|
||||
'app.home.natural': '自然',
|
||||
'app.home.design-guide': '设计指引',
|
||||
'app.home.components': '组件库',
|
||||
'app.home.detail': '查看详情',
|
||||
'app.home.global-style': '全局样式',
|
||||
'app.home.design-patterns': '设计模式',
|
||||
'app.home.more': '更多内容',
|
||||
'app.home.play-video': '播放视频',
|
||||
'app.home.getting-started': '开始使用',
|
||||
'app.home.recommend': '推荐',
|
||||
'app.home.recommend.yuque': '语雀,我们都喜欢的文档工具',
|
||||
'app.home.recommend.antv.g2plot': 'G2Plot:全新企业级图表',
|
||||
'app.home.more': '查看更多',
|
||||
'app.home.more-mobile-react': 'Ant Design Mobile of React',
|
||||
'app.home.more-mobile-angular': 'Ant Design Mobile of Angular',
|
||||
'app.home.design-language': '设计语言',
|
||||
'app.home.product-antv-slogan': '全新一代数据可视化解决方案',
|
||||
'app.home.product-pro-slogan': '开箱即用的中台前端/设计解决方案',
|
||||
'app.home.product-mobile-slogan': '一个基于 Preact / React / React Native 的 UI 组件库',
|
||||
'app.home.product-hitu': '海兔',
|
||||
'app.home.product-hitu-slogan': '全新一代图形化解决方案',
|
||||
'app.home.product-kitchen-slogan': '一款为设计者提升工作效率的 Sketch 工具集',
|
||||
'app.home.product-icons-slogan': '一整套优质的图标集',
|
||||
'app.home.view-more': '查看全部',
|
||||
'app.footer.repo': 'GitHub 仓库',
|
||||
'app.footer.awesome': 'Awesome Ant Design',
|
||||
'app.footer.course': 'Ant Design 实战教程',
|
||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -8,6 +8,8 @@ declare module '*.svg' {
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module 'bisheng/router';
|
||||
|
||||
declare module 'rc-pagination/*';
|
||||
|
||||
declare module 'omit.js';
|
||||
|
Loading…
Reference in New Issue
Block a user