Browse Source

feat: support compact theme (#22126)

* feat: support narrow theme mode

* chore: rename narrow to compact

* chore: height part

* chore: preview compact mode

* chore: to make site corrected

* chore: preview site

* docs: 📖 document compact theme usage

* docs: tweak theme doc

* docs: 📖 Add description about double css bundle size

* chore: preview

* chore: for preview

* chore: adjust pagination

* chore: compact mode done!

* chore: remove useless todo

* chore: fix review bug

* chore: fix review bug

* chore: fix card margin

* chore: fix review bug

* chore: fix review bug

* chore: improve i18n and transition

* Update site/theme/static/common.less

Co-Authored-By: 偏右 <afc163@gmail.com>

* chore: fix button size and description padding

* chore: update snapshots

* chore: add compact css bundlesize limit

* chore: compact dist support

Co-authored-by: afc163 <afc163@gmail.com>
pull/22712/head
zefeng 5 years ago
committed by GitHub
parent
commit
dda45e4796
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      .antd-tools.config.js
  2. 6
      components/alert/style/index.less
  3. 2
      components/auto-complete/style/index.less
  4. 2
      components/button/style/index.less
  5. 16
      components/button/style/mixin.less
  6. 9
      components/card/style/index.less
  7. 5
      components/card/style/size.less
  8. 2
      components/collapse/demo/basic.md
  9. 1
      components/collapse/demo/custom.md
  10. 10
      components/comment/style/index.less
  11. 4
      components/date-picker/style/index.less
  12. 4
      components/date-picker/style/panel.less
  13. 12
      components/descriptions/style/index.less
  14. 6
      components/drawer/demo/basic-right.md
  15. 6
      components/drawer/style/drawer.less
  16. 3
      components/form/demo/advanced-search.md
  17. 6
      components/input/__tests__/__snapshots__/demo.test.js.snap
  18. 22
      components/input/demo/addon.md
  19. 4
      components/input/style/allow-clear.less
  20. 6
      components/layout/demo/fixed.md
  21. 6
      components/layout/demo/top-side-2.md
  22. 6
      components/layout/demo/top-side.md
  23. 6
      components/layout/demo/top.md
  24. 26
      components/list/style/bordered.less
  25. 24
      components/list/style/index.less
  26. 52
      components/menu/__tests__/index.test.js
  27. 3
      components/menu/style/index.less
  28. 2
      components/modal/style/confirm.less
  29. 8
      components/modal/style/modal.less
  30. 18
      components/page-header/style/index.less
  31. 4
      components/pagination/style/index.less
  32. 2
      components/popover/demo/basic.md
  33. 6
      components/popover/style/index.less
  34. 3
      components/select/style/index.less
  35. 10
      components/select/style/multiple.less
  36. 10
      components/select/style/single.less
  37. 12
      components/skeleton/style/index.less
  38. 2
      components/statistic/style/index.less
  39. 1
      components/steps/demo/nav.md
  40. 11
      components/steps/style/custom-icon.less
  41. 17
      components/steps/style/index.less
  42. 3
      components/steps/style/progress-dot.less
  43. 1
      components/steps/style/small.less
  44. 5
      components/steps/style/vertical.less
  45. 2
      components/style/compact.less
  46. 172
      components/style/themes/compact.less
  47. 123
      components/style/themes/default.less
  48. 5
      components/table/style/size.less
  49. 5
      components/tabs/demo/card-top.md
  50. 12
      components/tabs/style/card-style.less
  51. 8
      components/tabs/style/index.less
  52. 2
      components/tabs/style/rtl.less
  53. 2
      components/timeline/style/index.less
  54. 12
      components/transfer/style/index.less
  55. 14
      components/upload/style/index.less
  56. 30
      docs/react/customize-theme.en-US.md
  57. 26
      docs/react/customize-theme.zh-CN.md
  58. 2
      docs/react/migration-v4.en-US.md
  59. 23
      docs/react/use-with-create-react-app.en-US.md
  60. 25
      docs/react/use-with-create-react-app.zh-CN.md
  61. 4
      package.json
  62. 15
      scripts/compact-vars.js
  63. 8
      scripts/generateColorLess.js
  64. 5
      site/theme/en-US.js
  65. 18
      site/theme/static/common.less
  66. 52
      site/theme/template/Content/MainContent.jsx
  67. 31
      site/theme/template/Content/ThemeIcon.jsx
  68. 4
      site/theme/template/Layout/Header/index.tsx
  69. 3
      site/theme/template/Layout/index.jsx
  70. 5
      site/theme/zh-CN.js
  71. 2
      tests/dekko/dist.test.js
  72. 74
      webpack.config.js

44
.antd-tools.config.js

@ -3,6 +3,7 @@ const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies
const packageInfo = require('./package.json');
const darkVars = require('./scripts/dark-vars');
const compactVars = require('./scripts/compact-vars');
// We need compile additional content for antd user
function finalizeCompile() {
@ -49,6 +50,27 @@ function finalizeCompile() {
}
}
function buildThemeFile(theme, vars) {
// Build less entry file: dist/antd.${theme}.less
fs.writeFileSync(
path.join(process.cwd(), 'dist', `antd.${theme}.less`),
`@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`,
);
// eslint-disable-next-line
console.log(`Built a entry less file to dist/antd.${theme}.less`);
// Build ${theme}.js: dist/${theme}-theme.js, for less-loader
fs.writeFileSync(
path.join(process.cwd(), 'dist', `${theme}-theme.js`),
`module.exports = ${JSON.stringify(vars, null, 2)};`,
);
// eslint-disable-next-line
console.log(`Built a ${theme} theme js file to dist/${theme}-theme.js`);
}
function finalizeDist() {
if (fs.existsSync(path.join(__dirname, './dist'))) {
// Build less entry file: dist/antd.less
@ -56,28 +78,10 @@ function finalizeDist() {
path.join(process.cwd(), 'dist', 'antd.less'),
'@import "../lib/style/index.less";\n@import "../lib/style/components.less";',
);
// eslint-disable-next-line
console.log('Built a entry less file to dist/antd.less');
// Build less entry file: dist/antd.dark.less
fs.writeFileSync(
path.join(process.cwd(), 'dist', 'antd.dark.less'),
'@import "../lib/style/dark.less";\n@import "../lib/style/components.less";',
);
// eslint-disable-next-line
console.log('Built a entry less file to dist/antd.dark.less');
// Build dark.js: dist/dark-theme.js, for less-loader
fs.writeFileSync(
path.join(process.cwd(), 'dist', 'dark-theme.js'),
`module.exports = ${JSON.stringify(darkVars, null, 2)};`,
);
// eslint-disable-next-line
console.log('Built a dark theme js file to dist/dark-theme.js');
buildThemeFile('dark', darkVars);
buildThemeFile('compact', compactVars);
}
}

6
components/alert/style/index.less

@ -12,7 +12,7 @@
border-radius: @border-radius-base;
&&-no-icon {
padding: 8px 15px;
padding: @alert-no-icon-padding-vertical 15px;
}
&&-closable {
@ -71,7 +71,7 @@
&-close-icon {
position: absolute;
top: 8px;
top: @padding-xs;
right: 16px;
padding: 0;
overflow: hidden;
@ -108,7 +108,7 @@
}
&-with-description&-no-icon {
padding: 15px;
padding: @alert-with-description-no-icon-padding-vertical 15px;
}
&-with-description &-icon {

2
components/auto-complete/style/index.less

@ -12,5 +12,5 @@
// https://github.com/ant-design/ant-design/issues/22302
.@{select-prefix-cls}-clear {
right: 13px;
}
}
}

2
components/button/style/index.less

@ -182,7 +182,7 @@
// To ensure that a space will be placed between character and `Icon`.
> .@{iconfont-css-prefix} + span,
> span + .@{iconfont-css-prefix} {
margin-left: 8px;
margin-left: @margin-xs;
}
&-background-ghost {

16
components/button/style/mixin.less

@ -254,6 +254,7 @@
.button-size(
@btn-height-sm; @btn-padding-horizontal-sm; @btn-font-size-sm; @btn-border-radius-sm
);
line-height: @btn-height-sm - 2px;
}
}
// primary button style
@ -370,14 +371,23 @@
// square button: the content only contains icon
.btn-square(@btnClassName: btn) {
.square(@btn-square-size);
.button-size(@btn-square-size; 0; @font-size-base + 2px; @btn-border-radius-base);
.button-size(@btn-square-size; 0; @btn-square-only-icon-size; @btn-border-radius-base);
& > * {
font-size: @btn-square-only-icon-size;
}
&.@{btnClassName}-lg {
.square(@btn-square-size-lg);
.button-size(@btn-square-size-lg; 0; @btn-font-size-lg + 2px; @btn-border-radius-base);
.button-size(@btn-square-size-lg; 0; @btn-square-only-icon-size-lg; @btn-border-radius-base);
& > * {
font-size: @btn-square-only-icon-size-lg;
}
}
&.@{btnClassName}-sm {
.square(@btn-square-size-sm);
.button-size(@btn-square-size-sm; 0; @font-size-base; @btn-border-radius-base);
.button-size(@btn-square-size-sm; 0; @btn-square-only-icon-size-sm; @btn-border-radius-base);
& > * {
font-size: @btn-square-only-icon-size-sm;
}
}
}
// circle button: the content only contains icon

9
components/card/style/index.less

