refactor: Dropdown cssinjs support (#35214)

* chore: init

* chore: dropdown style

* chore: more style

* chore: icon style

* chore: more style

* chore: diff shows the cache path

* chore: motion support

* chore: more style

* feat: status

* chore: sub menu style

* chore: all dropdown style

* fix: ts

* chore: update snapshot

* Update components/dropdown/style/index.tsx

Co-authored-by: MadCcc <1075746765@qq.com>

* chore: update style

Co-authored-by: MadCcc <1075746765@qq.com>
This commit is contained in:
二货机器人 2022-04-25 10:54:00 +08:00 committed by GitHub
parent 690608d1c2
commit b4730281a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1143 additions and 565 deletions

View File

@ -1,6 +1,7 @@
import type * as React from 'react';
import type { ComponentToken as ButtonComponentToken } from '../../button/style';
import type { ComponentToken as DividerComponentToken } from '../../divider/style';
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
import type { ComponentToken as CascaderComponentToken } from '../../cascader/style';
import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
@ -57,6 +58,7 @@ export interface OverrideToken {
Descriptions?: {};
Divider?: DividerComponentToken;
Drawer?: {};
Dropdown?: DropdownComponentToken;
Empty?: EmptyComponentToken;
Form?: {};
Grid?: {};
@ -133,6 +135,7 @@ export interface SeedToken extends PresetColorType {
// Size
sizeUnit: number;
sizeBaseStep: number;
sizePopupArrow: number;
// Control Base
controlHeight: number;
@ -297,6 +300,8 @@ export interface AliasToken extends Omit<DerivativeToken, OmitDerivativeKey> {
colorBgComponentDisabled: string;
// =============== Legacy: should be remove ===============
colorLoadingOpacity: number;
padding: number;
margin: number;

View File

@ -189,6 +189,7 @@ const seedToken: SeedToken = {
// Size
sizeUnit: 4,
sizeBaseStep: 4,
sizePopupArrow: 8 * Math.sqrt(2),
// Control Base
controlHeight: 32,

View File

@ -99,6 +99,8 @@ export default function formatToken(derivativeToken: RawMergedToken): AliasToken
// warningColors,
// errorColors,
colorLoadingOpacity: 0.65,
colorSuccessSecondary: successColors[2],
colorWarningSecondary: warningColors[2],
colorErrorSecondary: errorColors[2],

View File

@ -9,16 +9,22 @@ export type OverrideTokenWithoutDerivative = Omit<OverrideToken, 'derivative'>;
export type OverrideComponent = keyof OverrideTokenWithoutDerivative;
export type GlobalTokenWithComponent<ComponentName extends OverrideComponent> = GlobalToken &
OverrideToken[ComponentName];
export type StyleInfo = {
export interface StyleInfo {
hashId: string;
prefixCls: string;
rootPrefixCls: string;
iconPrefixCls: string;
};
}
export type TokenWithCommonCls<T> = T & {
/** Wrap component class with `.` prefix */
componentCls: string;
/** Origin prefix which do not have `.` prefix */
prefixCls: string;
/** Wrap icon class with `.` prefix */
iconCls: string;
/** Wrap ant prefixCls class with `.` prefix */
antCls: string;
};
export type FullToken<ComponentName extends OverrideComponent> = TokenWithCommonCls<

View File

@ -1,60 +1,80 @@
import type { GenerateStyle } from '../../_util/theme';
import type { ButtonToken } from '.';
const genGroupStyle: GenerateStyle<ButtonToken> = token => {
const { componentCls, fontSizeBase, controlLineWidth, colorPrimaryHover } = token;
return {
[`${componentCls}-group`]: {
position: 'relative',
display: 'inline-flex',
// Border
[`> span, > ${componentCls}`]: {
'&:not(:last-child)': {
[`&, & > ${componentCls}`]: {
borderStartEndRadius: 0,
borderEndEndRadius: 0,
'&:not(:disabled)': {
borderInlineEndColor: colorPrimaryHover,
},
},
const genButtonBorderStyle = (buttonTypeCls: string, borderColor: string) => ({
// Border
[`> span, > ${buttonTypeCls}`]: {
'&:not(:last-child)': {
[`&, & > ${buttonTypeCls}`]: {
'&:not(:disabled)': {
borderInlineEndColor: borderColor,
},
'&:not(:first-child)': {
marginInlineStart: -controlLineWidth,
[`&, & > ${componentCls}`]: {
borderStartStartRadius: 0,
borderEndStartRadius: 0,
'&:not(:disabled)': {
borderInlineStartColor: colorPrimaryHover,
},
},
},
},
[componentCls]: {
position: 'relative',
zIndex: 1,
[`&:hover,
&:focus,
&:active`]: {
zIndex: 2,
},
'&[disabled]': {
zIndex: 0,
},
},
[`${componentCls}-icon-only`]: {
fontSize: fontSizeBase,
},
},
'&:not(:first-child)': {
[`&, & > ${buttonTypeCls}`]: {
'&:not(:disabled)': {
borderInlineStartColor: borderColor,
},
},
},
},
});
const genGroupStyle: GenerateStyle<ButtonToken> = token => {
const { componentCls, fontSizeBase, controlLineWidth, colorPrimaryHover, colorErrorHover } =
token;
return {
[`${componentCls}-group`]: [
{
position: 'relative',
display: 'inline-flex',
// Border
[`> span, > ${componentCls}`]: {
'&:not(:last-child)': {
[`&, & > ${componentCls}`]: {
borderStartEndRadius: 0,
borderEndEndRadius: 0,
},
},
'&:not(:first-child)': {
marginInlineStart: -controlLineWidth,
[`&, & > ${componentCls}`]: {
borderStartStartRadius: 0,
borderEndStartRadius: 0,
},
},
},
[componentCls]: {
position: 'relative',
zIndex: 1,
[`&:hover,
&:focus,
&:active`]: {
zIndex: 2,
},
'&[disabled]': {
zIndex: 0,
},
},
[`${componentCls}-icon-only`]: {
fontSize: fontSizeBase,
},
},
// Border Color
genButtonBorderStyle(`${componentCls}-primary`, colorPrimaryHover),
genButtonBorderStyle(`${componentCls}-danger`, colorErrorHover),
],
};
};

View File

@ -326,7 +326,7 @@ const genSizeButtonStyle = (token: ButtonToken, sizePrefixCls: string = ''): CSS
// Loading
[`&${componentCls}-loading`]: {
opacity: 0.65,
opacity: token.colorLoadingOpacity,
cursor: 'default',
},

View File

@ -12875,7 +12875,7 @@ exports[`ConfigProvider components Dropdown normal 1`] = `
exports[`ConfigProvider components Dropdown prefixCls 1`] = `
<div
class="ant-btn-group prefix-Dropdown"
class="ant-btn-group prefix-Dropdown-button"
>
<button
class="ant-btn ant-btn-default"

View File

@ -6,6 +6,7 @@ import { ButtonHTMLType } from '../button/button';
import { ButtonGroupProps } from '../button/button-group';
import { ConfigContext } from '../config-provider';
import Dropdown, { DropdownProps } from './dropdown';
import useStyle from './style';
const ButtonGroup = Button.Group;
@ -63,7 +64,10 @@ const DropdownButton: DropdownButtonInterface = props => {
...restProps
} = props;
const prefixCls = getPrefixCls('dropdown-button', customizePrefixCls);
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
const buttonPrefixCls = `${prefixCls}-button`;
const [wrapSSR, hashId] = useStyle(prefixCls);
const dropdownProps = {
align,
overlay,
@ -106,11 +110,11 @@ const DropdownButton: DropdownButtonInterface = props => {
const [leftButtonToRender, rightButtonToRender] = buttonsRender!([leftButton, rightButton]);
return (
<ButtonGroup {...restProps} className={classNames(prefixCls, className)}>
return wrapSSR(
<ButtonGroup {...restProps} className={classNames(buttonPrefixCls, className, hashId)}>
{leftButtonToRender}
<Dropdown {...dropdownProps}>{rightButtonToRender}</Dropdown>
</ButtonGroup>
</ButtonGroup>,
);
};

View File

@ -8,6 +8,7 @@ import devWarning from '../_util/devWarning';
import { tuple } from '../_util/type';
import { cloneElement } from '../_util/reactNode';
import getPlacements from '../_util/placements';
import useStyle from './style';
const Placements = tuple(
'topLeft',
@ -165,6 +166,8 @@ const Dropdown: DropdownInterface = props => {
} = props;
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const child = React.Children.only(children) as React.ReactElement<any>;
const dropdownTrigger = cloneElement(child, {
@ -178,7 +181,7 @@ const Dropdown: DropdownInterface = props => {
disabled,
});
const overlayClassNameCustomized = classNames(overlayClassName, {
const overlayClassNameCustomized = classNames(overlayClassName, hashId, {
[`${prefixCls}-rtl`]: direction === 'rtl',
});
@ -193,7 +196,7 @@ const Dropdown: DropdownInterface = props => {
autoAdjustOverflow: true,
});
return (
return wrapSSR(
<RcDropdown
alignPoint={alignPoint}
{...props}
@ -208,7 +211,7 @@ const Dropdown: DropdownInterface = props => {
placement={getPlacement()}
>
{dropdownTrigger}
</RcDropdown>
</RcDropdown>,
);
};

View File

@ -0,0 +1,26 @@
import type { GenerateStyle } from '../../_util/theme';
import type { DropdownToken } from '.';
const genButtonStyle: GenerateStyle<DropdownToken> = token => {
const { componentCls, antCls, paddingXS, colorLoadingOpacity } = token;
return {
[`${componentCls}-button`]: {
whiteSpace: 'nowrap',
[`&${antCls}-btn-group > ${antCls}-btn`]: {
[`&-loading, &-loading + ${antCls}-btn`]: {
cursor: 'default',
pointerEvents: 'none',
opacity: colorLoadingOpacity,
},
[`&:last-child:not(:first-child):not(${antCls}-btn-icon-only)`]: {
paddingInline: paddingXS,
},
},
},
};
};
export default genButtonStyle;

View File

@ -1,394 +1,394 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import './status';
// @import '../../style/themes/index';
// @import '../../style/mixins/index';
// @import './status';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
.@{dropdown-prefix-cls} {
.reset-component();
// .@{dropdown-prefix-cls} {
// .reset-component();
position: absolute;
top: -9999px;
left: -9999px;
z-index: @zindex-dropdown;
display: block;
// position: absolute;
// top: -9999px;
// left: -9999px;
// z-index: @zindex-dropdown;
// display: block;
&::before {
position: absolute;
top: -@popover-distance + @popover-arrow-width;
right: 0;
bottom: -@popover-distance + @popover-arrow-width;
left: -7px;
z-index: -9999;
opacity: 0.0001;
content: ' ';
}
// &::before {
// position: absolute;
// top: -@popover-distance + @popover-arrow-width;
// right: 0;
// bottom: -@popover-distance + @popover-arrow-width;
// left: -7px;
// z-index: -9999;
// opacity: 0.0001;
// content: ' ';
// }
&-wrap {
position: relative;
// &-wrap {
// position: relative;
.@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
font-size: 10px;
}
// .@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
// font-size: 10px;
// }
.@{iconfont-css-prefix}-down::before {
transition: transform @animation-duration-base;
}
}
// .@{iconfont-css-prefix}-down::before {
// transition: transform @animation-duration-base;
// }
// }
&-wrap-open {
.@{iconfont-css-prefix}-down::before {
transform: rotate(180deg);
}
}
// &-wrap-open {
// .@{iconfont-css-prefix}-down::before {
// transform: rotate(180deg);
// }
// }
&-hidden,
&-menu-hidden,
&-menu-submenu-hidden {
display: none;
}
// &-hidden,
// &-menu-hidden,
// &-menu-submenu-hidden {
// display: none;
// }
// Offset the popover to account for the dropdown arrow
&-show-arrow&-placement-topLeft,
&-show-arrow&-placement-top,
&-show-arrow&-placement-topRight {
padding-bottom: @popover-distance;
}
// // Offset the popover to account for the dropdown arrow
// &-show-arrow&-placement-topLeft,
// &-show-arrow&-placement-top,
// &-show-arrow&-placement-topRight {
// padding-bottom: @popover-distance;
// }
&-show-arrow&-placement-bottomLeft,
&-show-arrow&-placement-bottom,
&-show-arrow&-placement-bottomRight {
padding-top: @popover-distance;
}
// &-show-arrow&-placement-bottomLeft,
// &-show-arrow&-placement-bottom,
// &-show-arrow&-placement-bottomRight {
// padding-top: @popover-distance;
// }
// Arrows
// .popover-arrow is outer, .popover-arrow:after is inner
// // Arrows
// // .popover-arrow is outer, .popover-arrow:after is inner
&-arrow {
position: absolute;
z-index: 1; // lift it up so the menu wouldn't cask shadow on it
display: block;
width: @popover-arrow-width;
height: @popover-arrow-width;
background: linear-gradient(
135deg,
transparent 40%,
@popover-bg 40%
); // Use linear-gradient to prevent arrow from covering text
.roundedArrow(@popover-arrow-width, 5px, @popover-bg);
}
// &-arrow {
// position: absolute;
// z-index: 1; // lift it up so the menu wouldn't cask shadow on it
// display: block;
// width: @popover-arrow-width;
// height: @popover-arrow-width;
// background: linear-gradient(
// 135deg,
// transparent 40%,
// @popover-bg 40%
// ); // Use linear-gradient to prevent arrow from covering text
// .roundedArrow(@popover-arrow-width, 5px, @popover-bg);
// }
&-placement-top > &-arrow,
&-placement-topLeft > &-arrow,
&-placement-topRight > &-arrow {
bottom: @popover-arrow-width * sqrt((1 / 2)) + 2px;
box-shadow: 3px 3px 7px -3px fade(@black, 10%);
transform: rotate(45deg);
}
// &-placement-top > &-arrow,
// &-placement-topLeft > &-arrow,
// &-placement-topRight > &-arrow {
// bottom: @popover-arrow-width * sqrt((1 / 2)) + 2px;
// box-shadow: 3px 3px 7px -3px fade(@black, 10%);
// transform: rotate(45deg);
// }
&-placement-top > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
// &-placement-top > &-arrow {
// left: 50%;
// transform: translateX(-50%) rotate(45deg);
// }
&-placement-topLeft > &-arrow {
left: 16px;
}
// &-placement-topLeft > &-arrow {
// left: 16px;
// }
&-placement-topRight > &-arrow {
right: 16px;
}
// &-placement-topRight > &-arrow {
// right: 16px;
// }
&-placement-bottom > &-arrow,
&-placement-bottomLeft > &-arrow,
&-placement-bottomRight > &-arrow {
top: (@popover-arrow-width + 2px) * sqrt((1 / 2));
box-shadow: 2px 2px 5px -2px fade(@black, 10%);
transform: rotate(-135deg) translateY(-0.5px);
}
// &-placement-bottom > &-arrow,
// &-placement-bottomLeft > &-arrow,
// &-placement-bottomRight > &-arrow {
// top: (@popover-arrow-width + 2px) * sqrt((1 / 2));
// box-shadow: 2px 2px 5px -2px fade(@black, 10%);
// transform: rotate(-135deg) translateY(-0.5px);
// }
&-placement-bottom > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(-135deg) translateY(-0.5px);
}
// &-placement-bottom > &-arrow {
// left: 50%;
// transform: translateX(-50%) rotate(-135deg) translateY(-0.5px);
// }
&-placement-bottomLeft > &-arrow {
left: 16px;
}
// &-placement-bottomLeft > &-arrow {
// left: 16px;
// }
&-placement-bottomRight > &-arrow {
right: 16px;
}
// &-placement-bottomRight > &-arrow {
// right: 16px;
// }
&-menu {
position: relative;
margin: 0;
padding: @dropdown-edge-child-vertical-padding 0;
text-align: left;
list-style-type: none;
background-color: @dropdown-menu-bg;
background-clip: padding-box;
border-radius: @border-radius-base;
outline: none;
box-shadow: @box-shadow-base;
// &-menu {
// position: relative;
// margin: 0;
// padding: @dropdown-edge-child-vertical-padding 0;
// text-align: left;
// list-style-type: none;
// background-color: @dropdown-menu-bg;
// background-clip: padding-box;
// border-radius: @border-radius-base;
// outline: none;
// box-shadow: @box-shadow-base;
&-item-group-title {
padding: 5px @control-padding-horizontal;
color: @text-color-secondary;
transition: all @animation-duration-slow;
}
// &-item-group-title {
// padding: 5px @control-padding-horizontal;
// color: @text-color-secondary;
// transition: all @animation-duration-slow;
// }
&-submenu-popup {
position: absolute;
z-index: @zindex-dropdown;
background: transparent;
box-shadow: none;
transform-origin: 0 0;
// &-submenu-popup {
// position: absolute;
// z-index: @zindex-dropdown;
// background: transparent;
// box-shadow: none;
// transform-origin: 0 0;
ul,
li {
list-style: none;
}
// ul,
// li {
// list-style: none;
// }
ul {
margin-right: 0.3em;
margin-left: 0.3em;
}
}
// ul {
// margin-right: 0.3em;
// margin-left: 0.3em;
// }
// }
// ======================= Item Content =======================
&-item {
position: relative;
display: flex;
align-items: center;
}
// // ======================= Item Content =======================
// &-item {
// position: relative;
// display: flex;
// align-items: center;
// }
&-item-icon {
min-width: 12px;
margin-right: 8px;
font-size: @font-size-sm;
}
// &-item-icon {
// min-width: 12px;
// margin-right: 8px;
// font-size: @font-size-sm;
// }
&-title-content {
flex: auto;
// &-title-content {
// flex: auto;
> a {
color: inherit;
transition: all @animation-duration-slow;
// > a {
// color: inherit;
// transition: all @animation-duration-slow;
&:hover {
color: inherit;
}
// &:hover {
// color: inherit;
// }
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
content: '';
}
}
}
// &::after {
// position: absolute;
// top: 0;
// right: 0;
// bottom: 0;
// left: 0;
// content: '';
// }
// }
// }
// =========================== Item ===========================
&-item,
&-submenu-title {
clear: both;
margin: 0;
padding: @dropdown-vertical-padding @control-padding-horizontal;
color: @text-color;
font-weight: normal;
font-size: @dropdown-font-size;
line-height: @dropdown-line-height;
cursor: pointer;
transition: all @animation-duration-slow;
// // =========================== Item ===========================
// &-item,
// &-submenu-title {
// clear: both;
// margin: 0;
// padding: @dropdown-vertical-padding @control-padding-horizontal;
// color: @text-color;
// font-weight: normal;
// font-size: @dropdown-font-size;
// line-height: @dropdown-line-height;
// cursor: pointer;
// transition: all @animation-duration-slow;
&:first-child {
& when (@dropdown-edge-child-vertical-padding = 0) {
border-radius: @border-radius-base @border-radius-base 0 0;
}
}
// &:first-child {
// & when (@dropdown-edge-child-vertical-padding = 0) {
// border-radius: @border-radius-base @border-radius-base 0 0;
// }
// }
&:last-child {
& when (@dropdown-edge-child-vertical-padding = 0) {
border-radius: 0 0 @border-radius-base @border-radius-base;
}
}
// &:last-child {
// & when (@dropdown-edge-child-vertical-padding = 0) {
// border-radius: 0 0 @border-radius-base @border-radius-base;
// }
// }
&-selected {
color: @dropdown-selected-color;
background-color: @dropdown-selected-bg;
}
// &-selected {
// color: @dropdown-selected-color;
// background-color: @dropdown-selected-bg;
// }
&:hover,
&&-active {
background-color: @item-hover-bg;
}
// &:hover,
// &&-active {
// background-color: @item-hover-bg;
// }
&-disabled {
color: @disabled-color;
cursor: not-allowed;
// &-disabled {
// color: @disabled-color;
// cursor: not-allowed;
&:hover {
color: @disabled-color;
background-color: @dropdown-menu-submenu-disabled-bg;
cursor: not-allowed;
}
// &:hover {
// color: @disabled-color;
// background-color: @dropdown-menu-submenu-disabled-bg;
// cursor: not-allowed;
// }
a {
pointer-events: none;
}
}
// a {
// pointer-events: none;
// }
// }
&-divider {
height: 1px;
margin: 4px 0;
overflow: hidden;
line-height: 0;
background-color: @border-color-split;
}
// &-divider {
// height: 1px;
// margin: 4px 0;
// overflow: hidden;
// line-height: 0;
// background-color: @border-color-split;
// }
.@{dropdown-prefix-cls}-menu-submenu-expand-icon {
position: absolute;
right: @padding-xs;
// .@{dropdown-prefix-cls}-menu-submenu-expand-icon {
// position: absolute;
// right: @padding-xs;
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
margin-right: 0 !important;
color: @text-color-secondary;
font-size: 10px;
font-style: normal;
}
}
}
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
// margin-right: 0 !important;
// color: @text-color-secondary;
// font-size: 10px;
// font-style: normal;
// }
// }
// }
&-item-group-list {
margin: 0 8px;
padding: 0;
list-style: none;
}
// &-item-group-list {
// margin: 0 8px;
// padding: 0;
// list-style: none;
// }
&-submenu-title {
padding-right: @control-padding-horizontal + @font-size-sm;
}
// &-submenu-title {
// padding-right: @control-padding-horizontal + @font-size-sm;
// }
&-submenu-vertical {
position: relative;
}
// &-submenu-vertical {
// position: relative;
// }
&-submenu-vertical > & {
position: absolute;
top: 0;
left: 100%;
min-width: 100%;
margin-left: 4px;
transform-origin: 0 0;
}
// &-submenu-vertical > & {
// position: absolute;
// top: 0;
// left: 100%;
// min-width: 100%;
// margin-left: 4px;
// transform-origin: 0 0;
// }
&-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
&,
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
color: @disabled-color;
background-color: @dropdown-menu-submenu-disabled-bg;
cursor: not-allowed;
}
}
// &-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
// &,
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
// color: @disabled-color;
// background-color: @dropdown-menu-submenu-disabled-bg;
// cursor: not-allowed;
// }
// }
// https://github.com/ant-design/ant-design/issues/19264
&-submenu-selected &-submenu-title {
color: @primary-color;
}
}
// // https://github.com/ant-design/ant-design/issues/19264
// &-submenu-selected &-submenu-title {
// color: @primary-color;
// }
// }
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
animation-name: antSlideUpIn;
}
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottom,
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottom,
// &.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
// &.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
// animation-name: antSlideUpIn;
// }
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
animation-name: antSlideDownIn;
}
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-top,
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-top,
// &.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
// &.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
// animation-name: antSlideDownIn;
// }
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
animation-name: antSlideUpOut;
}
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottom,
// &.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
// animation-name: antSlideUpOut;
// }
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
animation-name: antSlideDownOut;
}
}
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-top,
// &.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
// animation-name: antSlideDownOut;
// }
// }
.@{dropdown-prefix-cls}-trigger,
.@{dropdown-prefix-cls}-link,
.@{dropdown-prefix-cls}-button {
> .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
font-size: 10px;
vertical-align: baseline;
}
}
// .@{dropdown-prefix-cls}-trigger,
// .@{dropdown-prefix-cls}-link,
// .@{dropdown-prefix-cls}-button {
// > .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
// font-size: 10px;
// vertical-align: baseline;
// }
// }
.@{dropdown-prefix-cls}-button {
white-space: nowrap;
// .@{dropdown-prefix-cls}-button {
// white-space: nowrap;
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn {
&-loading,
&-loading + .@{ant-prefix}-btn {
cursor: default;
pointer-events: none;
}
// &.@{ant-prefix}-btn-group > .@{ant-prefix}-btn {
// &-loading,
// &-loading + .@{ant-prefix}-btn {
// cursor: default;
// pointer-events: none;
// }
&-loading + .@{ant-prefix}-btn::before {
display: block;
}
// &-loading + .@{ant-prefix}-btn::before {
// display: block;
// }
&:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
padding-right: @padding-xs;
padding-left: @padding-xs;
}
}
}
// &:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
// padding-right: @padding-xs;
// padding-left: @padding-xs;
// }
// }
// }
// https://github.com/ant-design/ant-design/issues/4903
.@{dropdown-prefix-cls}-menu-dark {
&,
.@{dropdown-prefix-cls}-menu {
background: @menu-dark-bg;
}
.@{dropdown-prefix-cls}-menu-item,
.@{dropdown-prefix-cls}-menu-submenu-title,
.@{dropdown-prefix-cls}-menu-item > a,
.@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
color: @text-color-secondary-dark;
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
color: @text-color-secondary-dark;
}
// // https://github.com/ant-design/ant-design/issues/4903
// .@{dropdown-prefix-cls}-menu-dark {
// &,
// .@{dropdown-prefix-cls}-menu {
// background: @menu-dark-bg;
// }
// .@{dropdown-prefix-cls}-menu-item,
// .@{dropdown-prefix-cls}-menu-submenu-title,
// .@{dropdown-prefix-cls}-menu-item > a,
// .@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
// color: @text-color-secondary-dark;
// .@{dropdown-prefix-cls}-menu-submenu-arrow::after {
// color: @text-color-secondary-dark;
// }
&:hover {
color: @text-color-inverse;
background: transparent;
}
}
.@{dropdown-prefix-cls}-menu-item-selected {
&,
&:hover,
> a {
color: @text-color-inverse;
background: @primary-color;
}
}
}
// &:hover {
// color: @text-color-inverse;
// background: transparent;
// }
// }
// .@{dropdown-prefix-cls}-menu-item-selected {
// &,
// &:hover,
// > a {
// color: @text-color-inverse;
// background: @primary-color;
// }
// }
// }
@import './rtl';
// @import './rtl';

View File

@ -1,5 +1,458 @@
import '../../style/index.less';
import './index.less';
// deps-lint-skip-all
import {
GenerateStyle,
resetComponent,
FullToken,
genComponentStyleHook,
mergeToken,
roundedArrow,
} from '../../_util/theme';
import {
initSlideMotion,
slideUpIn,
slideUpOut,
slideDownIn,
slideDownOut,
} from '../../style/motion';
import genButtonStyle from './button';
import genStatusStyle from './status';
// style dependencies
import '../../button/style';
export interface ComponentToken {
zIndexDropdown: number;
}
export interface DropdownToken extends FullToken<'Dropdown'> {
rootPrefixCls: string;
dropdownArrowDistance: number;
dropdownArrowOffset: number;
dropdownPaddingVertical: number;
dropdownEdgeChildVerticalPadding: number;
menuCls: string;
}
// =============================== Base ===============================
const genBaseStyle: GenerateStyle<DropdownToken> = token => {
const {
rootPrefixCls,
componentCls,
menuCls,
zIndexDropdown,
dropdownArrowDistance,
dropdownArrowOffset,
sizePopupArrow,
antCls,
iconCls,
colorBgComponent,
motionDurationMid,
motionDurationSlow,
dropdownPaddingVertical,
fontSizeBase,
dropdownEdgeChildVerticalPadding,
radiusBase,
colorTextDisabled,
fontSizeIcon,
controlPaddingHorizontal,
} = token;
return [
{
[componentCls]: {
...resetComponent(token),
position: 'absolute',
top: -9999,
left: {
_skip_check_: true,
value: -9999,
},
zIndex: zIndexDropdown,
display: 'block',
// A placeholder out of dropdown visible range to avoid close when user moving
'&::before': {
position: 'absolute',
insetBlock: -dropdownArrowDistance + sizePopupArrow,
// insetInlineStart: -7, // FIXME: Seems not work for hidden element
zIndex: -9999,
opacity: 0.0001,
content: '""',
},
[`${componentCls}-wrap`]: {
position: 'relative',
[`${antCls}-btn > ${iconCls}-down`]: {
fontSize: fontSizeIcon,
},
[`${iconCls}-down::before`]: {
transition: `transform ${motionDurationMid}`,
},
},
[`${componentCls}-wrap-open`]: {
[`${iconCls}-down::before`]: {
transform: `rotate(180deg)`,
},
},
[`
&-hidden,
&-menu-hidden,
&-menu-submenu-hidden
`]: {
display: 'none',
},
// =============================================================
// == Arrow ==
// =============================================================
// Offset the popover to account for the dropdown arrow
[`
&-show-arrow&-placement-topLeft,
&-show-arrow&-placement-top,
&-show-arrow&-placement-topRight
`]: {
paddingBottom: dropdownArrowDistance,
},
[`
&-show-arrow&-placement-bottomLeft,
&-show-arrow&-placement-bottom,
&-show-arrow&-placement-bottomRight
`]: {
paddingTop: dropdownArrowDistance,
},
// Note: .popover-arrow is outer, .popover-arrow:after is inner
[`${componentCls}-arrow`]: {
position: 'absolute',
zIndex: 1, // lift it up so the menu wouldn't cask shadow on it
display: 'block',
width: sizePopupArrow,
height: sizePopupArrow,
// Use linear-gradient to prevent arrow from covering text
background: `linear-gradient(135deg, transparent 40%, ${colorBgComponent} 40%)`,
...roundedArrow(sizePopupArrow, 5, colorBgComponent),
},
[`
&-placement-top > ${componentCls}-arrow,
&-placement-topLeft > ${componentCls}-arrow,
&-placement-topRight > ${componentCls}-arrow
`]: {
bottom: sizePopupArrow * Math.sqrt(1 / 2) + 2,
boxShadow: `3px 3px 7px -3px rgba(0, 0, 0, 0.1)`, // FIXME: hardcode
transform: 'rotate(45deg)',
},
[`&-placement-top > ${componentCls}-arrow`]: {
left: {
_skip_check_: true,
value: '50%',
},
transform: 'translateX(-50%) rotate(45deg)',
},
[`&-placement-topLeft > ${componentCls}-arrow`]: {
left: {
_skip_check_: true,
value: dropdownArrowOffset,
},
},
[`&-placement-topRight > ${componentCls}-arrow`]: {
right: {
_skip_check_: true,
value: dropdownArrowOffset,
},
},
[`
&-placement-bottom > ${componentCls}-arrow,
&-placement-bottomLeft > ${componentCls}-arrow,
&-placement-bottomRight > ${componentCls}-arrow
`]: {
top: (sizePopupArrow + 2) * Math.sqrt(1 / 2),
boxShadow: `2px 2px 5px -2px rgba(0, 0, 0, 0.1)`, // FIXME: hardcode
transform: `rotate(-135deg) translateY(-0.5px)`, // FIXME: hardcode
},
[`&-placement-bottom > ${componentCls}-arrow`]: {
left: {
_skip_check_: true,
value: '50%',
},
transform: `translateX(-50%) rotate(-135deg) translateY(-0.5px)`,
},
[`&-placement-bottomLeft > ${componentCls}-arrow`]: {
left: {
_skip_check_: true,
value: dropdownArrowOffset,
},
},
[`&-placement-bottomRight > ${componentCls}-arrow`]: {
right: {
_skip_check_: true,
value: dropdownArrowOffset,
},
},
// =============================================================
// == Motion ==
// =============================================================
// When position is not enough for dropdown, the placement will revert.
// We will handle this with revert motion name.
[`&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottomLeft,
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottomLeft
&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottom,
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottom,
&${antCls}-slide-down-enter${antCls}-slide-down-enter-active&-placement-bottomRight,
&${antCls}-slide-down-appear${antCls}-slide-down-appear-active&-placement-bottomRight`]: {
animationName: slideUpIn,
},
[`&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-topLeft,
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-topLeft,
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-top,
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-top,
&${antCls}-slide-up-enter${antCls}-slide-up-enter-active&-placement-topRight,
&${antCls}-slide-up-appear${antCls}-slide-up-appear-active&-placement-topRight`]: {
animationName: slideDownIn,
},
[`&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottomLeft,
&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottom,
&${antCls}-slide-down-leave${antCls}-slide-down-leave-active&-placement-bottomRight`]: {
animationName: slideUpOut,
},
[`&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-topLeft,
&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-top,
&${antCls}-slide-up-leave${antCls}-slide-up-leave-active&-placement-topRight`]: {
animationName: slideDownOut,
},
},
},
{
// =============================================================
// == Menu ==
// =============================================================
[`${componentCls} ${menuCls}`]: {
position: 'relative',
margin: 0,
},
[`${menuCls}-submenu-popup`]: {
position: 'absolute',
zIndex: zIndexDropdown,
background: 'transparent',
boxShadow: 'none',
transformOrigin: '0 0',
'ul,li': {
listStyle: 'none',
},
ul: {
marginInline: '0.3em',
},
},
[`${componentCls}, ${componentCls}-menu-submenu`]: {
[menuCls]: {
padding: `${dropdownEdgeChildVerticalPadding}px 0`,
listStyleType: 'none',
backgroundColor: colorBgComponent,
backgroundClip: 'padding-box',
borderRadius: token.controlRadius,
outline: 'none',
boxShadow: token.boxShadow,
[`${menuCls}-item-group-title`]: {
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
color: token.colorTextSecondary,
transition: `all ${motionDurationSlow}`,
},
// ======================= Item Content =======================
[`${menuCls}-item`]: {
position: 'relative',
display: 'flex',
alignItems: 'center',
},
[`${menuCls}-item-icon`]: {
minWidth: fontSizeBase,
marginInlineEnd: token.marginXS,
fontSize: token.fontSizeSM,
},
[`${menuCls}-title-content`]: {
flex: 'auto',
'> a': {
color: 'inherit',
transition: `all ${motionDurationSlow}`,
'&:hover': {
color: 'inherit',
},
'&::after': {
position: 'absolute',
inset: 0,
content: '""',
},
},
},
// =========================== Item ===========================
[`${menuCls}-item, ${menuCls}-submenu-title`]: {
clear: 'both',
margin: 0,
padding: `${dropdownPaddingVertical}px ${controlPaddingHorizontal}px`,
color: token.colorText,
fontWeight: 'normal',
fontSize: fontSizeBase,
lineHeight: token.lineHeight,
cursor: 'pointer',
transition: `all ${motionDurationSlow}`,
'&:first-child': !dropdownEdgeChildVerticalPadding
? {
borderRadius: `${radiusBase}px ${radiusBase}px 0 0`,
}
: [],
'&:last-child': !dropdownEdgeChildVerticalPadding
? {
borderRadius: `0 0 ${radiusBase}px ${radiusBase}px`,
}
: [],
'&-selected': {
color: token.colorPrimary,
backgroundColor: token.controlItemBgActive,
},
[`&:hover, &-active`]: {
backgroundColor: token.controlItemBgHover,
},
'&-disabled': {
color: colorTextDisabled,
cursor: 'not-allowed',
'&:hover': {
color: colorTextDisabled,
backgroundColor: colorBgComponent,
cursor: 'not-allowed',
},
a: {
pointerEvents: 'none',
},
},
'&-divider': {
height: 1, // By design
margin: `${token.marginXXS}px 0`,
overflow: 'hidden',
lineHeight: 0,
backgroundColor: token.colorSplit,
},
[`${componentCls}-menu-submenu-expand-icon`]: {
position: 'absolute',
insetInlineEnd: token.paddingXS,
[`${componentCls}-menu-submenu-arrow-icon`]: {
marginInlineEnd: '0 !important',
color: token.colorTextSecondary,
fontSize: fontSizeIcon,
fontStyle: 'normal',
},
},
},
[`${menuCls}-item-group-list`]: {
margin: `0 ${token.marginXS}px`,
padding: 0,
listStyle: 'none',
},
[`${menuCls}-submenu-title`]: {
paddingInlineEnd: controlPaddingHorizontal + token.fontSizeSM,
},
[`${menuCls}-submenu-vertical`]: {
position: 'relative',
},
[`${menuCls}-submenu${menuCls}-submenu-disabled ${componentCls}-menu-submenu-title`]: {
[`&, ${componentCls}-menu-submenu-arrow-icon`]: {
color: colorTextDisabled,
backgroundColor: colorBgComponent,
cursor: 'not-allowed',
},
},
// https://github.com/ant-design/ant-design/issues/19264
[`${menuCls}-submenu-selected ${componentCls}-menu-submenu-title`]: {
color: token.colorPrimary,
},
},
},
},
// Follow code may reuse in other components
[
initSlideMotion(rootPrefixCls, 'slide-up', slideUpIn, slideUpOut, token),
initSlideMotion(rootPrefixCls, 'slide-down', slideDownIn, slideDownOut, token),
slideUpIn,
slideUpOut,
slideDownIn,
slideDownOut,
],
];
};
// ============================== Export ==============================
export default genComponentStyleHook(
'Dropdown',
(token, { rootPrefixCls }) => {
const {
marginXXS,
sizePopupArrow,
controlHeight,
fontSizeBase,
lineHeight,
paddingXXS,
componentCls,
} = token;
const dropdownPaddingVertical = (controlHeight - fontSizeBase * lineHeight) / 2;
const dropdownToken = mergeToken<DropdownToken>(token, {
menuCls: `${componentCls}-menu`,
rootPrefixCls,
dropdownArrowDistance: sizePopupArrow + marginXXS,
dropdownArrowOffset: (sizePopupArrow / Math.sqrt(2)) * 2,
dropdownPaddingVertical,
dropdownEdgeChildVerticalPadding: paddingXXS,
});
return [
genBaseStyle(dropdownToken),
genButtonStyle(dropdownToken),
genStatusStyle(dropdownToken),
];
},
token => ({
zIndexDropdown: token.zIndexPopup + 50,
}),
);

View File

@ -1,90 +1,90 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
// @import '../../style/themes/index';
// @import '../../style/mixins/index';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
.@{dropdown-prefix-cls} {
&-rtl {
direction: rtl;
}
// .@{dropdown-prefix-cls} {
// &-rtl {
// direction: rtl;
// }
&::before {
.@{dropdown-prefix-cls}-rtl& {
right: -7px;
left: 0;
}
}
// &::before {
// .@{dropdown-prefix-cls}-rtl& {
// right: -7px;
// left: 0;
// }
// }
&-menu {
&&-rtl {
direction: rtl;
text-align: right;
}
// &-menu {
// &&-rtl {
// direction: rtl;
// text-align: right;
// }
&-item-group-title {
.@{dropdown-prefix-cls}-rtl &,
.@{dropdown-prefix-cls}-menu-submenu-rtl & {
direction: rtl;
text-align: right;
}
}
// &-item-group-title {
// .@{dropdown-prefix-cls}-rtl &,
// .@{dropdown-prefix-cls}-menu-submenu-rtl & {
// direction: rtl;
// text-align: right;
// }
// }
&-submenu-popup {
&.@{dropdown-prefix-cls}-menu-submenu-rtl {
transform-origin: 100% 0;
}
// &-submenu-popup {
// &.@{dropdown-prefix-cls}-menu-submenu-rtl {
// transform-origin: 100% 0;
// }
ul,
li {
.@{dropdown-prefix-cls}-rtl & {
text-align: right;
}
}
}
// ul,
// li {
// .@{dropdown-prefix-cls}-rtl & {
// text-align: right;
// }
// }
// }
&-item,
&-submenu-title {
.@{dropdown-prefix-cls}-rtl & {
text-align: right;
}
// &-item,
// &-submenu-title {
// .@{dropdown-prefix-cls}-rtl & {
// text-align: right;
// }
> .@{iconfont-css-prefix}:first-child,
> span > .@{iconfont-css-prefix}:first-child {
.@{dropdown-prefix-cls}-rtl & {
margin-right: 0;
margin-left: 8px;
}
}
// > .@{iconfont-css-prefix}:first-child,
// > span > .@{iconfont-css-prefix}:first-child {
// .@{dropdown-prefix-cls}-rtl & {
// margin-right: 0;
// margin-left: 8px;
// }
// }
.@{dropdown-prefix-cls}-menu-submenu-expand-icon {
.@{dropdown-prefix-cls}-rtl & {
right: auto;
left: @padding-xs;
}
// .@{dropdown-prefix-cls}-menu-submenu-expand-icon {
// .@{dropdown-prefix-cls}-rtl & {
// right: auto;
// left: @padding-xs;
// }
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
.@{dropdown-prefix-cls}-rtl & {
margin-left: 0 !important;
transform: scaleX(-1);
}
}
}
}
// .@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
// .@{dropdown-prefix-cls}-rtl & {
// margin-left: 0 !important;
// transform: scaleX(-1);
// }
// }
// }
// }
&-submenu-title {
.@{dropdown-prefix-cls}-rtl & {
padding-right: @control-padding-horizontal;
padding-left: @control-padding-horizontal + @font-size-sm;
}
}
// &-submenu-title {
// .@{dropdown-prefix-cls}-rtl & {
// padding-right: @control-padding-horizontal;
// padding-left: @control-padding-horizontal + @font-size-sm;
// }
// }
&-submenu-vertical > & {
.@{dropdown-prefix-cls}-rtl & {
right: 100%;
left: 0;
margin-right: 4px;
margin-left: 0;
}
}
}
}
// &-submenu-vertical > & {
// .@{dropdown-prefix-cls}-rtl & {
// right: 100%;
// left: 0;
// margin-right: 4px;
// margin-left: 0;
// }
// }
// }
// }

View File

@ -1,14 +1,14 @@
@import (reference) '../../style/themes/index';
// @import (reference) '../../style/themes/index';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
// @dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
.@{dropdown-prefix-cls}-menu-item {
&&-danger {
color: @error-color;
// .@{dropdown-prefix-cls}-menu-item {
// &&-danger {
// color: @error-color;
&:hover {
color: @text-color-inverse;
background-color: @error-color;
}
}
}
// &:hover {
// color: @text-color-inverse;
// background-color: @error-color;
// }
// }
// }

View File

@ -0,0 +1,25 @@
import type { GenerateStyle } from '../../_util/theme';
import type { DropdownToken } from '.';
const genStatusStyle: GenerateStyle<DropdownToken> = token => {
const { componentCls, menuCls, colorError, colorTextLightSolid } = token;
const itemCls = `${menuCls}-item`;
return {
[`${componentCls}, ${componentCls}-menu-submenu`]: {
[`${menuCls} ${itemCls}`]: {
[`&${itemCls}-danger`]: {
color: colorError,
'&:hover': {
color: colorTextLightSolid,
backgroundColor: colorError,
},
},
},
},
};
};
export default genStatusStyle;

View File

@ -62,6 +62,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
} = props;
const passedProps = omit(restProps, ['collapsedWidth']);
const injectFromDropdown = (props as any)['data-dropdown-inject'];
// ========================= Items ===========================
const mergedChildren = useItems(items) || children;
@ -101,7 +102,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {
};
const prefixCls = getPrefixCls('menu', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls, !injectFromDropdown);
const menuClassName = classNames(`${prefixCls}-${theme}`, className);
// ======================== Context ==========================

