diff --git a/components/_util/theme/index.tsx b/components/_util/theme/index.tsx index be83acb8be..c9d2861dc6 100644 --- a/components/_util/theme/index.tsx +++ b/components/_util/theme/index.tsx @@ -98,6 +98,8 @@ export interface DerivativeToken extends Omit { warningOutlineColor: string; itemActiveBackground: string; + highlightColor: string; + linkColor: string; fontSizeSM: number; fontSizeLG: number; @@ -154,6 +156,8 @@ function derivative(designToken: DesignToken): DerivativeToken { warningHoverColor: warningColors[4], warningOutlineColor: new TinyColor(warningColor).setAlpha(0.2).toRgbString(), + highlightColor: errorColors[4], // FIXME: Should not align with error color + itemActiveBackground: primaryColors[0], linkColor: primaryColor, diff --git a/components/cascader/index.tsx b/components/cascader/index.tsx index 89f8caa1af..a177166092 100644 --- a/components/cascader/index.tsx +++ b/components/cascader/index.tsx @@ -22,6 +22,8 @@ import getIcons from '../select/utils/iconUtil'; import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion'; import { FormItemStatusContext } from '../form/context'; import { getMergedStatus, getStatusClassNames, InputStatus } from '../_util/statusUtils'; +import useStyle from './style'; +import useSelectStyle from '../select/style'; // Align the design since we use `rc-select` in root. This help: // - List search content will show all content @@ -140,6 +142,7 @@ const Cascader = React.forwardRef((props: CascaderProps, ref: React.Ref, ref: React.Ref, ref: React.Ref, ref: React.Ref, ref: React.Ref, ref: React.Ref ); + + return wrapCascaderSSR(wrapSelectSSR(renderNode)); }) as (( props: React.PropsWithChildren> & { ref?: React.Ref }, ) => React.ReactElement) & { diff --git a/components/cascader/style/index.less b/components/cascader/style/index.less index 8df1d85fc7..ac83ef085d 100644 --- a/components/cascader/style/index.less +++ b/components/cascader/style/index.less @@ -1,104 +1,104 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; -@import '../../input/style/mixin'; -@import '../../checkbox/style/mixin'; +// @import '../../style/themes/index'; +// @import '../../style/mixins/index'; +// @import '../../input/style/mixin'; +// @import '../../checkbox/style/mixin'; -@cascader-prefix-cls: ~'@{ant-prefix}-cascader'; +// @cascader-prefix-cls: ~'@{ant-prefix}-cascader'; -.antCheckboxFn(@checkbox-prefix-cls: ~'@{cascader-prefix-cls}-checkbox'); +// .antCheckboxFn(@checkbox-prefix-cls: ~'@{cascader-prefix-cls}-checkbox'); -.@{cascader-prefix-cls} { - width: 184px; +// .@{cascader-prefix-cls} { +// width: 184px; - &-checkbox { - top: 0; - margin-right: @padding-xs; - } +// &-checkbox { +// top: 0; +// margin-right: @padding-xs; +// } - &-menus { - display: flex; - flex-wrap: nowrap; - align-items: flex-start; +// &-menus { +// display: flex; +// flex-wrap: nowrap; +// align-items: flex-start; - &.@{cascader-prefix-cls}-menu-empty { - .@{cascader-prefix-cls}-menu { - width: 100%; - height: auto; - } - } - } +// &.@{cascader-prefix-cls}-menu-empty { +// .@{cascader-prefix-cls}-menu { +// width: 100%; +// height: auto; +// } +// } +// } - &-menu { - min-width: 111px; - height: 180px; - margin: 0; - margin: -@dropdown-edge-child-vertical-padding 0; - padding: @cascader-dropdown-edge-child-vertical-padding 0; - overflow: auto; - vertical-align: top; - list-style: none; - border-right: @border-width-base @border-style-base @cascader-menu-border-color-split; - -ms-overflow-style: -ms-autohiding-scrollbar; // https://github.com/ant-design/ant-design/issues/11857 +// &-menu { +// min-width: 111px; +// height: 180px; +// margin: 0; +// margin: -@dropdown-edge-child-vertical-padding 0; +// padding: @cascader-dropdown-edge-child-vertical-padding 0; +// overflow: auto; +// vertical-align: top; +// list-style: none; +// border-right: @border-width-base @border-style-base @cascader-menu-border-color-split; +// -ms-overflow-style: -ms-autohiding-scrollbar; // https://github.com/ant-design/ant-design/issues/11857 - &-item { - display: flex; - flex-wrap: nowrap; - align-items: center; - padding: @cascader-dropdown-vertical-padding @control-padding-horizontal; - overflow: hidden; - line-height: @cascader-dropdown-line-height; - white-space: nowrap; - text-overflow: ellipsis; - cursor: pointer; - transition: all 0.3s; +// &-item { +// display: flex; +// flex-wrap: nowrap; +// align-items: center; +// padding: @cascader-dropdown-vertical-padding @control-padding-horizontal; +// overflow: hidden; +// line-height: @cascader-dropdown-line-height; +// white-space: nowrap; +// text-overflow: ellipsis; +// cursor: pointer; +// transition: all 0.3s; - &:hover { - background: @item-hover-bg; - } +// &:hover { +// background: @item-hover-bg; +// } - &-disabled { - color: @disabled-color; - cursor: not-allowed; +// &-disabled { +// color: @disabled-color; +// cursor: not-allowed; - &:hover { - background: transparent; - } - } +// &:hover { +// background: transparent; +// } +// } - .@{cascader-prefix-cls}-menu-empty & { - color: @disabled-color; - cursor: default; - pointer-events: none; - } +// .@{cascader-prefix-cls}-menu-empty & { +// color: @disabled-color; +// cursor: default; +// pointer-events: none; +// } - &-active:not(&-disabled) { - &, - &:hover { - font-weight: @select-item-selected-font-weight; - background-color: @cascader-item-selected-bg; - } - } +// &-active:not(&-disabled) { +// &, +// &:hover { +// font-weight: @select-item-selected-font-weight; +// background-color: @cascader-item-selected-bg; +// } +// } - &-content { - flex: auto; - } +// &-content { +// flex: auto; +// } - &-expand &-expand-icon, - &-loading-icon { - margin-left: @padding-xss; - color: @text-color-secondary; - font-size: 10px; +// &-expand &-expand-icon, +// &-loading-icon { +// margin-left: @padding-xss; +// color: @text-color-secondary; +// font-size: 10px; - .@{cascader-prefix-cls}-menu-item-disabled& { - color: @disabled-color; - } - } +// .@{cascader-prefix-cls}-menu-item-disabled& { +// color: @disabled-color; +// } +// } - &-keyword { - color: @highlight-color; - } - } - } -} +// &-keyword { +// color: @highlight-color; +// } +// } +// } +// } -@import './rtl'; +// @import './rtl'; diff --git a/components/cascader/style/index.tsx b/components/cascader/style/index.tsx index b4e1b0338a..f7276c96cd 100644 --- a/components/cascader/style/index.tsx +++ b/components/cascader/style/index.tsx @@ -1,8 +1,172 @@ -import '../../style/index.less'; -import './index.less'; +// import '../../style/index.less'; +// import './index.less'; -// style dependencies -import '../../empty/style'; -import '../../select/style'; +// // style dependencies +// import '../../empty/style'; +// import '../../select/style'; -// deps-lint-skip: form +// // deps-lint-skip: form + +// deps-lint-skip-all +import { CSSInterpolation } from '@ant-design/cssinjs'; +import { + DerivativeToken, + useStyleRegister, + useToken, + UseComponentStyleResult, +} from '../../_util/theme'; +import { getStyle as getCheckboxStyle } from '../../checkbox/style'; + +interface CascaderToken extends DerivativeToken { + cascaderCls: string; +} + +// =============================== Base =============================== +const genBaseStyle = (token: CascaderToken): CSSInterpolation => { + const { cascaderCls } = token; + const cascaderMenuItemCls = `${cascaderCls}-menu-item`; + const iconCls = ` + ${cascaderMenuItemCls}-expand ${cascaderMenuItemCls}-expand-icon, + ${cascaderMenuItemCls}-loading-icon + `; + + const itemPaddingVertical = Math.round( + (token.controlHeight - token.fontSize * token.lineHeight) / 2, + ); + + return [ + // ===================================================== + // == Control == + // ===================================================== + { + [cascaderCls]: { + width: 184, // FIXME: hardcode in v4 + }, + }, + + // ===================================================== + // == Popup == + // ===================================================== + { + [`${cascaderCls}-dropdown`]: { + [cascaderCls]: { + // ================== Checkbox ================== + '&-checkbox': { + top: 0, + marginInlineEnd: token.paddingXS, + }, + + // ==================== Menu ==================== + // >>> Menus + '&-menus': { + display: 'flex', + flexWrap: 'nowrap', + alignItems: 'flex-start', + + [`&${cascaderCls}-menu-empty`]: { + [`${cascaderCls}-menu`]: { + width: '100%', + height: 'auto', + + [cascaderMenuItemCls]: { + color: token.textColorDisabled, + cursor: 'default', + pointerEvents: 'none', + }, + }, + }, + }, + + // >>> Menu + '&-menu': { + minWidth: 111, // FIXME: hardcode in v4 + height: 180, // FIXME: hardcode in v4 + margin: `-${token.paddingXS}px 0`, + padding: `${token.paddingXS}px 0`, + overflow: 'auto', + verticalAlign: 'top', + listStyle: 'none', + borderInlineEnd: `${token.borderWidth}px ${token.borderStyle} ${token.borderColorSplit}`, + '-ms-overflow-style': '-ms-autohiding-scrollbar', // https://github.com/ant-design/ant-design/issues/11857 + + '&-item': { + display: 'flex', + flexWrap: 'nowrap', + alignItems: 'center', + padding: `${itemPaddingVertical}px ${token.paddingSM}px`, + overflow: 'hidden', + lineHeight: token.lineHeight, + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + cursor: 'pointer', + transition: `all ${token.duration}`, + + '&:hover': { + background: token.itemHoverBackground, + }, + ' &-disabled': { + color: token.textColorDisabled, + cursor: 'not-allowed', + + '&:hover': { + background: 'transparent', + }, + + [iconCls]: { + color: token.textColorDisabled, + }, + }, + + [`&-active:not(${cascaderMenuItemCls}-disabled)`]: { + [`&, &:hover`]: { + fontWeight: 600, // FIXME: hardcode + backgroundColor: token.itemActiveBackground, + }, + }, + + '&-content': { + flex: 'auto', + }, + + [iconCls]: { + marginInlineStart: token.paddingXXS, + color: token.textColorSecondary, + fontSize: 10, // FIXME: hardcode in v4 + }, + + '&-keyword': { + color: token.highlightColor, + }, + }, + }, + }, + }, + }, + // ===================================================== + // == RTL == + // ===================================================== + { + [`${cascaderCls}-dropdown-rtl`]: { + direction: 'rtl', + }, + }, + ]; +}; + +// ============================== Export ============================== +export default function useStyle(prefixCls: string): UseComponentStyleResult { + const [theme, token, hashId] = useToken(); + + const cascaderToken: CascaderToken = { + ...token, + cascaderCls: `.${prefixCls}`, + }; + + return [ + useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [ + getCheckboxStyle(`${prefixCls}-checkbox`, token, hashId), + genBaseStyle(cascaderToken), + ]), + hashId, + ]; +}