@ -2,7 +2,6 @@
@import '../../style/mixins/index';
@card-prefix-cls: ~'@{ant-prefix}-card';
@card-head-height: 48px;
@card-hoverable-hover-border: transparent;
@card-action-icon-size: 16px;
@ -39,7 +38,7 @@
padding: 0 @card-padding-base;
color: @card-head-color;
font-weight: 500;
font-size: @font-size-lg;
font-size: @card-head-font-size;
background: @card-head-background;
border-bottom: @border-width-base @border-style-base @border-color-split;
border-radius: @card-radius @card-radius 0 0;
@ -61,7 +60,7 @@
.@{ant-prefix}-tabs {
clear: both;
margin-bottom: -17px;
margin-bottom: @card-head-tabs-margin-bottom;
color: @text-color;
font-weight: normal;
font-size: @font-size-base;
@ -154,7 +153,7 @@
& > li {
float: left;
margin: 12px 0;
margin: @card-actions-li-margin;
color: @text-color-secondary;
text-align: center;
@ -236,7 +235,7 @@
&-detail {
overflow: hidden;
> div:not(:last-child) {
margin-bottom: 8px;
margin-bottom: @margin-xs;
}
}

5
components/card/style/size.less

@ -1,7 +1,4 @@
@card-head-height-sm: 36px;
@card-padding-base-sm: @card-padding-base / 2;
@card-head-padding-sm: @card-head-padding / 2;
@card-head-font-size-sm: @font-size-base;
@import './index';
.@{card-prefix-cls}-small {
> .@{card-prefix-cls}-head {

2
components/collapse/demo/basic.md

@ -45,7 +45,7 @@ ReactDOM.render(
```
<style>
p {
[data-theme="compact"] p, p {
margin: 0;
}
</style>

1
components/collapse/demo/custom.md

@ -47,6 +47,7 @@ ReactDOM.render(
```
```css
[data-theme='compact'] .site-collapse-custom-collapse .site-collapse-custom-panel,
.site-collapse-custom-collapse .site-collapse-custom-panel {
background: #f7f7f7;
border-radius: 2px;

10
components/comment/style/index.less

@ -15,7 +15,7 @@
&-avatar {
position: relative;
flex-shrink: 0;
margin-right: 12px;
margin-right: @margin-sm;
cursor: pointer;
img {
@ -36,11 +36,11 @@
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin-bottom: 4px;
margin-bottom: @margin-xss;
font-size: @comment-font-size-base;
& > a,
& > span {
padding-right: 8px;
padding-right: @padding-xs;
font-size: @comment-font-size-sm;
line-height: 18px;
}
@ -65,12 +65,14 @@
}
&-detail p {
margin-bottom: @comment-content-detail-p-margin-bottom;
white-space: pre-wrap;
}
}
&-actions {
margin-top: 12px;
margin-top: @comment-actions-margin-top;
margin-bottom: @comment-actions-margin-bottom;
padding-left: 0;
> li {

4
components/date-picker/style/index.less

@ -9,8 +9,8 @@
.picker-padding(@input-height, @font-size, @padding-horizontal) {
// font height probably 22.0001, So use floor better
@font-height: floor(@font-size * @line-height-base) + 2;
@padding-top: (@input-height - @font-height) / 2;
@padding-bottom: @input-height - @font-height - @padding-top;
@padding-top: max((@input-height - @font-height) / 2, 0);
@padding-bottom: max(@input-height - @font-height - @padding-top, 0);
padding: @padding-top @padding-horizontal @padding-bottom;
}

4
components/date-picker/style/panel.less

@ -660,11 +660,11 @@
.@{picker-prefix-cls}-time-panel-cell-inner {
display: block;
width: 100%;
height: 32px;
height: @picker-time-panel-cell-height;
margin: 0;
padding: 0;
color: @text-color;
line-height: 32px;
line-height: @picker-time-panel-cell-height;
text-align: center;
border-radius: 0;
cursor: pointer;

12
components/descriptions/style/index.less

@ -3,13 +3,9 @@
@descriptions-prefix-cls: ~'@{ant-prefix}-descriptions';
@descriptions-default-padding: 16px 24px;
@descriptions-middle-padding: 12px 24px;
@descriptions-small-padding: 8px 16px;
.@{descriptions-prefix-cls} {
&-title {
margin-bottom: 20px;
margin-bottom: @descriptions-title-margin-bottom;
color: @heading-color;
font-weight: bold;
font-size: @font-size-lg;
@ -29,7 +25,7 @@
&-row {
> th,
> td {
padding-bottom: 16px;
padding-bottom: @padding-md;
}
&:last-child {
border-bottom: none;
@ -81,7 +77,7 @@
.@{descriptions-prefix-cls}-row {
> th,
> td {
padding-bottom: 12px;
padding-bottom: @padding-sm;
}
}
}
@ -90,7 +86,7 @@
.@{descriptions-prefix-cls}-row {
> th,
> td {
padding-bottom: 8px;
padding-bottom: @padding-xs;
}
}
}

6
components/drawer/demo/basic-right.md

@ -55,3 +55,9 @@ class App extends React.Component {
ReactDOM.render(<App />, mountNode);
```
```css
[data-theme='compact'] .ant-drawer-body p {
margin-bottom: 0px;
}
```

6
components/drawer/style/drawer.less

@ -157,14 +157,14 @@
right: 0;
z-index: @zindex-popup-close;
display: block;
width: 56px;
height: 56px;
width: @drawer-header-close-size;
height: @drawer-header-close-size;
padding: 0;
color: @text-color-secondary;
font-weight: 700;
font-size: @font-size-lg;
font-style: normal;
line-height: 56px;
line-height: @drawer-header-close-size;
text-align: center;
text-transform: none;
text-decoration: none;

3
components/form/demo/advanced-search.md

@ -99,6 +99,7 @@ ReactDOM.render(
```
```css
[data-theme='compact'] .ant-advanced-search-form,
.ant-advanced-search-form {
padding: 24px;
background: #fbfbfb;
@ -106,10 +107,12 @@ ReactDOM.render(
border-radius: 2px;
}
[data-theme='compact'] .ant-advanced-search-form .ant-form-item,
.ant-advanced-search-form .ant-form-item {
display: flex;
}
[data-theme='compact'] .ant-advanced-search-form .ant-form-item-control-wrapper,
.ant-advanced-search-form .ant-form-item-control-wrapper {
flex: 1;
}

6
components/input/__tests__/__snapshots__/demo.test.js.snap

@ -42,8 +42,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = `
class="ant-input-group-addon"
>
<div
class="ant-select ant-select-single ant-select-show-arrow"
style="width:90px"
class="ant-select select-before ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-selector"
@ -109,8 +108,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = `
class="ant-input-group-addon"
>
<div
class="ant-select ant-select-single ant-select-show-arrow"
style="width:80px"
class="ant-select select-after ant-select-single ant-select-show-arrow"
>
<div
class="ant-select-selector"

22
components/input/demo/addon.md

@ -20,13 +20,13 @@ import { SettingOutlined } from '@ant-design/icons';
const { Option } = Select;
const selectBefore = (
<Select defaultValue="http://" style={{ width: 90 }}>
<Select defaultValue="http://" className="select-before">
<Option value="http://">http://</Option>
<Option value="https://">https://</Option>
</Select>
);
const selectAfter = (
<Select defaultValue=".com" style={{ width: 80 }}>
<Select defaultValue=".com" className="select-after">
<Option value=".com">.com</Option>
<Option value=".jp">.jp</Option>
<Option value=".cn">.cn</Option>
@ -52,3 +52,21 @@ ReactDOM.render(
mountNode,
);
```
```css
.select-before {
width: 90px;
}
.select-after {
width: 80px;
}
[data-theme='compact'] .select-before {
width: 71px;
}
[data-theme='compact'] .select-after {
width: 65px;
}
```

4
components/input/style/allow-clear.less

@ -34,8 +34,8 @@
// ======================= TextArea ========================
.@{ant-prefix}-input-affix-wrapper-textarea-with-clear-btn {
padding: 0;
border: 0;
padding: 0 !important;
border: 0 !important;
}
.@{ant-prefix}-input-textarea-clear-icon {

6
components/layout/demo/fixed.md

@ -23,11 +23,7 @@ ReactDOM.render(
<Layout>
<Header style={{ position: 'fixed', zIndex: 1, width: '100%' }}>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>

6
components/layout/demo/top-side-2.md

@ -24,11 +24,7 @@ ReactDOM.render(
<Layout>
<Header className="header">
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>

6
components/layout/demo/top-side.md

@ -24,11 +24,7 @@ ReactDOM.render(
<Layout>
<Header className="header">
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>

6
components/layout/demo/top.md

@ -28,11 +28,7 @@ ReactDOM.render(
<Layout className="layout">
<Header>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>

26
components/list/style/bordered.less

@ -1,40 +1,44 @@
@import '../../style/themes/index';
.@{list-prefix-cls}-bordered {
border: 1px solid @border-color-base;
border-radius: @border-radius-base;
.@{list-prefix-cls}-header {
padding-right: 24px;
padding-left: 24px;
padding-right: @padding-lg;
padding-left: @padding-lg;
}
.@{list-prefix-cls}-footer {
padding-right: 24px;
padding-left: 24px;
padding-right: @padding-lg;
padding-left: @padding-lg;
}
.@{list-prefix-cls}-item {
padding-right: 24px;
padding-left: 24px;
padding-right: @padding-lg;
padding-left: @padding-lg;
}
.@{list-prefix-cls}-pagination {
margin: 16px 24px;
margin: @margin-md @margin-lg;
}
&.@{list-prefix-cls}-sm {
.@{list-prefix-cls}-item {
padding-right: 16px;
padding-left: 16px;
padding: @list-item-padding-sm;
}
.@{list-prefix-cls}-header,
.@{list-prefix-cls}-footer {
padding: 8px 16px;
padding: @list-item-padding-sm;
}
}
&.@{list-prefix-cls}-lg {
.@{list-prefix-cls}-item {
padding: @list-item-padding-lg;
}
.@{list-prefix-cls}-header,
.@{list-prefix-cls}-footer {
padding: 16px 24px;
padding: @list-item-padding-lg;
}
}
}

24
components/list/style/index.less

@ -14,7 +14,7 @@
}
&-pagination {
margin-top: 24px;
margin-top: @margin-lg;
text-align: right;
// https://github.com/ant-design/ant-design/issues/20037
@ -24,7 +24,7 @@
}
&-more {
margin-top: 12px;
margin-top: @margin-sm;
text-align: center;
button {
padding-right: 32px;
@ -87,7 +87,7 @@
}
&-description {
color: @text-color-secondary;
font-size: @font-size-base;
font-size: @list-item-meta-description-font-size;
line-height: 22px;
}
}
@ -101,7 +101,7 @@
& > li {
position: relative;
display: inline-block;
padding: 0 8px;
padding: 0 @padding-xs;
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
@ -133,12 +133,12 @@
&-header,
&-footer {
padding-top: 12px;
padding-bottom: 12px;
padding-top: @padding-sm;
padding-bottom: @padding-sm;
}
&-empty {
padding: 16px 0;
padding: @padding-md 0;
color: @text-color-secondary;
font-size: 12px;
text-align: center;
@ -164,13 +164,11 @@
}
&-lg &-item {
padding-top: 16px;
padding-bottom: 16px;
padding: @list-item-padding-lg;
}
&-sm &-item {
padding-top: 8px;
padding-bottom: 8px;
padding: @list-item-padding-sm;
}
&-vertical &-item {
@ -201,7 +199,7 @@
margin-left: auto;
> li {
padding: 0 16px;
padding: 0 @padding-md;
&:first-child {
padding-left: 0;
}
@ -212,7 +210,7 @@
&-grid .@{ant-prefix}-col > &-item {
display: block;
max-width: 100%;
margin-bottom: 16px;
margin-bottom: @margin-md;
padding-top: 0;
padding-bottom: 0;
border-bottom: none;

52
components/menu/__tests__/index.test.js

@ -381,9 +381,7 @@ describe('Menu', () => {
inlineCollapsed
getPopupContainer={node => node.parentNode}
>
<Menu.Item key="menu1">
item
</Menu.Item>
<Menu.Item key="menu1">item</Menu.Item>
<Menu.Item key="menu2" title="title">
item
</Menu.Item>
@ -401,12 +399,48 @@ describe('Menu', () => {
</Menu.Item>
</Menu>,
);
expect(wrapper.find(Menu.Item).at(0).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(1).find(Tooltip).props().title).toBe('title');
expect(wrapper.find(Menu.Item).at(2).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(3).find(Tooltip).props().title).toBe(null);
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
expect(
wrapper
.find(Menu.Item)
.at(0)
.find(Tooltip)
.props().title,
).toBe('item');
expect(
wrapper
.find(Menu.Item)
.at(1)
.find(Tooltip)
.props().title,
).toBe('title');
expect(
wrapper
.find(Menu.Item)
.at(2)
.find(Tooltip)
.props().title,
).toBe('item');
expect(
wrapper
.find(Menu.Item)
.at(3)
.find(Tooltip)
.props().title,
).toBe(null);
expect(
wrapper
.find(Menu.Item)
.at(4)
.find(Tooltip)
.props().title,
).toBe('');
expect(
wrapper
.find(Menu.Item)
.at(4)
.find(Tooltip)
.props().title,
).toBe('');
});
describe('open submenu when click submenu title', () => {

3
components/menu/style/index.less

@ -30,10 +30,11 @@
}
&-item-group-title {
height: @menu-item-group-height;
padding: 8px 16px;
color: @menu-item-group-title-color;
font-size: @font-size-base;
line-height: @line-height-base;
line-height: @menu-item-group-height;
transition: all 0.3s;
}

2
components/modal/style/confirm.less

@ -12,7 +12,7 @@
}
.@{ant-prefix}-modal-body {
padding: 32px 32px 24px;
padding: @modal-confirm-body-padding;
}
&-body-wrapper {

8
components/modal/style/modal.less

@ -60,11 +60,11 @@
&-x {
display: block;
width: 56px;
height: 56px;
width: @modal-header-close-size;
height: @modal-header-close-size;
font-size: @font-size-lg;
font-style: normal;
line-height: 56px;
line-height: @modal-header-close-size;
text-align: center;
text-transform: none;
text-rendering: auto;
@ -78,7 +78,7 @@
}
&-header {
padding: 16px 24px;
padding: @modal-header-padding;
color: @text-color;
background: @modal-header-bg;
border-bottom: @border-width-base @border-style-base @modal-header-border-color-split;

18
components/page-header/style/index.less

@ -24,7 +24,7 @@
&-back {
float: left;
margin: 8px 0;
margin-right: 16px;
margin-right: @margin-md;
font-size: 16px;
line-height: 1;
@ -37,12 +37,12 @@
.@{ant-prefix}-divider-vertical {
height: 14px;
margin: 0 12px;
margin: 0 @margin-sm;
vertical-align: middle;
}
.@{ant-prefix}-breadcrumb + &-heading {
margin-top: 8px;
margin-top: @margin-xs;
}
&-heading {
@ -53,7 +53,7 @@
display: block;
float: left;
margin-bottom: 0;
padding-right: 12px;
padding-right: @padding-sm;
color: @heading-color;
font-weight: 600;
font-size: @heading-4-size;
@ -62,13 +62,13 @@
.@{ant-prefix}-avatar {
float: left;
margin-right: 12px;
margin-right: @margin-sm;
}
&-sub-title {
float: left;
margin: 5px 0;
margin-right: 12px;
margin-right: @margin-sm;
color: @text-color-secondary;
font-size: 14px;
line-height: 22px;
@ -92,11 +92,11 @@
}
&-content {
padding-top: 12px;
padding-top: @page-header-content-padding-vertical;
}
&-footer {
margin-top: 16px;
margin-top: @margin-md;
.@{ant-prefix}-tabs-bar {
margin-bottom: 1px;
border-bottom: 0;
@ -116,7 +116,7 @@
float: unset;
clear: both;
width: 100%;
padding-top: 12px;
padding-top: @padding-sm;
}
}
}

4
components/pagination/style/index.less

@ -321,6 +321,10 @@
&.mini &-options {
margin-left: 2px;
&-size-changer {
top: @pagination-mini-options-size-changer-top;
}
&-quick-jumper {
height: @pagination-item-size-sm;
line-height: @pagination-item-size-sm;

2
components/popover/demo/basic.md

@ -32,7 +32,7 @@ ReactDOM.render(
```
<style>
p {
.ant-popover-content p {
margin: 0;
}
</style>

6
components/popover/style/index.less

@ -68,16 +68,16 @@
&-title {
min-width: @popover-min-width;
min-height: 32px;
min-height: @popover-min-height;
margin: 0; // reset heading margin
padding: 5px @padding-md 4px;
padding: 5px @popover-padding-horizontal 4px;
color: @heading-color;
font-weight: 500;
border-bottom: 1px solid @border-color-split;
}
&-inner-content {
padding: 12px @padding-md;
padding: @padding-sm @popover-padding-horizontal;
color: @popover-color;
}

3
components/select/style/index.less

@ -52,7 +52,6 @@
.@{select-prefix-cls} {
.reset-component;
position: relative;
display: inline-block;
@ -188,7 +187,7 @@
.item() {
position: relative;
display: block;
min-height: 32px;
min-height: @select-dropdown-height;
padding: @select-dropdown-vertical-padding @control-padding-horizontal;
color: @text-color;
font-weight: normal;

10
components/select/style/multiple.less

@ -1,9 +1,7 @@
@import './index';
@select-multiple-item-border-width: 1px;
@select-multiple-item-height: @input-height-base - @input-padding-vertical-base * 2; // Normal 24px
@select-multiple-item-spacing-half: ceil(@input-padding-vertical-base / 2);
@select-multiple-padding: max(
@input-padding-vertical-base - @select-multiple-item-border-width -
@select-multiple-item-spacing-half,
@ -156,7 +154,7 @@
}
}
.select-size('lg', @input-height-lg);
.select-size('lg', @select-multiple-item-height-lg);
.select-size('sm', @input-height-sm);
// Size small need additional set padding
@ -165,4 +163,10 @@
left: @input-padding-horizontal-sm;
}
}
&.@{select-prefix-cls}-lg {
.@{select-prefix-cls}-selection-item {
height: @select-multiple-item-height-lg;
line-height: @select-multiple-item-height-lg;
}
}
}

10
components/select/style/single.less

@ -130,7 +130,7 @@
}
}
.select-size('lg', @input-height-lg);
.select-size('lg', @select-single-item-height-lg);
.select-size('sm', @input-height-sm);
// Size small need additional set padding
@ -156,4 +156,12 @@
}
}
}
&.@{select-prefix-cls}-lg {
&:not(.@{select-prefix-cls}-customize-input) {
.@{select-prefix-cls}-selector {
padding: 0 @input-padding-horizontal-lg;
}
}
}
}

12
components/skeleton/style/index.less

@ -14,7 +14,7 @@
&-header {
display: table-cell;
padding-right: 16px;
padding-right: @padding-md;
vertical-align: top;
// Avatar
@ -32,11 +32,11 @@
.@{skeleton-title-prefix-cls} {
width: 100%;
height: 16px;
margin-top: 16px;
margin-top: @margin-md;
background: @skeleton-color;
+ .@{skeleton-paragraph-prefix-cls} {
margin-top: 24px;
margin-top: @margin-lg;
}
}
@ -55,7 +55,7 @@
}
+ li {
margin-top: 16px;
margin-top: @skeleton-paragraph-li-margin-top;
}
}
}
@ -64,10 +64,10 @@
&-with-avatar &-content {
// Title
.@{skeleton-title-prefix-cls} {
margin-top: 12px;
margin-top: @margin-sm;
+ .@{skeleton-paragraph-prefix-cls} {
margin-top: 28px;
margin-top: @skeleton-paragraph-margin-top;
}
}
}