View File

@ -1,7 +1,13 @@
// deps-lint-skip-all
import { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import { genComponentStyleHook, resetComponent, clearFix, mergeToken } from '../../_util/theme';
import {
genComponentStyleHook,
resetComponent,
clearFix,
mergeToken,
UseComponentStyleResult,
} from '../../_util/theme';
import type { GenerateStyle, FullToken } from '../../_util/theme';
/** Component only token. Which will handle additional calculation of alias token */
@ -1028,39 +1034,48 @@ const genBaseStyle: GenerateStyle<MenuToken, CSSObject> = (token): CSSObject =>
};
// ============================== Export ==============================
export default genComponentStyleHook('Menu', token => {
const MenuToken = mergeToken<MenuToken>(token, {
black: '#000', // FIXME: hard code in v4
componentBackground: '#fff', // FIXME: hard code in v4
darkBg: '#001529', // FIXME: hard code in v4
darkInlineSubmenuBg: '#000c17', // FIXME: hard code in v4
colorTextSecondary: new TinyColor('#000').setAlpha(0.45).toRgbString(), // FIXME: hard code in v4
highlightDangerColor: new TinyColor('#f5222d').setAlpha(0.2).toRgbString(), // FIXME: hard code in v4 // color(~`colorPalette('@{red-6}', 5) `)
itemActiveDangerBg: new TinyColor('#f5222d').setAlpha(0.9).toRgbString(), // FIXME: hard code in v4 // color(~`colorPalette('@{red-6}', 1) `)
itemActiveBackground: new TinyColor('#000').setAlpha(0.9).toRgbString(), // FIXME: hard code in v4
itemActiveBg: '#e6f7ff', // FIXME: hard code in v4,
textColorDark: new TinyColor('#000').setAlpha(0.85).toRgbString(), // FIXME: hard code in v4
disabledColor: new TinyColor('#000').setAlpha(0.25).toRgbString(), // FIXME: hard code in v4
darkColor: new TinyColor('#fff').setAlpha(0.65).toRgbString(), // FIXME: hard code in v4
colorDark: new TinyColor('#fff').setAlpha(0.85).toRgbString(), // FIXME: hard code in v4
disabledColorDark: new TinyColor('#fff').setAlpha(0.45).toRgbString(), // FIXME: hard code in v4
darkHighlightColor: '#fff', // FIXME: hard code in v4
motionDurationMD: '0.15s', // FIXME: hard code in v4,
primaryColor: '#1890ff', // FIXME: hard code in v4
boxShadowColor: new TinyColor('#1890ff').setAlpha(0.05).toRgbString(), // FIXME: hard code in v4, shade(@primary-color, 5%)
borderColorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(), // FIXME: hard code in v4
menuInlineSubmenuBg: new TinyColor({ h: 0, s: 0, v: 98 }).toHexString(), // FIXME: hard code in v4
easeOut: 'cubic-bezier(0.215, 0.61, 0.355, 1)', // FIXME: hard code in v4
width20: 20, // FIXME: hard code in v4
zIndexDrop: 1050, // FIXME: hard code in v4
menuOpacity: 0.0001, // FIXME: hard code in v4
sizeLg: 16, // FIXME: hard code in v4
export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResult => {
const useOriginHook = genComponentStyleHook('Menu', token => {
// Dropdown will handle menu style self. We do not need to handle this.
if (injectStyle === false) {
return [];
}
const MenuToken = mergeToken<MenuToken>(token, {
black: '#000', // FIXME: hard code in v4
componentBackground: '#fff', // FIXME: hard code in v4
darkBg: '#001529', // FIXME: hard code in v4
darkInlineSubmenuBg: '#000c17', // FIXME: hard code in v4
colorTextSecondary: new TinyColor('#000').setAlpha(0.45).toRgbString(), // FIXME: hard code in v4
highlightDangerColor: new TinyColor('#f5222d').setAlpha(0.2).toRgbString(), // FIXME: hard code in v4 // color(~`colorPalette('@{red-6}', 5) `)
itemActiveDangerBg: new TinyColor('#f5222d').setAlpha(0.9).toRgbString(), // FIXME: hard code in v4 // color(~`colorPalette('@{red-6}', 1) `)
itemActiveBackground: new TinyColor('#000').setAlpha(0.9).toRgbString(), // FIXME: hard code in v4
itemActiveBg: '#e6f7ff', // FIXME: hard code in v4,
textColorDark: new TinyColor('#000').setAlpha(0.85).toRgbString(), // FIXME: hard code in v4
disabledColor: new TinyColor('#000').setAlpha(0.25).toRgbString(), // FIXME: hard code in v4
darkColor: new TinyColor('#fff').setAlpha(0.65).toRgbString(), // FIXME: hard code in v4
colorDark: new TinyColor('#fff').setAlpha(0.85).toRgbString(), // FIXME: hard code in v4
disabledColorDark: new TinyColor('#fff').setAlpha(0.45).toRgbString(), // FIXME: hard code in v4
darkHighlightColor: '#fff', // FIXME: hard code in v4
motionDurationMD: '0.15s', // FIXME: hard code in v4,
primaryColor: '#1890ff', // FIXME: hard code in v4
boxShadowColor: new TinyColor('#1890ff').setAlpha(0.05).toRgbString(), // FIXME: hard code in v4, shade(@primary-color, 5%)
borderColorSplit: new TinyColor({ h: 0, s: 0, v: 94 }).toHexString(), // FIXME: hard code in v4
menuInlineSubmenuBg: new TinyColor({ h: 0, s: 0, v: 98 }).toHexString(), // FIXME: hard code in v4
easeOut: 'cubic-bezier(0.215, 0.61, 0.355, 1)', // FIXME: hard code in v4
width20: 20, // FIXME: hard code in v4
zIndexDrop: 1050, // FIXME: hard code in v4
menuOpacity: 0.0001, // FIXME: hard code in v4
sizeLg: 16, // FIXME: hard code in v4
});
return [
genBaseStyle(MenuToken),
genDarkStyle(MenuToken),
genLightStyle(MenuToken),
genStatusStyle(MenuToken),
];
});
return [
genBaseStyle(MenuToken),
genDarkStyle(MenuToken),
genLightStyle(MenuToken),
genStatusStyle(MenuToken),
];
});
return useOriginHook(prefixCls);
};

View File

@ -115,7 +115,7 @@
],
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/cssinjs": "^0.0.0-alpha.31",
"@ant-design/cssinjs": "^0.0.0-alpha.33",
"@ant-design/icons": "^4.7.0",
"@ant-design/react-slick": "~0.28.1",
"@babel/runtime": "^7.12.5",

View File

@ -15,45 +15,54 @@ export interface PreviewProps {
onClose: () => void;
}
function formatStyle(style: string) {
let formatted = style;
// Break lines
formatted = formatted.replace(/{/g, ' {\n').replace(/}/g, '}\n').replace(/;/g, ';\n');
// Line convert
{
const lines = formatted.split(/[\n\r]+/);
let leftParenthesis = false;
formatted = lines
.map(line => {
if (line.includes('}')) {
leftParenthesis = false;
}
if (leftParenthesis) {
line = ` ${line.replace(/:/g, ': ')}`;
}
if (line.includes('{')) {
leftParenthesis = true;
}
// More lines for }
line = line.replace('}', '}\n');
return line;
})
.join('\n');
}
return formatted;
}
export default function Preview({ visible, onClose }: PreviewProps) {
const [styleList, setStyleList] = React.useState<string[]>([]);
const [styleList, setStyleList] = React.useState<{ text: string; path: string }[]>([]);
React.useEffect(() => {
const observer = new MutationObserver(() => {
const latestStyles = Array.from(document.querySelectorAll('style[data-css-hash]'))
.map(style => style?.innerHTML || '')
// Break lines
.map(style => style.replace(/{/g, ' {\n'))
.map(style => style.replace(/}/g, '}\n'))
.map(style => style.replace(/;/g, ';\n'))
// Line convert
.map(style => {
const lines = style.split(/[\n\r]+/);
let leftParenthesis = false;
return lines
.map(line => {
if (line.includes('}')) {
leftParenthesis = false;
}
if (leftParenthesis) {
line = ` ${line.replace(/:/g, ': ')}`;
}
if (line.includes('{')) {
leftParenthesis = true;
}
// More lines for }
line = line.replace('}', '}\n');
return line;
})
.join('\n');
})
// Format
.filter(txt => txt);
.filter(style => style)
.map(style => ({
text: formatStyle(style.innerHTML),
path: style.getAttribute('data-dev-cache-path')!,
}))
.filter(style => style.text);
setStyleList(latestStyles);
});
@ -67,11 +76,14 @@ export default function Preview({ visible, onClose }: PreviewProps) {
const formatStyles = React.useMemo(
() =>
styleList.map(style => {
const lines = style
const lines = style.text
.split(/[\n\r]+/)
.map(line => (line.includes('{') ? line.replace(/,/g, ',\n') : line))
.join('\n');
return hljs.highlight(lines, { language: 'css' }).value;
return {
...style,
text: hljs.highlight(lines, { language: 'css' }).value,
};
}),
[styleList],
);
@ -80,8 +92,8 @@ export default function Preview({ visible, onClose }: PreviewProps) {
type Item = { status: STATUS; line: string; source?: string };
const list: Item[] = [];
styleList.forEach(style => {
const lines = style.split(/[\n\r]+/);
styleList.forEach(({ text }) => {
const lines = text.split(/[\n\r]+/);
lines.forEach((line, index) => {
const status = getValidateStatus(line);
@ -130,8 +142,11 @@ export default function Preview({ visible, onClose }: PreviewProps) {
<Tabs>
<Tabs.TabPane tab="Style" key="style">
<Typography>
{formatStyles.map((style, index) => (
<pre key={index} dangerouslySetInnerHTML={{ __html: style }} />
{formatStyles.map(({ text, path }, index) => (
<pre
key={index}
dangerouslySetInnerHTML={{ __html: `🐚 Cache: ${path}\n\n${text}` }}
/>
))}
</Typography>
</Tabs.TabPane>

View File

@ -1,4 +1,6 @@
# V5 breaking change 记录
- Dropdown 魔改包裹元素样式移除,请使用 Space 组件
- Dropdown
- 魔改包裹元素样式移除,请使用 Space 组件
- DropdownButton 的 prefixCls 改为 `dropdown`
- Upload List 结构变化