mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
fix: DatePicker itemHeight calculation (#47874)
* chore: init * chore: clean up * chore: clean up
This commit is contained in:
parent
1491b0c624
commit
7884eba28e
@ -1,51 +1,66 @@
|
||||
import React from 'react';
|
||||
import type { DatePickerProps } from 'antd';
|
||||
import { ConfigProvider, DatePicker, Space, TimePicker } from 'antd';
|
||||
import { ConfigProvider, DatePicker, Divider, Flex, Space, TimePicker } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
/** Test usage. Do not use in your production. */
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const onChange: DatePickerProps['onChange'] = (date, dateString) => {
|
||||
console.log(date, dateString);
|
||||
};
|
||||
|
||||
const App: React.FC = () => (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
DatePicker: {
|
||||
presetsWidth: 160,
|
||||
zIndexPopup: 888,
|
||||
cellHoverWithRangeBg: '#f0f0f0',
|
||||
cellActiveWithRangeBg: '#e6bbff',
|
||||
cellRangeBorderColor: 'green',
|
||||
timeColumnWidth: 80,
|
||||
timeColumnHeight: 250,
|
||||
timeCellHeight: 30,
|
||||
cellWidth: 64,
|
||||
cellHeight: 40,
|
||||
textHeight: 45,
|
||||
withoutTimeCellHeight: 70,
|
||||
<>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
DatePicker: {
|
||||
presetsWidth: 160,
|
||||
zIndexPopup: 888,
|
||||
cellHoverWithRangeBg: '#f0f0f0',
|
||||
cellActiveWithRangeBg: '#e6bbff',
|
||||
cellRangeBorderColor: 'green',
|
||||
timeColumnWidth: 80,
|
||||
timeColumnHeight: 250,
|
||||
timeCellHeight: 30,
|
||||
cellWidth: 64,
|
||||
cellHeight: 40,
|
||||
textHeight: 45,
|
||||
withoutTimeCellHeight: 70,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<DatePicker
|
||||
presets={[
|
||||
{ label: 'Yesterday', value: dayjs().add(-1, 'd') },
|
||||
{ label: 'Last Week', value: dayjs().add(-7, 'd') },
|
||||
{ label: 'Last Month', value: dayjs().add(-1, 'month') },
|
||||
]}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<RangePicker />
|
||||
<TimePicker onChange={onChange} />
|
||||
<DatePicker onChange={onChange} picker="month" />
|
||||
</Space>
|
||||
</ConfigProvider>
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<DatePicker
|
||||
presets={[
|
||||
{ label: 'Yesterday', value: dayjs().add(-1, 'd') },
|
||||
{ label: 'Last Week', value: dayjs().add(-7, 'd') },
|
||||
{ label: 'Last Month', value: dayjs().add(-1, 'month') },
|
||||
]}
|
||||
/>
|
||||
<RangePicker />
|
||||
<TimePicker />
|
||||
<DatePicker picker="month" />
|
||||
</Space>
|
||||
</ConfigProvider>
|
||||
|
||||
<Divider />
|
||||
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
DatePicker: {
|
||||
controlHeightSM: 32,
|
||||
controlHeight: 40,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Flex vertical gap={8}>
|
||||
<DatePicker multiple size="small" />
|
||||
<DatePicker multiple />
|
||||
<DatePicker multiple size="large" />
|
||||
</Flex>
|
||||
</ConfigProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
@ -1,35 +1,30 @@
|
||||
import type { CSSInterpolation } from '@ant-design/cssinjs';
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { FIXED_ITEM_MARGIN, genSelectionStyle } from '../../select/style/multiple';
|
||||
import { genOverflowStyle, getMultipleSelectorUnit } from '../../select/style/multiple';
|
||||
import { mergeToken, type GenerateStyle } from '../../theme/internal';
|
||||
import type { PickerToken } from './token';
|
||||
|
||||
const genSize = (token: PickerToken, suffix?: string): CSSInterpolation => {
|
||||
const { componentCls, selectHeight, fontHeight, lineWidth, controlHeight, calc } = token;
|
||||
const { componentCls, controlHeight } = token;
|
||||
|
||||
const suffixCls = suffix ? `${componentCls}-${suffix}` : '';
|
||||
|
||||
const height = token.calc(fontHeight).add(2).equal();
|
||||
const restHeight = () => calc(selectHeight).sub(height).sub(calc(lineWidth).mul(2));
|
||||
|
||||
const paddingBase = token.max(restHeight().div(2).equal(), 0);
|
||||
const paddingTop = token.max(token.calc(paddingBase).sub(FIXED_ITEM_MARGIN).equal(), 0);
|
||||
const paddingBottom = token.max(
|
||||
restHeight()
|
||||
.sub(paddingTop)
|
||||
.sub(FIXED_ITEM_MARGIN * 2)
|
||||
.equal(),
|
||||
0,
|
||||
);
|
||||
const multipleSelectorUnit = getMultipleSelectorUnit(token);
|
||||
|
||||
return [
|
||||
genSelectionStyle(token, suffix),
|
||||
// genSelectionStyle(token, suffix),
|
||||
{
|
||||
[`${componentCls}-multiple${suffixCls}`]: {
|
||||
paddingTop,
|
||||
paddingBottom,
|
||||
paddingInlineStart: paddingBase,
|
||||
paddingBlock: multipleSelectorUnit.containerPadding,
|
||||
paddingInlineStart: multipleSelectorUnit.basePadding,
|
||||
minHeight: controlHeight,
|
||||
|
||||
// ======================== Selections ========================
|
||||
[`${componentCls}-selection-item`]: {
|
||||
height: multipleSelectorUnit.itemHeight,
|
||||
lineHeight: unit(multipleSelectorUnit.itemLineHeight),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -41,7 +36,7 @@ const genPickerMultipleStyle: GenerateStyle<PickerToken> = (token) => {
|
||||
const smallToken = mergeToken<PickerToken>(token, {
|
||||
fontHeight: token.fontSize,
|
||||
selectHeight: token.controlHeightSM,
|
||||
multipleSelectItemHeight: token.controlHeightXS,
|
||||
multipleSelectItemHeight: token.multipleItemHeightSM,
|
||||
borderRadius: token.borderRadiusSM,
|
||||
borderRadiusSM: token.borderRadiusXS,
|
||||
controlHeight: token.controlHeightSM,
|
||||
@ -66,7 +61,6 @@ const genPickerMultipleStyle: GenerateStyle<PickerToken> = (token) => {
|
||||
genSize(largeToken, 'large'),
|
||||
|
||||
// ====================== Selection ======================
|
||||
genSelectionStyle(token),
|
||||
{
|
||||
[`${componentCls}${componentCls}-multiple`]: {
|
||||
width: '100%',
|
||||
@ -81,6 +75,9 @@ const genPickerMultipleStyle: GenerateStyle<PickerToken> = (token) => {
|
||||
},
|
||||
},
|
||||
|
||||
// ===================== Overflow ====================
|
||||
...genOverflowStyle(token),
|
||||
|
||||
// ====================== Input ======================
|
||||
// Input is `readonly`, which is used for a11y only
|
||||
[`${componentCls}-multiple-input`]: {
|
||||
|
@ -139,7 +139,9 @@ export const initPickerPanelToken = (token: TokenWithCommonCls<GlobalToken>): Pi
|
||||
};
|
||||
|
||||
export const initPanelComponentToken = (token: GlobalToken): PanelComponentToken => {
|
||||
const { colorBgContainerDisabled, controlHeightSM, controlHeightLG } = token;
|
||||
const { colorBgContainerDisabled, controlHeight, controlHeightSM, controlHeightLG, paddingXXS } =
|
||||
token;
|
||||
|
||||
return {
|
||||
cellHoverBg: token.controlItemBgHover,
|
||||
cellActiveWithRangeBg: token.controlItemBgActive,
|
||||
@ -155,8 +157,9 @@ export const initPanelComponentToken = (token: GlobalToken): PanelComponentToken
|
||||
withoutTimeCellHeight: controlHeightLG * 1.65,
|
||||
multipleItemBg: token.colorFillSecondary,
|
||||
multipleItemBorderColor: 'transparent',
|
||||
multipleItemHeight: controlHeightSM,
|
||||
multipleItemHeightLG: token.controlHeight,
|
||||
multipleItemHeight: controlHeight - paddingXXS * 2,
|
||||
multipleItemHeightSM: controlHeightSM - paddingXXS * 2,
|
||||
multipleItemHeightLG: controlHeightLG - paddingXXS * 2,
|
||||
multipleSelectorBgDisabled: colorBgContainerDisabled,
|
||||
multipleItemColorDisabled: token.colorTextDisabled,
|
||||
multipleItemBorderColorDisabled: 'transparent',
|
||||
|
@ -20,6 +20,44 @@ type SelectItemToken = Pick<
|
||||
| 'inputPaddingHorizontalBase'
|
||||
>;
|
||||
|
||||
/**
|
||||
* Get multiple selector needed style. The calculation:
|
||||
*
|
||||
* ContainerPadding = BasePadding - ItemMargin
|
||||
*
|
||||
* Border: ╔═══════════════════════════╗ ┬
|
||||
* ContainerPadding: ║ ║ │
|
||||
* ╟───────────────────────────╢ ┬ │
|
||||
* Item Margin: ║ ║ │ │
|
||||
* ║ ┌──────────┐ ║ │ │
|
||||
* Item(multipleItemHeight): ║ BasePadding │ Item │ ║ Overflow Container(ControlHeight)
|
||||
* ║ └──────────┘ ║ │ │
|
||||
* Item Margin: ║ ║ │ │
|
||||
* ╟───────────────────────────╢ ┴ │
|
||||
* ContainerPadding: ║ ║ │
|
||||
* Border: ╚═══════════════════════════╝ ┴
|
||||
*/
|
||||
export const getMultipleSelectorUnit = (
|
||||
token: Pick<
|
||||
SelectToken,
|
||||
'max' | 'calc' | 'multipleSelectItemHeight' | 'paddingXXS' | 'lineWidth'
|
||||
>,
|
||||
) => {
|
||||
const { multipleSelectItemHeight, paddingXXS, lineWidth } = token;
|
||||
|
||||
const basePadding = token.max(token.calc(paddingXXS).sub(lineWidth).equal(), 0);
|
||||
const containerPadding = token.max(token.calc(basePadding).sub(FIXED_ITEM_MARGIN).equal(), 0);
|
||||
|
||||
return {
|
||||
basePadding,
|
||||
containerPadding,
|
||||
itemHeight: unit(multipleSelectItemHeight),
|
||||
itemLineHeight: unit(
|
||||
token.calc(multipleSelectItemHeight).sub(token.calc(token.lineWidth).mul(2)).equal(),
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
const getSelectItemStyle = (token: SelectItemToken): number | string => {
|
||||
const { multipleSelectItemHeight, selectHeight, lineWidth } = token;
|
||||
const selectItemDist = token
|
||||
@ -31,11 +69,118 @@ const getSelectItemStyle = (token: SelectItemToken): number | string => {
|
||||
return selectItemDist;
|
||||
};
|
||||
|
||||
export const genSelectionStyle = (
|
||||
/**
|
||||
* Get the `rc-overflow` needed style.
|
||||
* It's a share style which means not affected by `size`.
|
||||
*/
|
||||
export const genOverflowStyle = (
|
||||
token: Pick<
|
||||
SelectToken,
|
||||
| 'calc'
|
||||
| 'componentCls'
|
||||
| 'iconCls'
|
||||
| 'borderRadiusSM'
|
||||
| 'motionDurationSlow'
|
||||
| 'paddingXS'
|
||||
| 'multipleItemColorDisabled'
|
||||
| 'multipleItemBorderColorDisabled'
|
||||
| 'colorIcon'
|
||||
| 'colorIconHover'
|
||||
>,
|
||||
): CSSObject => {
|
||||
const {
|
||||
componentCls,
|
||||
iconCls,
|
||||
borderRadiusSM,
|
||||
motionDurationSlow,
|
||||
paddingXS,
|
||||
multipleItemColorDisabled,
|
||||
multipleItemBorderColorDisabled,
|
||||
colorIcon,
|
||||
colorIconHover,
|
||||
} = token;
|
||||
|
||||
const selectOverflowPrefixCls = `${componentCls}-selection-overflow`;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Do not merge `height` & `line-height` under style with `selection` & `search`, since chrome
|
||||
* may update to redesign with its align logic.
|
||||
*/
|
||||
// =========================== Overflow ===========================
|
||||
[selectOverflowPrefixCls]: {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flex: 'auto',
|
||||
flexWrap: 'wrap',
|
||||
maxWidth: '100%',
|
||||
|
||||
'&-item': {
|
||||
flex: 'none',
|
||||
alignSelf: 'center',
|
||||
maxWidth: '100%',
|
||||
display: 'inline-flex',
|
||||
},
|
||||
|
||||
// ======================== Selections ==========================
|
||||
[`${componentCls}-selection-item`]: {
|
||||
display: 'flex',
|
||||
alignSelf: 'center',
|
||||
flex: 'none',
|
||||
boxSizing: 'border-box',
|
||||
maxWidth: '100%',
|
||||
marginBlock: FIXED_ITEM_MARGIN,
|
||||
borderRadius: borderRadiusSM,
|
||||
cursor: 'default',
|
||||
transition: `font-size ${motionDurationSlow}, line-height ${motionDurationSlow}, height ${motionDurationSlow}`,
|
||||
marginInlineEnd: token.calc(FIXED_ITEM_MARGIN).mul(2).equal(),
|
||||
paddingInlineStart: paddingXS,
|
||||
paddingInlineEnd: token.calc(paddingXS).div(2).equal(),
|
||||
|
||||
[`${componentCls}-disabled&`]: {
|
||||
color: multipleItemColorDisabled,
|
||||
borderColor: multipleItemBorderColorDisabled,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
|
||||
// It's ok not to do this, but 24px makes bottom narrow in view should adjust
|
||||
'&-content': {
|
||||
display: 'inline-block',
|
||||
marginInlineEnd: token.calc(paddingXS).div(2).equal(),
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'pre', // fix whitespace wrapping. custom tags display all whitespace within.
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
|
||||
'&-remove': {
|
||||
...resetIcon(),
|
||||
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: colorIcon,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 10,
|
||||
lineHeight: 'inherit',
|
||||
cursor: 'pointer',
|
||||
|
||||
[`> ${iconCls}`]: {
|
||||
verticalAlign: '-0.2em',
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
color: colorIconHover,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genSelectionStyle = (
|
||||
token: TokenWithCommonCls<AliasToken> & SelectItemToken,
|
||||
suffix?: string,
|
||||
): CSSObject => {
|
||||
const { componentCls, iconCls } = token;
|
||||
const { componentCls } = token;
|
||||
|
||||
const selectOverflowPrefixCls = `${componentCls}-selection-overflow`;
|
||||
|
||||
@ -44,27 +189,12 @@ export const genSelectionStyle = (
|
||||
|
||||
const suffixCls = suffix ? `${componentCls}-${suffix}` : '';
|
||||
|
||||
const multipleSelectorUnit = getMultipleSelectorUnit(token);
|
||||
|
||||
return {
|
||||
[`${componentCls}-multiple${suffixCls}`]: {
|
||||
/**
|
||||
* Do not merge `height` & `line-height` under style with `selection` & `search`, since chrome
|
||||
* may update to redesign with its align logic.
|
||||
*/
|
||||
// =========================== Overflow ===========================
|
||||
[selectOverflowPrefixCls]: {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flex: 'auto',
|
||||
flexWrap: 'wrap',
|
||||
maxWidth: '100%',
|
||||
|
||||
'&-item': {
|
||||
flex: 'none',
|
||||
alignSelf: 'center',
|
||||
maxWidth: '100%',
|
||||
display: 'inline-flex',
|
||||
},
|
||||
},
|
||||
// ========================= Overflow =========================
|
||||
...genOverflowStyle(token),
|
||||
|
||||
// ========================= Selector =========================
|
||||
[`${componentCls}-selector`]: {
|
||||
@ -73,8 +203,8 @@ export const genSelectionStyle = (
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
// Multiple is little different that horizontal is follow the vertical
|
||||
paddingInline: token.calc(FIXED_ITEM_MARGIN).mul(2).equal(),
|
||||
paddingBlock: token.calc(selectItemDist).sub(FIXED_ITEM_MARGIN).equal(),
|
||||
paddingInline: multipleSelectorUnit.basePadding,
|
||||
paddingBlock: multipleSelectorUnit.containerPadding,
|
||||
borderRadius: token.borderRadius,
|
||||
|
||||
[`${componentCls}-disabled&`]: {
|
||||
@ -94,58 +224,8 @@ export const genSelectionStyle = (
|
||||
|
||||
// ======================== Selections ========================
|
||||
[`${componentCls}-selection-item`]: {
|
||||
display: 'flex',
|
||||
alignSelf: 'center',
|
||||
flex: 'none',
|
||||
boxSizing: 'border-box',
|
||||
maxWidth: '100%',
|
||||
height: selectItemHeight,
|
||||
marginTop: FIXED_ITEM_MARGIN,
|
||||
marginBottom: FIXED_ITEM_MARGIN,
|
||||
lineHeight: unit(
|
||||
token.calc(selectItemHeight).sub(token.calc(token.lineWidth).mul(2)).equal(),
|
||||
),
|
||||
borderRadius: token.borderRadiusSM,
|
||||
cursor: 'default',
|
||||
transition: `font-size ${token.motionDurationSlow}, line-height ${token.motionDurationSlow}, height ${token.motionDurationSlow}`,
|
||||
marginInlineEnd: token.calc(FIXED_ITEM_MARGIN).mul(2).equal(),
|
||||
paddingInlineStart: token.paddingXS,
|
||||
paddingInlineEnd: token.calc(token.paddingXS).div(2).equal(),
|
||||
|
||||
[`${componentCls}-disabled&`]: {
|
||||
color: token.multipleItemColorDisabled,
|
||||
borderColor: token.multipleItemBorderColorDisabled,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
|
||||
// It's ok not to do this, but 24px makes bottom narrow in view should adjust
|
||||
'&-content': {
|
||||
display: 'inline-block',
|
||||
marginInlineEnd: token.calc(token.paddingXS).div(2).equal(),
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'pre', // fix whitespace wrapping. custom tags display all whitespace within.
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
|
||||
'&-remove': {
|
||||
...resetIcon(),
|
||||
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: token.colorIcon,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 10,
|
||||
lineHeight: 'inherit',
|
||||
cursor: 'pointer',
|
||||
|
||||
[`> ${iconCls}`]: {
|
||||
verticalAlign: '-0.2em',
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
color: token.colorIconHover,
|
||||
},
|
||||
},
|
||||
height: multipleSelectorUnit.itemHeight,
|
||||
lineHeight: unit(multipleSelectorUnit.itemLineHeight),
|
||||
},
|
||||
|
||||
// ========================== Input ==========================
|
||||
@ -241,7 +321,7 @@ const genMultipleStyle = (token: SelectToken): CSSInterpolation => {
|
||||
|
||||
const smallToken = mergeToken<SelectToken>(token, {
|
||||
selectHeight: token.controlHeightSM,
|
||||
multipleSelectItemHeight: token.controlHeightXS,
|
||||
multipleSelectItemHeight: token.multipleItemHeightSM,
|
||||
borderRadius: token.borderRadiusSM,
|
||||
borderRadiusSM: token.borderRadiusXS,
|
||||
});
|
||||
|
@ -17,6 +17,11 @@ export interface MultipleSelectorToken {
|
||||
* @descEN Height of multiple tag
|
||||
*/
|
||||
multipleItemHeight: number;
|
||||
/**
|
||||
* @desc 小号多选标签高度
|
||||
* @descEN Height of multiple tag with small size
|
||||
*/
|
||||
multipleItemHeightSM: number;
|
||||
/**
|
||||
* @desc 大号多选标签高度
|
||||
* @descEN Height of multiple tag with large size
|
||||
@ -121,7 +126,13 @@ export const prepareComponentToken: GetDefaultToken<'Select'> = (token) => {
|
||||
const {
|
||||
fontSize,
|
||||
lineHeight,
|
||||
|
||||
controlHeight,
|
||||
controlHeightSM,
|
||||
controlHeightLG,
|
||||
|
||||
paddingXXS,
|
||||
|
||||
controlPaddingHorizontal,
|
||||
zIndexPopupBase,
|
||||
colorText,
|
||||
@ -130,12 +141,15 @@ export const prepareComponentToken: GetDefaultToken<'Select'> = (token) => {
|
||||
controlItemBgHover,
|
||||
colorBgContainer,
|
||||
colorFillSecondary,
|
||||
controlHeightLG,
|
||||
controlHeightSM,
|
||||
|
||||
colorBgContainerDisabled,
|
||||
colorTextDisabled,
|
||||
} = token;
|
||||
|
||||
const multipleItemHeight = controlHeight - paddingXXS * 2;
|
||||
const multipleItemHeightSM = controlHeightSM - paddingXXS * 2;
|
||||
const multipleItemHeightLG = controlHeightLG - paddingXXS * 2;
|
||||
|
||||
return {
|
||||
zIndexPopup: zIndexPopupBase + 50,
|
||||
optionSelectedColor: colorText,
|
||||
@ -151,8 +165,9 @@ export const prepareComponentToken: GetDefaultToken<'Select'> = (token) => {
|
||||
singleItemHeightLG: controlHeightLG,
|
||||
multipleItemBg: colorFillSecondary,
|
||||
multipleItemBorderColor: 'transparent',
|
||||
multipleItemHeight: controlHeightSM,
|
||||
multipleItemHeightLG: controlHeight,
|
||||
multipleItemHeight,
|
||||
multipleItemHeightSM,
|
||||
multipleItemHeightLG,
|
||||
multipleSelectorBgDisabled: colorBgContainerDisabled,
|
||||
multipleItemColorDisabled: colorTextDisabled,
|
||||
multipleItemBorderColorDisabled: 'transparent',
|
||||
|
Loading…
Reference in New Issue
Block a user