2
components/statistic/style/index.less

@ -7,7 +7,7 @@
.reset-component;
&-title {
margin-bottom: 4px;
margin-bottom: @margin-xss;
color: @text-color-secondary;
font-size: @statistic-title-font-size;
}

1
components/steps/demo/nav.md

@ -90,6 +90,7 @@ ReactDOM.render(<Demo />, mountNode);
```
```css
[data-theme='compact'] .site-navigation-steps,
.site-navigation-steps {
margin-bottom: 60px;
box-shadow: 0px -1px 0 0 #e8e8e8 inset;

11
components/steps/style/custom-icon.less

@ -4,12 +4,12 @@
background: none;
border: 0;
> .@{steps-prefix-cls}-icon {
top: 0;
top: @steps-icon-custom-top;
left: 0.5px;
width: @steps-icon-size;
height: @steps-icon-size;
font-size: 24px;
line-height: @steps-icon-size;
width: @steps-icon-custom-size;
height: @steps-icon-custom-size;
font-size: @steps-icon-custom-font-size;
line-height: @steps-icon-custom-size;
}
}
&.@{steps-prefix-cls}-item-process {
@ -25,6 +25,7 @@
.@{steps-prefix-cls}-item-custom {
.@{steps-prefix-cls}-item-icon {
width: auto;
background: none;
}
}
}

17
components/steps/style/index.less

@ -20,13 +20,6 @@
@error-tail-color: @wait-tail-color;
@steps-nav-active-color: @primary-color;
@steps-icon-size: 32px;
@steps-small-icon-size: 24px;
@steps-dot-size: 8px;
@steps-current-dot-size: 10px;
@steps-desciption-max-width: 140px;
@steps-nav-content-max-width: auto;
.@{steps-prefix-cls} {
.reset-component;
@ -64,8 +57,8 @@
&-icon {
width: @steps-icon-size;
height: @steps-icon-size;
margin-right: 8px;
font-size: @font-size-lg;
margin: @steps-icon-margin;
font-size: @steps-icon-font-size;
font-family: @font-family;
line-height: @steps-icon-size;
text-align: center;
@ -75,7 +68,7 @@
> .@{steps-prefix-cls}-icon {
position: relative;
top: -1px;
top: @steps-icon-top;
color: @primary-color;
line-height: 1;
}
@ -103,11 +96,11 @@
padding-right: 16px;
color: @text-color;
font-size: @font-size-lg;
line-height: @steps-icon-size;
line-height: @steps-title-line-height;
&::after {
position: absolute;
top: @steps-icon-size / 2;
top: @steps-title-line-height / 2;
left: 100%;
display: block;
width: 9999px;

3
components/steps/style/progress-dot.less

@ -5,7 +5,7 @@
line-height: @line-height-base;
}
&-tail {
top: 2px;
top: @steps-dot-top;
width: 100%;
margin: 0 0 0 @steps-desciption-max-width / 2;
padding: 0;
@ -93,6 +93,7 @@
.@{steps-prefix-cls}-item-icon {
margin-top: 8px;
margin-left: 0;
background: none;
.@{steps-prefix-cls}-rtl& {
margin-right: 0;

1
components/steps/style/small.less

@ -10,6 +10,7 @@
.@{steps-prefix-cls}-item-icon {
width: @steps-small-icon-size;
height: @steps-small-icon-size;
margin: @steps-small-icon-margin;
font-size: @font-size-sm;
line-height: @steps-small-icon-size;
text-align: center;

5
components/steps/style/vertical.less

@ -1,5 +1,6 @@
.steps-vertical() {
display: block;
display: flex;
flex-direction: column;
.@{steps-prefix-cls}-item {
display: block;
overflow: visible;
@ -25,7 +26,7 @@
> .@{steps-prefix-cls}-item-tail {
position: absolute;
top: 0;
left: 16px;
left: @steps-icon-size / 2;
width: 1px;
height: 100%;
padding: @steps-icon-size + 6px 0 6px;

2
components/style/compact.less

@ -0,0 +1,2 @@
@import './themes/compact.less';
@import './core/index';

172
components/style/themes/compact.less

@ -0,0 +1,172 @@
@import './default.less';
@mode: compact;
// default paddings
@default-padding-lg: 24px; // containers
@default-padding-md: 16px; // small containers and buttons
@default-padding-sm: 12px; // Form controls and items
@default-padding-xs: 8px; // small items
@default-padding-xss: 4px; // more small
// vertical paddings
@padding-lg: 16px; // containers
@padding-md: 8px; // small containers and buttons
@padding-sm: 8px; // Form controls and items
@padding-xs: 4px; // small items
@padding-xss: 0px; // more small
// vertical padding for all form controls
@control-padding-horizontal: @padding-sm;
@control-padding-horizontal-sm: @default-padding-xs;
// vertical margins
@margin-lg: 16px; // containers
@margin-md: 8px; // small containers and buttons
@margin-sm: 8px; // Form controls and items
@margin-xs: 4px; // small items
@margin-xss: 0px; // more small
// height rules
@height-base: 28px;
@height-lg: 32px;
@height-sm: 22px;
// Button
// ---
@btn-padding-horizontal-base: @default-padding-sm - 1px;
@btn-padding-horizontal-lg: @btn-padding-horizontal-base;
@btn-padding-horizontal-sm: @default-padding-xs - 1px;
@btn-square-only-icon-size: 14px;
@btn-square-only-icon-size-sm: 14px;
@btn-square-only-icon-size-lg: 16px;
//Dropdown
@dropdown-line-height: 18px;
// Form
// ---
@form-item-margin-bottom: 16px;
// Input
// ---
@input-padding-vertical-base: max(
round((@input-height-base - @font-size-base * @line-height-base) / 2 * 10) / 10 -
@border-width-base,
2px
);
@input-padding-horizontal-lg: 11px;
// PageHeader
// ---
@page-header-padding: 16px;
@page-header-padding-vertical: 8px;
// Pagination
// ---
@pagination-mini-options-size-changer-top: 1px;
// Cascader
// ----
@cascader-dropdown-line-height: @dropdown-line-height;
// Select
// ---
@select-dropdown-height: @height-base;
@select-single-item-height-lg: 32px;
@select-multiple-item-height: @input-height-base - max(@input-padding-vertical-base, 4) * 2; // Normal 24px
@select-multiple-item-height-lg: 24px;
@select-multiple-item-spacing-half: 3px;
// Tree
// ---
@tree-title-height: 20px;
// Transfer
// ---
@transfer-item-padding-vertical: 3px;
@transfer-list-search-icon-top: 8px;
// Comment
// ---
@comment-actions-margin-bottom: 0px;
@comment-actions-margin-top: @margin-xs;
@comment-content-detail-p-margin-bottom: 0px;
// Steps
// ---
@steps-icon-size: 24px;
@steps-icon-custom-size: 20px;
@steps-icon-custom-font-size: 20px;
@steps-icon-custom-top: 2px;
@steps-icon-margin: 2px 8px 2px 0;
@steps-icon-font-size: @font-size-base;
@steps-dot-top: 4px;
@steps-icon-top: 0px;
// Collapse
// ---
@collapse-header-padding-extra: 32px;
// List
// ---
@list-item-meta-description-font-size: @font-size-sm;
@list-item-padding-sm: 4px 12px;
@list-item-padding-lg: 12px 16px;
// Drawer
// ---
@drawer-header-padding: 11px @padding-lg;
@drawer-footer-padding-vertical: @padding-sm;
@drawer-header-close-size: 44px;
// Modal
// --
@modal-header-padding: 11px @padding-lg;
@modal-footer-padding-vertical: @padding-sm;
@modal-header-close-size: 44px;
@modal-confirm-body-padding: 24px 24px 16px;
// popover
// --
@popover-min-height: 28px;
@popover-padding-horizontal: @default-padding-sm;
// Card
// ---
@card-padding-base: 16px;
@card-head-height: 36px;
@card-head-font-size: @card-head-font-size-sm;
@card-head-padding: 8px;
@card-padding-base: 12px;
@card-padding-base-sm: @card-padding-base;
@card-head-height-sm: 30px;
@card-head-padding-sm: 4px;
@card-actions-li-margin: 4px 0;
@card-head-tabs-margin-bottom: -9px;
// Table
// ---
@table-padding-vertical: 12px;
@table-padding-horizontal: 8px;
@table-padding-vertical-md: 8px;
@table-padding-horizontal-md: 8px;
@table-padding-vertical-sm: 4px;
@table-padding-horizontal-sm: 4px;
// Statistic
// ---
@statistic-content-font-size: 20px;
// Alert
// ---
@alert-with-description-no-icon-padding-vertical: 11px;
// Skeleton
// ---
@skeleton-paragraph-margin-top: 20px;
@skeleton-paragraph-li-margin-top: 12px;
// Descriptions
@descriptions-title-margin-bottom: 8px;
@descriptions-default-padding: 12px @padding-lg;

123
components/style/themes/default.less

@ -79,11 +79,24 @@
@padding-md: 16px; // small containers and buttons
@padding-sm: 12px; // Form controls and items
@padding-xs: 8px; // small items
@padding-xss: 4px; // more small
// vertical padding for all form controls
@control-padding-horizontal: @padding-sm;
@control-padding-horizontal-sm: @padding-xs;
// vertical margins
@margin-lg: 24px; // containers
@margin-md: 16px; // small containers and buttons
@margin-sm: 12px; // Form controls and items
@margin-xs: 8px; // small items
@margin-xss: 4px; // more small
// height rules
@height-base: 32px;
@height-lg: 40px;
@height-sm: 24px;
// The background colors for active and hover states for things like
// list items or table cells.
@item-active-bg: @primary-1;
@ -188,9 +201,9 @@
@btn-padding-horizontal-lg: @btn-padding-horizontal-base;
@btn-padding-horizontal-sm: @padding-xs - 1px;
@btn-height-base: 32px;
@btn-height-lg: 40px;
@btn-height-sm: 24px;
@btn-height-base: @height-base;
@btn-height-lg: @height-lg;
@btn-height-sm: @height-sm;
@btn-circle-size: @btn-height-base;
@btn-circle-size-lg: @btn-height-lg;
@ -199,6 +212,9 @@
@btn-square-size: @btn-height-base;
@btn-square-size-lg: @btn-height-lg;
@btn-square-size-sm: @btn-height-sm;
@btn-square-only-icon-size: @font-size-base + 2px;
@btn-square-only-icon-size-sm: @font-size-base;
@btn-square-only-icon-size-lg: @btn-font-size-lg + 2px;
@btn-group-border: @primary-5;
@ -213,6 +229,10 @@
// Descriptions
@descriptions-bg: #fafafa;
@descriptions-title-margin-bottom: 20px;
@descriptions-default-padding: @padding-md @padding-lg;
@descriptions-middle-padding: @padding-sm @padding-lg;
@descriptions-small-padding: @padding-xs @padding-md;
// Dropdown
@dropdown-selected-color: @primary-color;
@ -340,9 +360,9 @@
// Input
// ---
@input-height-base: 32px;
@input-height-lg: 40px;
@input-height-sm: 24px;
@input-height-base: @height-base;
@input-height-lg: @height-lg;
@input-height-sm: @height-sm;
@input-padding-horizontal: @control-padding-horizontal - 1px;
@input-padding-horizontal-base: @input-padding-horizontal;
@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px;
@ -352,8 +372,10 @@
@border-width-base,
3px
);
@input-padding-vertical-sm: round((@input-height-sm - @font-size-base * @line-height-base) / 2 * 10) /
10 - @border-width-base;
@input-padding-vertical-sm: max(
round((@input-height-sm - @font-size-base * @line-height-base) / 2 * 10) / 10 - @border-width-base,
0
);
@input-padding-vertical-lg: ceil((@input-height-lg - @font-size-lg * @line-height-base) / 2 * 10) /
10 - @border-width-base;
@input-placeholder-color: hsv(0, 0, 75%);
@ -387,10 +409,15 @@
@select-dropdown-vertical-padding: @dropdown-vertical-padding;
@select-dropdown-font-size: @dropdown-font-size;
@select-dropdown-line-height: @dropdown-line-height;
@select-dropdown-height: 32px;
@select-background: @component-background;
@select-clear-background: @select-background;
@select-selection-item-bg: @background-color-base;
@select-selection-item-border-color: @border-color-split;
@select-single-item-height-lg: 40px;
@select-multiple-item-height: @input-height-base - @input-padding-vertical-base * 2; // Normal 24px
@select-multiple-item-height-lg: 32px;
@select-multiple-item-spacing-half: ceil(@input-padding-vertical-base / 2);
// Cascader
// ---
@ -434,6 +461,7 @@
@popover-color: @text-color;
// Popover maximum width
@popover-min-width: 177px;
@popover-min-height: 32px;
// Popover arrow width
@popover-arrow-width: 6px;
// Popover arrow color
@ -443,12 +471,15 @@
@popover-arrow-outer-color: @popover-bg;
// Popover distance with trigger
@popover-distance: @popover-arrow-width + 4px;
@popover-padding-horizontal: @padding-md;
// Modal
// --
@modal-body-padding: 24px;
@modal-body-padding: @padding-lg;
@modal-header-bg: @component-background;
@modal-header-padding: @padding-md @padding-lg;
@modal-header-border-color-split: @border-color-split;
@modal-header-close-size: 56px;
@modal-content-bg: @component-background;
@modal-heading-color: @heading-color;
@modal-footer-bg: transparent;
@ -456,6 +487,7 @@
@modal-footer-padding-vertical: 10px;
@modal-footer-padding-horizontal: 16px;
@modal-mask-bg: fade(@black, 45%);
@modal-confirm-body-padding: 32px 32px 24px;
// Progress
// --
@ -469,6 +501,7 @@
// ---
@menu-inline-toplevel-item-height: 40px;
@menu-item-height: 40px;
@menu-item-group-height: @line-height-base;
@menu-collapsed-width: 80px;
@menu-bg: @component-background;
@menu-popup-bg: @component-background;
@ -515,6 +548,10 @@
@table-expanded-row-bg: #fbfbfb;
@table-padding-vertical: 16px;
@table-padding-horizontal: 16px;
@table-padding-vertical-md: @table-padding-vertical * 3 / 4;
@table-padding-horizontal-md: @table-padding-horizontal / 2;
@table-padding-vertical-sm: @table-padding-vertical / 2;
@table-padding-horizontal-sm: @table-padding-horizontal / 2;
@table-border-radius-base: @border-radius-base;
@table-footer-bg: @background-color-light;
@table-footer-color: @heading-color;
@ -544,6 +581,7 @@
@picker-border-color: @border-color-split;
@picker-date-hover-range-border-color: lighten(@primary-color, 20%);
@picker-date-hover-range-color: @picker-basic-cell-hover-with-range-color;
@picker-time-panel-cell-height: 28px;
// Calendar
// ---
@ -578,20 +616,28 @@
// ---
@card-head-color: @heading-color;
@card-head-background: transparent;
@card-head-font-size: @font-size-lg;
@card-head-font-size-sm: @font-size-base;
@card-head-padding: 16px;
@card-head-padding-sm: @card-head-padding / 2;
@card-head-height: 48px;
@card-head-height-sm: 36px;
@card-inner-head-padding: 12px;
@card-padding-base: 24px;
@card-padding-base-sm: @card-padding-base / 2;
@card-actions-background: @background-color-light;
@card-actions-li-margin: 12px 0;
@card-skeleton-bg: #cfd8dc;
@card-background: @component-background;
@card-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12),
0 5px 12px 4px rgba(0, 0, 0, 0.09);
@card-radius: @border-radius-base;
@card-head-tabs-margin-bottom: -17px;
// Comment
// ---
@comment-bg: inherit;
@comment-padding-base: 16px 0;
@comment-padding-base: @padding-md 0;
@comment-nest-indent: 44px;
@comment-font-size-base: @font-size-base;
@comment-font-size-sm: @font-size-sm;
@ -599,6 +645,9 @@
@comment-author-time-color: #ccc;
@comment-action-color: @text-color-secondary;
@comment-action-hover-color: #595959;
@comment-actions-margin-bottom: inherit;
@comment-actions-margin-top: @margin-sm;
@comment-content-detail-p-margin-bottom: inherit;
// Tabs
// ---
@ -609,14 +658,14 @@
@tabs-title-font-size-lg: @font-size-lg;
@tabs-title-font-size-sm: @font-size-base;
@tabs-ink-bar-color: @primary-color;
@tabs-bar-margin: 0 0 16px 0;
@tabs-bar-margin: 0 0 @margin-md 0;
@tabs-horizontal-margin: 0 32px 0 0;
@tabs-horizontal-margin-rtl: 0 0 0 32px;
@tabs-horizontal-padding: 12px 0;
@tabs-horizontal-padding-lg: 16px 0;
@tabs-horizontal-padding-sm: 8px 0;
@tabs-vertical-padding: 8px 24px;
@tabs-vertical-margin: 0 0 16px 0;
@tabs-horizontal-padding: @padding-sm 0;
@tabs-horizontal-padding-lg: @padding-md 0;
@tabs-horizontal-padding-sm: @padding-xs 0;
@tabs-vertical-padding: @padding-xs @padding-lg;
@tabs-vertical-margin: 0 0 @margin-md 0;
@tabs-scrolling-size: 32px;
@tabs-highlight-color: @primary-color;
@tabs-hover-color: @primary-5;
@ -657,7 +706,7 @@
// Pagination
// ---
@pagination-item-bg: @component-background;
@pagination-item-size: 32px;
@pagination-item-size: @height-base;
@pagination-item-size-sm: 24px;
@pagination-font-family: Arial;
@pagination-font-weight-active: 500;
@ -666,12 +715,14 @@
@pagination-item-disabled-color-active: @white;
@pagination-item-disabled-bg-active: darken(@disabled-bg, 10%);
@pagination-item-input-bg: @component-background;
@pagination-mini-options-size-changer-top: 0px;
// PageHeader
// ---
@page-header-padding: 24px;
@page-header-padding-vertical: 16px;
@page-header-padding-breadcrumb: 12px;
@page-header-padding: @padding-lg;
@page-header-padding-vertical: @padding-md;
@page-header-padding-breadcrumb: @padding-sm;
@page-header-content-padding-vertical: @padding-sm;
@page-header-back-color: #000;
@page-header-ghost-bg: inherit;
@ -718,7 +769,7 @@
// Collapse
// ---
@collapse-header-padding: 12px 16px;
@collapse-header-padding: @padding-sm @padding-md;
@collapse-header-padding-extra: 40px;
@collapse-header-bg: @background-color-light;
@collapse-content-padding: @padding-md;
@ -728,13 +779,18 @@
// ---
@skeleton-color: #f2f2f2;
@skeleton-to-color: shade(@skeleton-color, 5%);
@skeleton-paragraph-margin-top: 28px;
@skeleton-paragraph-li-margin-top: @margin-md;
// Transfer
// ---
@transfer-header-height: 40px;
@transfer-item-height: @height-base;
@transfer-disabled-bg: @disabled-bg;
@transfer-list-height: 200px;
@transfer-item-hover-bg: @item-hover-bg;
@transfer-item-padding-vertical: 6px;
@transfer-list-search-icon-top: 12px;
// Message
// ---
@ -762,6 +818,8 @@
@alert-text-color: @text-color;
@alert-close-color: @text-color-secondary;
@alert-close-hover-color: @icon-color-hover;
@alert-no-icon-padding-vertical: @padding-xs;
@alert-with-description-no-icon-padding-vertical: @padding-md - 1px;
// List
// ---
@ -769,10 +827,13 @@
@list-footer-background: transparent;
@list-empty-text-padding: @padding-md;
@list-item-padding: @padding-sm 0;
@list-item-padding-sm: @padding-xs @padding-md;
@list-item-padding-lg: 16px 24px;
@list-item-meta-margin-bottom: @padding-md;
@list-item-meta-avatar-margin-right: @padding-md;
@list-item-meta-title-margin-bottom: @padding-sm;
@list-customize-card-bg: @component-background;
@list-item-meta-description-font-size: @font-size-base;
// Statistic
// ---
@ -783,11 +844,12 @@
// Drawer
// ---
@drawer-header-padding: 16px 24px;
@drawer-body-padding: 24px;
@drawer-header-padding: @padding-md @padding-lg;
@drawer-body-padding: @padding-lg;
@drawer-bg: @component-background;
@drawer-footer-padding-vertical: @modal-footer-padding-vertical;
@drawer-footer-padding-horizontal: @modal-footer-padding-horizontal;
@drawer-header-close-size: 56px;
// Timeline
// ---
@ -813,6 +875,21 @@
@process-tail-color: @border-color-split;
@steps-nav-arrow-color: fade(@black, 25%);
@steps-background: @component-background;
@steps-icon-size: 32px;
@steps-icon-custom-size: @steps-icon-size;
@steps-icon-custom-top: 0px;
@steps-icon-custom-font-size: 24px;
@steps-icon-top: -1px;
@steps-icon-font-size: @font-size-lg;
@steps-icon-margin: 0 8px 0 0;
@steps-title-line-height: @height-base;
@steps-small-icon-size: 24px;
@steps-small-icon-margin: 0 8px 0 0;
@steps-dot-size: 8px;
@steps-dot-top: 2px;
@steps-current-dot-size: 10px;
@steps-desciption-max-width: 140px;
@steps-nav-content-max-width: auto;
// Notification
// ---

5
components/table/style/size.less

@ -1,10 +1,5 @@
@import './index';
@table-padding-vertical-md: @table-padding-vertical * 3 / 4;
@table-padding-horizontal-md: @table-padding-horizontal / 2;
@table-padding-vertical-sm: @table-padding-vertical / 2;
@table-padding-horizontal-sm: @table-padding-horizontal / 2;
.table-size(@size, @padding-vertical, @padding-horizontal) {
.@{table-prefix-cls}.@{table-prefix-cls}-@{size} {
.@{table-prefix-cls}-title,

5
components/tabs/demo/card-top.md

@ -43,25 +43,30 @@ ReactDOM.render(
```
```css
[data-theme='compact'] .card-container > .ant-tabs-card > .ant-tabs-content,
.card-container > .ant-tabs-card > .ant-tabs-content {
height: 120px;
margin-top: -16px;
}
[data-theme='compact'] .card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane,
.card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
background: #fff;
padding: 16px;
}
[data-theme='compact'] .card-container > .ant-tabs-card > .ant-tabs-bar,
.card-container > .ant-tabs-card > .ant-tabs-bar {
border-color: #fff;
}
[data-theme='compact'] .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab,
.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
border-color: transparent;
background: transparent;
}
[data-theme='compact'] .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active,
.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
border-color: #fff;
background: #fff;

12
components/tabs/style/card-style.less

@ -15,7 +15,7 @@
height: @tabs-card-height;
margin: 0;
margin-right: @tabs-card-gutter;
padding: 0 16px;
padding: 0 @padding-md;
line-height: @tabs-card-height - 2px;
background: @tabs-card-head-background;
border: @border-width-base @border-style-base @border-color-split;
@ -34,7 +34,6 @@
}
}
&&-card &-card-bar &-tab-disabled {
color: @tabs-card-active-color;
color: @disabled-color;
}
&&-card &-card-bar &-tab-inactive {
@ -45,7 +44,6 @@
}
&&-card &-card-bar &-tab &-close-x {
width: 16px;
height: 16px;
height: @font-size-base;
margin-right: -5px;
margin-left: 3px;
@ -126,13 +124,13 @@
height: 100%;
}
.@{tab-prefix-cls}-tab {
margin-bottom: 8px;
margin-bottom: @margin-sm;
border-bottom: @border-width-base @border-style-base @border-color-split;
&-active {
padding-bottom: 4px;
}
&:last-child {
margin-bottom: 8px;
margin-bottom: @margin-sm;
}
}
.@{tab-prefix-cls}-new-tab {
@ -150,7 +148,7 @@
border-radius: @border-radius-base 0 0 @border-radius-base;
&-active {
margin-right: -1px;
padding-right: 18px;
padding-right: @padding-md + 2px;
}
}
}
@ -165,7 +163,7 @@
border-radius: 0 @border-radius-base @border-radius-base 0;
&-active {
margin-left: -1px;
padding-left: 18px;
padding-left: @padding-md + 2px;
}
}
}

8
components/tabs/style/index.less

@ -61,7 +61,7 @@
// https://github.com/ant-design/ant-design/issues/9104
&-bottom &-bottom-bar {
margin-top: 16px;
margin-top: @margin-md;
margin-bottom: 0;
border-top: @border-width-base @border-style-base @border-color-split;
border-bottom: none;
@ -208,7 +208,7 @@
}
.@{iconfont-css-prefix} {
margin-right: 8px;
margin-right: @margin-sm;
}
&-active {
@ -378,7 +378,7 @@
}
}
.@{tab-prefix-cls}-left-content {
padding-left: 24px;
padding-left: @padding-lg;
border-left: @border-width-base @border-style-base @border-color-split;
}
@ -399,7 +399,7 @@
}
}
.@{tab-prefix-cls}-right-content {
padding-right: 24px;
padding-right: @padding-lg;
border-right: @border-width-base @border-style-base @border-color-split;
}
}

2
components/tabs/style/rtl.less

@ -39,7 +39,7 @@
.@{iconfont-css-prefix} {
.@{tab-prefix-cls}-rtl & {
margin-right: 0;
margin-left: 8px;
margin-left: @margin-xs;
}
}
}

2
components/timeline/style/index.less

@ -81,7 +81,7 @@
&-content {
position: relative;
top: -(@font-size-base * @line-height-base - @font-size-base) + 1px;
margin: 0 0 0 18px;
margin: 0 0 0 @margin-lg + 2px;
word-break: break-word;
}

12
components/transfer/style/index.less

@ -35,11 +35,11 @@
}
&-search {
padding-right: 24px;
padding-right: 24px !important;
padding-left: @control-padding-horizontal-sm;
&-action {
position: absolute;
top: 12px;
top: @transfer-list-search-icon-top;
right: 12px;
bottom: 12px;
width: 28px;
@ -94,12 +94,12 @@
top: 0;
left: 0;
width: 100%;
padding: 12px;
padding: @padding-sm;
}
}
&-body-with-search {
padding-top: @input-height-base + 24px;
padding-top: @input-height-base + @padding-sm * 2;
}
&-content {
@ -109,8 +109,8 @@
overflow: auto;
list-style: none;
&-item {
min-height: 32px;
padding: 6px @control-padding-horizontal;
min-height: @transfer-item-height;
padding: @transfer-item-padding-vertical @control-padding-horizontal;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;

14
components/upload/style/index.less

@ -52,7 +52,7 @@
display: table-cell;
width: 100%;
height: 100%;
padding: 8px;
padding: @padding-xs;
text-align: center;
vertical-align: middle;
}
@ -74,7 +74,7 @@
transition: border-color 0.3s;
.@{upload-prefix-cls} {
padding: 16px 0;
padding: @padding-md 0;
}
&.@{upload-prefix-cls}-drag-hover:not(.@{upload-prefix-cls}-disabled) {
@ -140,6 +140,7 @@
.@{upload-prefix-cls}-list {
.reset-component;
.clearfix;
line-height: 22px;
&-item-list-type-text {
&:hover {
.@{upload-prefix-cls}-list-item-name-icon-count-1 {
@ -153,13 +154,14 @@
&-item {
position: relative;
height: 22px;
margin-top: 8px;
margin-top: @margin-xs;
font-size: @font-size-base;
&-name {
display: inline-block;
width: 100%;
padding-left: @font-size-base + 8px;
overflow: hidden;
line-height: 22px;
white-space: nowrap;
text-overflow: ellipsis;
}
@ -263,7 +265,7 @@
.@{upload-item} {
position: relative;
height: 66px;
padding: 8px;
padding: @padding-xs;
border: @border-width-base @upload-picture-card-border-style @border-color-base;
border-radius: @border-radius-base;
&:hover {
@ -374,13 +376,13 @@
float: left;
width: @upload-picture-card-size;
height: @upload-picture-card-size;
margin: 0 8px 8px 0;
margin: 0 @margin-xs @margin-xs 0;
}
.@{upload-item} {
float: left;
width: @upload-picture-card-size;
height: @upload-picture-card-size;
margin: 0 8px 8px 0;
margin: 0 @margin-xs @margin-xs 0;
}
.@{upload-item}-info {

30
docs/react/customize-theme.en-US.md

@ -133,10 +133,11 @@ You must import styles as less format. A common mistake would be importing multi
We have some official themes, try them out and give us some feedback!
- 🌑 Dark Theme (follow document below)
- ☁️ [Aliyun Console Theme (Beta)](https://github.com/ant-design/ant-design-aliyun-theme)
- 🌑 Dark Theme (supported in 4.0.0+)
- 🌑 Compact Theme (supported in 4.1.0+)
- ☁️ [Aliyun Console Theme (Beta)](https://github.com/ant-design/ant-design-aliyun-theme)
### Use dark theme
### Use dark or compact theme
![](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*mYU9R4YFxscAAAAAAAAAAABkARQnAQ)
@ -150,33 +151,39 @@ If you're using [Umi 3](http://umijs.org/zh/), which only need two steps:
$ npm i @umijs/plugin-antd -D
```
2. set `dark: true`.
2. set `dark` or `compact` to `true`.
```js
// .umirc.ts or config/config.ts
export default {
antd: {
dark: true,
dark: true, // active dark theme
compact: true, // active compact theme
},
},
```
Method 2: Import [antd/dist/antd.dark.less](https://unpkg.com/browse/antd@4.x/dist/antd.dark.less) in the style file:
Method 2: Import [antd/dist/antd.dark.less](https://unpkg.com/browse/antd@4.x/dist/antd.dark.less) or [antd/dist/antd.compact.less](https://unpkg.com/browse/antd@4.x/dist/antd.compact.less) in the style file:
```less
@import '~antd/dist/antd.dark.less'; // Introduce the official dark less style entry file
@import '~antd/dist/antd.compact.less';
```
If the project does not use Less, you can import [antd.dark.css](https://unpkg.com/browse/antd@4.x/dist/antd.dark.css) in the CSS file:
If the project does not use Less, you can import [antd.dark.css](https://unpkg.com/browse/antd@4.x/dist/antd.dark.css) or [antd/dist/antd.compact.css](https://unpkg.com/browse/antd@4.x/dist/antd.compact.css) in the CSS file:
```css
@import '~antd/dist/antd.dark.css';
@import '~antd/dist/antd.compact.css';
```
> Note that you don't need to import `antd/dist/antd.less` or `antd/dist/antd.css` anymore, please remove it, and remove babel-plugin-import `style` config too.
Method 3: using [less-loader](https://github.com/webpack-contrib/less-loader) in `webpack.config.js` to introduce as needed:
```diff
const darkThemeVars = require('antd/dist/dark-theme');
const darkTheme = require('antd/dist/dark-theme');
const compactTheme = require('antd/dist/compact-theme');
// webpack.config.js
module.exports = {
@ -191,15 +198,18 @@ module.exports = {
+ options: {
+ modifyVars: {
+ 'hack': `true;@import "${require.resolve('antd/lib/style/color/colorPalette.less')}";`,
+ ...darkThemeVars,
+ ...darkTheme,
+ ...compactTheme,
+ },
+ javascriptEnabled: true,
+ },
}],
}],
}
};
```
Use dark theme and compact theme at the same time will cause double css bundle size in current implementation, please be aware of this.
## Related Articles
- [Using Ant Design in Sass-Styled Webpack Projects with `antd-scss-theme-plugin`](https://intoli.com/blog/antd-scss-theme-plugin/)

26
docs/react/customize-theme.zh-CN.md

@ -111,10 +111,11 @@ module.exports = {
我们提供了一些官方主题,欢迎在项目中试用,并且给我们提供反馈。
- 🌑 暗色主题(用法见下方文档)
- 🌑 暗黑主题(4.0.0+ 支持)
- 📦 紧凑主题(4.1.0+ 支持)
- ☁️ [阿里云控制台主题(Beta)](https://github.com/ant-design/ant-design-aliyun-theme)
### 使用暗主题
### 使用暗黑主题和紧凑主题
![](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*mYU9R4YFxscAAAAAAAAAAABkARQnAQ)
@ -128,33 +129,39 @@ module.exports = {
$ npm i @umijs/plugin-antd -D
```
2. 配置 `dark: true`
2. 配置 `dark``compact`
```js
// .umirc.ts or config/config.ts
export default {
antd: {
dark: true,
dark: true, // 开启暗色主题
compact: true, // 开启紧凑主题
},
},
```
方式二:是在样式文件全量引入 [antd.dark.less](https://unpkg.com/browse/antd@4.x/dist/antd.dark.less)。
方式二:是在样式文件全量引入 [antd.dark.less](https://unpkg.com/browse/antd@4.x/dist/antd.dark.less) 或 [antd.compact.less](https://unpkg.com/browse/antd@4.x/dist/antd.compact.less)
```less
@import '~antd/dist/antd.dark.less'; // 引入官方提供的暗色 less 样式入口文件
@import '~antd/dist/antd.compact.less'; // 引入官方提供的暗色 less 样式入口文件
```
如果项目不使用 Less,可在 CSS 文件中全量引入 [antd.dark.css](https://unpkg.com/browse/antd@4.x/dist/antd.dark.css)。
如果项目不使用 Less,可在 CSS 文件中全量引入 [antd.dark.css](https://unpkg.com/browse/antd@4.x/dist/antd.dark.css) 或 [antd.compact.css](https://unpkg.com/browse/antd@4.x/dist/antd.compact.css)。
```css
@import '~antd/dist/antd.dark.css';
@import '~antd/dist/antd.compact.css';
```
> 注意这种方式下你不需要再引入 `antd/dist/antd.less``antd/dist/antd.css` 了,可以安全移除掉。也不需要开启 babel-plugin-import 的 `style` 配置。
方式三:是用在 `webpack.config.js` 使用 [less-loader](https://github.com/webpack-contrib/less-loader) 按需引入:
```diff
const darkThemeVars = require('antd/dist/dark-theme');
const darkTheme = require('antd/dist/dark-theme');
const compactTheme = require('antd/dist/compact-theme');
// webpack.config.js
module.exports = {
@ -169,7 +176,8 @@ module.exports = {
+ options: {
+ modifyVars: {
+ 'hack': `true;@import "${require.resolve('antd/lib/style/color/colorPalette.less')}";`,
+ ...darkThemeVars,
+ ...darkTheme,
+ ...compactTheme,
+ },
+ javascriptEnabled: true,
+ },
@ -178,6 +186,8 @@ module.exports = {
};
```
同时开启暗黑和紧凑模式会导致 css 的加载体积增加一倍,这暂时受限于我们目前的主题实现方式,请知晓。
## 社区教程
- [Using Ant Design in Sass-Styled Webpack Projects with `antd-scss-theme-plugin`](https://intoli.com/blog/antd-scss-theme-plugin/)

2
docs/react/migration-v4.en-US.md

@ -3,7 +3,7 @@ order: 8
title: V3 to V4
---
This document will help you upgrade from antd `3.x` version to antd `4.x` version. If you are using `2.x` or older version, please refer to the previous [upgrade document] (https://github.com/ant-design/ant-design/blob/2adf8ced24da7b3cb46a3475854a83d76a98c536/CHANGELOG.en-US.md#300) to 3.x.
This document will help you upgrade from antd `3.x` version to antd `4.x` version. If you are using `2.x` or older version, please refer to the previous [upgrade document](https://github.com/ant-design/ant-design/blob/2adf8ced24da7b3cb46a3475854a83d76a98c536/CHANGELOG.en-US.md#300) to 3.x.
## Upgrade preparation

23
docs/react/use-with-create-react-app.en-US.md

@ -199,28 +199,7 @@ module.exports = override(
We use `modifyVars` option of [less-loader](https://github.com/webpack/less-loader#less-options) here. If you see a green button rendered on the page after rebooting the server, then the configuration was successful.
### Use custom dark theme
```diff
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
+ const darkThemeVars = require('antd/dist/dark-theme');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
modifyVars: {
+ 'hack': `true;@import "${require.resolve('antd/lib/style/color/colorPalette.less')}";`,
+ ...darkThemeVars,
'@primary-color': '#1DA57A'
},
}),
);
```
We have built-in dark theme and compact theme in antd, you can reference to [Use dark or compact theme](/docs/react/customize-theme#Use-dark-or-compact-theme).
> You could also try [craco](https://github.com/sharegate/craco) and [craco-antd](https://github.com/FormAPI/craco-antd) to customize create-react-app webpack config same as customize-cra does.

25
docs/react/use-with-create-react-app.zh-CN.md

@ -199,30 +199,7 @@ module.exports = override(
这里利用了 [less-loader](https://github.com/webpack/less-loader#less-options) 的 `modifyVars` 来进行主题配置,变量和其他配置方式可以参考 [配置主题](/docs/react/customize-theme) 文档。修改后重启 `yarn start`,如果看到一个绿色的按钮就说明配置成功了。
### 使用自定义深色主题
```diff
const { override, fixBabelImports, addLessLoader } = require('customize-cra');
+ const darkThemeVars = require('antd/dist/dark-theme');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
modifyVars: {
+ 'hack': `true;@import "${require.resolve('antd/lib/style/color/colorPalette.less')}";`,
+ ...darkThemeVars,
'@primary-color': '#1DA57A'
},
}),
);
```
> 你也可以使用 [craco](https://github.com/sharegate/craco) 和 [craco-antd](https://github.com/FormAPI/craco-antd) 来实现和 customize-cra 一样的修改 create-react-app 配置的功能。
antd 内建了深色主题和紧凑主题,你可以参照 [使用暗色主题和紧凑主题](/docs/react/customize-theme#使用暗色主题和紧凑主题) 进行接入。
## 使用 Day.js 替换 momentjs 优化打包大小

4
package.json

@ -271,6 +271,10 @@
{
"path": "./dist/antd.dark.min.css",
"maxSize": "65 kB"
},
{
"path": "./dist/antd.compact.min.css",
"maxSize": "65 kB"
}
],
"title": "Ant Design"

15
scripts/compact-vars.js

@ -0,0 +1,15 @@
const fs = require('fs');
const path = require('path');
const lessToJs = require('less-vars-to-js');
const stylePath = path.join(__dirname, '..', 'components', 'style');
const colorLess = fs.readFileSync(path.join(stylePath, 'color', 'colors.less'), 'utf8');
const defaultLess = fs.readFileSync(path.join(stylePath, 'themes', 'default.less'), 'utf8');
const compactLess = fs.readFileSync(path.join(stylePath, 'themes', 'compact.less'), 'utf8');
const compactPaletteLess = lessToJs(`${colorLess}${defaultLess}${compactLess}`, {
stripPrefix: true,
resolveVariables: false,
});
module.exports = compactPaletteLess;

8
scripts/generateColorLess.js

@ -3,6 +3,7 @@ const path = require('path');
const { generateTheme } = require('antd-theme-generator');
const genCss = require('antd-pro-merge-less');
const dark = require('./dark-vars');
const compact = require('./compact-vars');
genCss(
path.join(__dirname, '..'),
@ -16,6 +17,13 @@ genCss(
'@site-markdown-code-bg': '@input-bg',
},
},
{
theme: 'compact',
fileName: './_site/compact.css',
modifyVars: {
...compact,
},
},
],
{
ignoreAntd: true,

5
site/theme/en-US.js

@ -1,8 +1,9 @@
module.exports = {
locale: 'en-US',
messages: {
'app.theme.switch.dark': 'Switch default mode',
'app.theme.switch.default': 'Switch dark mode',
'app.theme.switch.default': 'Default theme',
'app.theme.switch.dark': 'Dark theme',
'app.theme.switch.compact': 'Compact theme',
'app.header.search': 'Search...',
'app.header.menu.documentation': 'Docs',
'app.header.menu.components': 'Components',

18
site/theme/static/common.less

@ -206,6 +206,8 @@ a {
right: 32px;
bottom: 102px;
z-index: 2147483640;
display: flex;
flex-direction: column;
cursor: pointer;
&-tooltip {
.ant-tooltip-inner {
@ -215,9 +217,17 @@ a {
& > div {
display: block;
}
&-active {
color: @primary-color;
}
& &-avatar {
color: #000;
background-color: #fff;
box-shadow: @shadow-2;
transition: color .3s;
&:hover {
color: @primary-color;
}
}
}
@ -235,7 +245,13 @@ a {
#header #nav.ant-menu,
.main-wrapper,
.main-wrapper > .ant-row > .main-menu .main-menu-inner > .ant-menu,
.main-wrapper > .ant-row > .main-menu .main-menu-inner > .ant-menu.aside-container.ant-menu-inline > .ant-menu-item-group > .ant-menu-item-group-title::after,
.main-wrapper
> .ant-row
> .main-menu
.main-menu-inner
> .ant-menu.aside-container.ant-menu-inline
> .ant-menu-item-group
> .ant-menu-item-group-title::after,
.main-wrapper .main-container,
#demo-toc.toc {
transition: all 0.3s @ease-in-out-circ;

52
site/theme/template/Content/MainContent.jsx

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'bisheng/router';
import { Row, Col, Menu, Affix, Tooltip, Avatar } from 'antd';
import { Row, Col, Menu, Affix, Tooltip, Avatar, Dropdown } from 'antd';
import { injectIntl } from 'react-intl';
import { LeftOutlined, RightOutlined, ExportOutlined } from '@ant-design/icons';
import ContributorsList from '@qixian.cs/github-contributors-list';
@ -9,7 +9,7 @@ import classNames from 'classnames';
import get from 'lodash/get';
import MobileMenu from 'rc-drawer';
import { DarkIcon, DefaultIcon } from './ThemeIcon';
import ThemeIcon from './ThemeIcon';
import Article from './Article';
import PrevAndNext from './PrevAndNext';
import Footer from '../Layout/Footer';
@ -60,7 +60,7 @@ const getSideBarOpenKeys = nextProps => {
class MainContent extends Component {
static contextTypes = {
theme: PropTypes.oneOf(['default', 'dark']),
theme: PropTypes.oneOf(['default', 'dark', 'compact']),
setTheme: PropTypes.func,
setIframeTheme: PropTypes.func,
};
@ -266,6 +266,24 @@ class MainContent extends Component {
);
}
getThemeSwitchMenu() {
const { theme } = this.context;
const {
intl: { formatMessage },
} = this.props;
return (
<Menu onClick={({ key }) => this.changeThemeMode(key)} selectedKeys={[theme]}>
{[
{ type: 'default', text: formatMessage({ id: 'app.theme.switch.default' }) },
{ type: 'dark', text: formatMessage({ id: 'app.theme.switch.dark' }) },
{ type: 'compact', text: formatMessage({ id: 'app.theme.switch.compact' }) },
].map(({ type, text }) => (
<Menu.Item key={type}>{text}</Menu.Item>
))}
</Menu>
);
}
flattenMenu(menu) {
if (!menu) {
return null;
@ -279,10 +297,11 @@ class MainContent extends Component {
return this.flattenMenu((menu.props && menu.props.children) || menu.children);
}
changeTheme = () => {
const { theme, setTheme } = this.context;
const nextTheme = theme !== 'dark' ? 'dark' : 'default';
setTheme(nextTheme);
changeThemeMode = theme => {
const { setTheme, theme: selectedTheme } = this.context;
if (selectedTheme !== theme) {
setTheme(theme);
}
};
render() {
@ -320,7 +339,6 @@ class MainContent extends Component {
</Menu>
);
const componentPage = /^\/?components/.test(this.props.location.pathname);
return (
<div className="main-wrapper">
<Row>
@ -377,21 +395,9 @@ class MainContent extends Component {
</section>
{componentPage && (
<div className="fixed-widgets">
<Tooltip
getPopupContainer={node => node.parentNode}
title={formatMessage({ id: `app.theme.switch.${theme}` })}
overlayClassName="fixed-widgets-tooltip"
>
<Avatar
className={classNames(
'fixed-widgets-avatar',
`fixed-widgets-avatar-${theme}`,
)}
size={44}
onClick={this.changeTheme}
icon={theme === 'dark' ? <DarkIcon /> : <DefaultIcon />}
/>
</Tooltip>
<Dropdown overlay={this.getThemeSwitchMenu()} placement="topCenter">
<Avatar className="fixed-widgets-avatar" size={44} icon={<ThemeIcon />} />
</Dropdown>
</div>
)}
<PrevAndNext prev={prev} next={next} />

31
site/theme/template/Content/ThemeIcon.jsx

@ -1,34 +1,17 @@
import React from 'react';
import Icon from '@ant-design/icons';
export const DefaultIcon = props => {
const ThemeIcon = props => {
const SVGIcon = () => (
<svg width={21} height={21} viewBox="0 0 21 21" {...props}>
<g fill="none" fillRule="evenodd">
<circle fill="#222" cx={10.5} cy={10.5} r={10.5} />
<path
d="M13.396 11c0-3.019-1.832-5.584-4.394-6.566A6.427 6.427 0 0111.304 4C15.002 4 18 7.135 18 11c0 3.866-2.998 7-6.698 7A6.42 6.42 0 019 17.566c2.564-.98 4.396-3.545 4.396-6.566z"
fill="#FFF"
fillRule="nonzero"
/>
<svg width={21} height={21} viewBox="0 0 21 21" fill="currentColor" {...props}>
<g fillRule="evenodd">
<g fillRule="nonzero">
<path d="M7.02 3.635l12.518 12.518a1.863 1.863 0 010 2.635l-1.317 1.318a1.863 1.863 0 01-2.635 0L3.068 7.588A2.795 2.795 0 117.02 3.635zm2.09 14.428a.932.932 0 110 1.864.932.932 0 010-1.864zm-.043-9.747L7.75 9.635l9.154 9.153 1.318-1.317-9.154-9.155zM3.52 12.473c.514 0 .931.417.931.931v.932h.932a.932.932 0 110 1.864h-.932v.931a.932.932 0 01-1.863 0l-.001-.931h-.93a.932.932 0 010-1.864h.93v-.932c0-.514.418-.931.933-.931zm15.374-3.727a1.398 1.398 0 110 2.795 1.398 1.398 0 010-2.795zM4.385 4.953a.932.932 0 000 1.317l2.046 2.047L7.75 7 5.703 4.953a.932.932 0 00-1.318 0zM14.701.36a.932.932 0 01.931.932v.931h.932a.932.932 0 010 1.864h-.933l.001.932a.932.932 0 11-1.863 0l-.001-.932h-.93a.932.932 0 110-1.864h.93v-.931a.932.932 0 01.933-.932z" />
</g>
</g>
</svg>
);
return <Icon component={SVGIcon} {...props} />;
};
export const DarkIcon = props => {
const SVGIcon = () => (
<svg width={21} height={21} viewBox="0 0 21 21" {...props}>
<g fill="none" fillRule="evenodd">
<path
fill="#222"
fillRule="nonzero"
d="M21 10.5l-3 3V18h-4.5l-3 3-3-3H3v-4.5l-3-3 3-3V3h4.5l3-3 3 3H18v4.5z"
/>
<circle stroke="#FFF" strokeWidth={1.5} cx={10.5} cy={10.5} r={4} />
</g>
</svg>
);
return <Icon component={SVGIcon} {...props} />;
};
export default ThemeIcon;

4
site/theme/template/Layout/Header/index.tsx

@ -65,7 +65,7 @@ interface HeaderState {
class Header extends React.Component<HeaderProps, HeaderState> {
static contextTypes = {
router: PropTypes.object.isRequired,
theme: PropTypes.oneOf(['default', 'dark']),
theme: PropTypes.oneOf(['default', 'dark', 'compact']),
direction: PropTypes.string,
};
@ -298,7 +298,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
<UnorderedListOutlined className="nav-phone-icon" onClick={this.handleShowMenu} />
</Popover>
)}
<Row style={{ flexFlow: 'nowrap' }}>
<Row style={{ flexFlow: 'nowrap', height: 64 }}>
<Col {...colProps[0]}>
<Logo {...sharedProps} />
</Col>

3
site/theme/template/Layout/index.jsx

@ -63,6 +63,7 @@ const SITE_THEME_STORE_KEY = 'site-theme';
const timestamp = new Date().getTime();
const themeMap = {
dark: `/dark.css?${timestamp}`,
compact: `/compact.css?${timestamp}`,
};
const themeConfig = {
themeMap,
@ -75,7 +76,7 @@ export default class Layout extends React.Component {
};
static childContextTypes = {
theme: PropTypes.oneOf(['default', 'dark']),
theme: PropTypes.oneOf(['default', 'dark', 'compact']),
setTheme: PropTypes.func,
direction: PropTypes.string,
setIframeTheme: PropTypes.func,

5
site/theme/zh-CN.js

@ -1,8 +1,9 @@
module.exports = {
locale: 'zh-CN',
messages: {
'app.theme.switch.dark': '切换浅色模式',
'app.theme.switch.default': '切换暗黑模式',
'app.theme.switch.default': '默认主题',
'app.theme.switch.dark': '暗黑主题',
'app.theme.switch.compact': '紧凑主题',
'app.header.search': '全文本搜索...',
'app.header.menu.documentation': '文档',
'app.header.menu.components': '组件',

2
tests/dekko/dist.test.js

@ -12,6 +12,8 @@ $('dist')
.hasFile('antd.less')
.hasFile('antd.dark.less')
.hasFile('antd.dark.css')
.hasFile('antd.compact.less')
.hasFile('antd.compact.css')
.hasFile('dark-theme.js');
// eslint-disable-next-line

74
webpack.config.js

@ -5,6 +5,7 @@ const PacktrackerPlugin = require('@packtracker/webpack-plugin');
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const darkVars = require('./scripts/dark-vars');
const compactVars = require('./scripts/compact-vars');
const { webpack } = getWebpackConfig;
@ -33,15 +34,29 @@ function externalMoment(config) {
};
}
const webpackConfig = getWebpackConfig(false);
const webpackDarkConfig = getWebpackConfig(false);
if (process.env.RUN_ENV === 'PRODUCTION') {
webpackConfig.forEach(config => {
function processWebpackThemeConfig(themeConfig, theme, vars) {
themeConfig.forEach(config => {
ignoreMomentLocale(config);
externalMoment(config);
addLocales(config);
// Reduce non-minified dist files size
config.optimization.usedExports = true;
// rename default entry to ${theme} entry
Object.keys(config.entry).forEach(entryName => {
config.entry[entryName.replace('antd', `antd.${theme}`)] = config.entry[entryName];
delete config.entry[entryName];
});
// apply ${theme} less variables
config.module.rules.forEach(rule => {
// filter less rule
if (rule.test instanceof RegExp && rule.test.test('.less')) {
rule.use[rule.use.length - 1].options.modifyVars = vars;
}
});
const themeReg = new RegExp(`${theme}(.min)?\\.js(\\.map)?$`);
// ignore emit ${theme} entry js & js.map file
config.plugins.push(new IgnoreEmitPlugin(themeReg));
// skip codesandbox ci
if (!process.env.CSB_REPO) {
// https://docs.packtracker.io/uploading-your-webpack-stats/webpack-plugin
@ -50,37 +65,23 @@ if (process.env.RUN_ENV === 'PRODUCTION') {
project_token: '30c6a021-96c0-4d67-8bd2-0d2fcbd8962b',
upload: process.env.CI === 'true',
fail_build: false,
exclude_assets: name => !['antd.min.js', 'antd.min.css'].includes(name),
}),
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
exclude_assets: name => ![`antd.${theme}.min.js`, `antd.${theme}.min.css`].includes(name),
}),
);
}
});
}
webpackDarkConfig.forEach(config => {
const webpackConfig = getWebpackConfig(false);
const webpackDarkConfig = getWebpackConfig(false);
const webpackCompactConfig = getWebpackConfig(false);
if (process.env.RUN_ENV === 'PRODUCTION') {
webpackConfig.forEach(config => {
ignoreMomentLocale(config);
externalMoment(config);
// rename default entry to dark entry
Object.keys(config.entry).forEach(entryName => {
config.entry[entryName.replace('antd', 'antd.dark')] = config.entry[entryName];
delete config.entry[entryName];
});
// apply dark less variables
config.module.rules.forEach(rule => {
// filter less rule
if (rule.test instanceof RegExp && rule.test.test('.less')) {
rule.use[rule.use.length - 1].options.modifyVars = darkVars;
}
});
// ignore emit dark entry js & js.map file
config.plugins.push(new IgnoreEmitPlugin(/dark(.min)?\.js(\.map)?$/));
addLocales(config);
// Reduce non-minified dist files size
config.optimization.usedExports = true;
// skip codesandbox ci
if (!process.env.CSB_REPO) {
// https://docs.packtracker.io/uploading-your-webpack-stats/webpack-plugin
@ -89,11 +90,18 @@ if (process.env.RUN_ENV === 'PRODUCTION') {
project_token: '30c6a021-96c0-4d67-8bd2-0d2fcbd8962b',
upload: process.env.CI === 'true',
fail_build: false,
exclude_assets: name => !['antd.dark.min.js', 'antd.dark.min.css'].includes(name),
exclude_assets: name => !['antd.min.js', 'antd.min.css'].includes(name),
}),
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
}),
);
}
});
processWebpackThemeConfig(webpackDarkConfig, 'dark', darkVars);
processWebpackThemeConfig(webpackCompactConfig, 'compact', compactVars);
}
module.exports = webpackConfig.concat(webpackDarkConfig);
module.exports = [...webpackConfig, ...webpackDarkConfig, ...webpackCompactConfig];

Loading…
Cancel
Save