refactor: menu
parent
221b203cbb
commit
94e981e00b
|
@ -41,6 +41,8 @@ import type { FocusEventHandler, MouseEventHandler } from '../../_util/EventInte
|
|||
import collapseMotion from '../../_util/collapseMotion';
|
||||
import type { ItemType } from './hooks/useItems';
|
||||
import useItems from './hooks/useItems';
|
||||
import useStyle from '../style';
|
||||
import { useInjectOverride } from './OverrideContext';
|
||||
|
||||
export const menuProps = () => ({
|
||||
id: String,
|
||||
|
@ -95,7 +97,17 @@ export default defineComponent({
|
|||
props: menuProps(),
|
||||
slots: ['expandIcon', 'overflowedIndicator'],
|
||||
setup(props, { slots, emit, attrs }) {
|
||||
const { prefixCls, direction, getPrefixCls } = useConfigInject('menu', props);
|
||||
const { direction, getPrefixCls } = useConfigInject('menu', props);
|
||||
const override = useInjectOverride();
|
||||
const prefixCls = computed(() => {
|
||||
return getPrefixCls('menu', props.prefixCls || override?.prefixCls?.value);
|
||||
});
|
||||
const [wrapSSR, hashId] = useStyle(
|
||||
prefixCls,
|
||||
computed(() => {
|
||||
return !override;
|
||||
}),
|
||||
);
|
||||
const store = shallowRef<Map<string, StoreMenuInfo>>(new Map());
|
||||
const siderCollapsed = inject(SiderCollapsedKey, ref(undefined));
|
||||
const inlineCollapsed = computed(() => {
|
||||
|
@ -265,6 +277,9 @@ export default defineComponent({
|
|||
mergedMode.value = props.mode;
|
||||
mergedInlineCollapsed.value = false;
|
||||
}
|
||||
if (override?.mode?.value) {
|
||||
mergedMode.value = override.mode.value;
|
||||
}
|
||||
});
|
||||
|
||||
const isInlineMode = computed(() => mergedMode.value === 'inline');
|
||||
|
@ -346,6 +361,7 @@ export default defineComponent({
|
|||
const onInternalClick = (info: MenuInfo) => {
|
||||
emit('click', info);
|
||||
triggerSelection(info);
|
||||
override?.onClick?.();
|
||||
};
|
||||
|
||||
const onInternalOpenChange = (key: Key, open: boolean) => {
|
||||
|
@ -406,7 +422,7 @@ export default defineComponent({
|
|||
triggerSubMenuAction: computed(() => props.triggerSubMenuAction),
|
||||
getPopupContainer: computed(() => props.getPopupContainer),
|
||||
inlineCollapsed: mergedInlineCollapsed,
|
||||
antdMenuTheme: computed(() => props.theme),
|
||||
theme: computed(() => props.theme),
|
||||
siderCollapsed,
|
||||
defaultMotions: computed(() => (isMounted.value ? defaultMotions.value : null)),
|
||||
motion: computed(() => (isMounted.value ? props.motion : null)),
|
||||
|
@ -419,7 +435,7 @@ export default defineComponent({
|
|||
isRootMenu: ref(true),
|
||||
expandIcon,
|
||||
forceSubMenuRender: computed(() => props.forceSubMenuRender),
|
||||
rootClassName: computed(() => ''),
|
||||
rootClassName: hashId,
|
||||
});
|
||||
return () => {
|
||||
const childList = itemsNodes.value || flattenChildren(slots.default?.());
|
||||
|
@ -442,14 +458,14 @@ export default defineComponent({
|
|||
));
|
||||
const overflowedIndicator = slots.overflowedIndicator?.() || <EllipsisOutlined />;
|
||||
|
||||
return (
|
||||
return wrapSSR(
|
||||
<Overflow
|
||||
{...attrs}
|
||||
onMousedown={props.onMousedown}
|
||||
prefixCls={`${prefixCls.value}-overflow`}
|
||||
component="ul"
|
||||
itemComponent={MenuItem}
|
||||
class={[className.value, attrs.class]}
|
||||
class={[className.value, attrs.class, hashId.value]}
|
||||
role="menu"
|
||||
id={props.id}
|
||||
data={wrappedChildList}
|
||||
|
@ -499,7 +515,7 @@ export default defineComponent({
|
|||
<PathContext>{wrappedChildList}</PathContext>
|
||||
</div>
|
||||
</Teleport>
|
||||
</Overflow>
|
||||
</Overflow>,
|
||||
);
|
||||
};
|
||||
},
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import type { ComputedRef, InjectionKey } from 'vue';
|
||||
import { provide, computed, inject } from 'vue';
|
||||
import type { MenuProps } from './menu';
|
||||
|
||||
// Used for Dropdown only
|
||||
export interface OverrideContextProps {
|
||||
prefixCls?: ComputedRef<string>;
|
||||
mode?: ComputedRef<MenuProps['mode']>;
|
||||
selectable?: ComputedRef<boolean>;
|
||||
validator?: (menuProps: Pick<MenuProps, 'mode'>) => void;
|
||||
onClick?: () => void;
|
||||
}
|
||||
export const OverrideContextKey: InjectionKey<OverrideContextProps> = Symbol('OverrideContextKey');
|
||||
export const useInjectOverride = () => {
|
||||
return inject(OverrideContextKey, undefined);
|
||||
};
|
||||
|
||||
export const useProvideOverride = (props: OverrideContextProps) => {
|
||||
const { prefixCls, mode, selectable, validator, onClick } = useInjectOverride() || {};
|
||||
provide(OverrideContextKey, {
|
||||
prefixCls: computed(() => (props.prefixCls?.value ?? prefixCls?.value) as string),
|
||||
mode: computed(() => props.mode?.value ?? mode?.value),
|
||||
selectable: computed(() => (props.selectable?.value ?? selectable?.value) as boolean),
|
||||
validator: props.validator ?? validator,
|
||||
onClick: props.onClick ?? onClick,
|
||||
});
|
||||
};
|
|
@ -93,7 +93,6 @@ export default defineComponent({
|
|||
changeActiveKeys,
|
||||
mode,
|
||||
inlineCollapsed,
|
||||
antdMenuTheme,
|
||||
openKeys,
|
||||
overflowDisabled,
|
||||
onOpenChange,
|
||||
|
@ -101,6 +100,7 @@ export default defineComponent({
|
|||
unRegisterMenuInfo,
|
||||
selectedSubMenuKeys,
|
||||
expandIcon: menuExpandIcon,
|
||||
theme,
|
||||
} = useInjectMenu();
|
||||
|
||||
const hasKey = vnodeKey !== undefined && vnodeKey !== null;
|
||||
|
@ -196,7 +196,7 @@ export default defineComponent({
|
|||
const popupClassName = computed(() =>
|
||||
classNames(
|
||||
prefixCls.value,
|
||||
`${prefixCls.value}-${props.theme || antdMenuTheme.value}`,
|
||||
`${prefixCls.value}-${props.theme || theme.value}`,
|
||||
props.popupClassName,
|
||||
),
|
||||
);
|
||||
|
@ -279,13 +279,14 @@ export default defineComponent({
|
|||
const subMenuPrefixClsValue = subMenuPrefixCls.value;
|
||||
let titleNode = () => null;
|
||||
if (!overflowDisabled.value && mode.value !== 'inline') {
|
||||
const popupOffset = mode.value === 'horizontal' ? [0, 8] : [10, 0];
|
||||
titleNode = () => (
|
||||
<PopupTrigger
|
||||
mode={triggerModeRef.value}
|
||||
prefixCls={subMenuPrefixClsValue}
|
||||
visible={!props.internalPopupClose && open.value}
|
||||
popupClassName={popupClassName.value}
|
||||
popupOffset={props.popupOffset}
|
||||
popupOffset={props.popupOffset || popupOffset}
|
||||
disabled={mergedDisabled.value}
|
||||
onVisibleChange={onPopupVisibleChange}
|
||||
v-slots={{
|
||||
|
|
|
@ -13,24 +13,24 @@ import { ref, shallowRef, watch } from 'vue';
|
|||
import type { MenuProps } from '../Menu';
|
||||
import type { StoreMenuInfo } from './useMenuContext';
|
||||
|
||||
interface MenuItemType extends VcMenuItemType {
|
||||
export interface MenuItemType extends VcMenuItemType {
|
||||
danger?: boolean;
|
||||
icon?: any;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
interface SubMenuType extends Omit<VcSubMenuType, 'children'> {
|
||||
export interface SubMenuType extends Omit<VcSubMenuType, 'children'> {
|
||||
icon?: any;
|
||||
theme?: 'dark' | 'light';
|
||||
children: ItemType[];
|
||||
}
|
||||
|
||||
interface MenuItemGroupType extends Omit<VcMenuItemGroupType, 'children'> {
|
||||
export interface MenuItemGroupType extends Omit<VcMenuItemGroupType, 'children'> {
|
||||
children?: MenuItemType[];
|
||||
key?: Key;
|
||||
}
|
||||
|
||||
interface MenuDividerType extends VcMenuDividerType {
|
||||
export interface MenuDividerType extends VcMenuDividerType {
|
||||
dashed?: boolean;
|
||||
key?: Key;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ export interface MenuContextProps {
|
|||
rtl?: ComputedRef<boolean>;
|
||||
|
||||
inlineCollapsed: Ref<boolean>;
|
||||
antdMenuTheme?: ComputedRef<MenuTheme>;
|
||||
theme?: ComputedRef<MenuTheme>;
|
||||
|
||||
siderCollapsed?: ComputedRef<boolean>;
|
||||
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
.accessibility-focus-dark() {
|
||||
box-shadow: 0 0 0 2px @primary-7;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls} {
|
||||
&&-root:focus-visible {
|
||||
.accessibility-focus-dark();
|
||||
}
|
||||
|
||||
&-dark &-item,
|
||||
&-dark &-submenu-title {
|
||||
&:focus-visible {
|
||||
.accessibility-focus-dark();
|
||||
}
|
||||
}
|
||||
|
||||
// dark theme
|
||||
&&-dark,
|
||||
&-dark &-sub,
|
||||
&&-dark &-sub {
|
||||
color: @menu-dark-color;
|
||||
background: @menu-dark-bg;
|
||||
.@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
|
||||
opacity: 0.45;
|
||||
transition: all 0.3s;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
background: @menu-dark-arrow-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-submenu-popup {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&-dark &-inline&-sub {
|
||||
background: @menu-dark-inline-submenu-bg;
|
||||
}
|
||||
|
||||
&-dark&-horizontal {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&-dark&-horizontal > &-item,
|
||||
&-dark&-horizontal > &-submenu {
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
padding: @menu-item-padding;
|
||||
border-color: @menu-dark-bg;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&-dark&-horizontal > &-item:hover {
|
||||
background-color: @menu-dark-item-active-bg;
|
||||
}
|
||||
|
||||
&-dark&-horizontal > &-item > a::before {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&-dark &-item,
|
||||
&-dark &-item-group-title,
|
||||
&-dark &-item > a,
|
||||
&-dark &-item > span > a {
|
||||
color: @menu-dark-color;
|
||||
}
|
||||
|
||||
&-dark&-inline,
|
||||
&-dark&-vertical,
|
||||
&-dark&-vertical-left,
|
||||
&-dark&-vertical-right {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&-dark&-inline &-item,
|
||||
&-dark&-vertical &-item,
|
||||
&-dark&-vertical-left &-item,
|
||||
&-dark&-vertical-right &-item {
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-inline &-item,
|
||||
&-dark&-inline &-submenu-title {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-dark &-item:hover,
|
||||
&-dark &-item-active,
|
||||
&-dark &-submenu-active,
|
||||
&-dark &-submenu-open,
|
||||
&-dark &-submenu-selected,
|
||||
&-dark &-submenu-title:hover {
|
||||
color: @menu-dark-highlight-color;
|
||||
background-color: transparent;
|
||||
|
||||
> a,
|
||||
> span > a {
|
||||
color: @menu-dark-highlight-color;
|
||||
}
|
||||
> .@{menu-prefix-cls}-submenu-title {
|
||||
> .@{menu-prefix-cls}-submenu-arrow {
|
||||
opacity: 1;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
background: @menu-dark-highlight-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-dark &-item:hover {
|
||||
background-color: @menu-dark-item-hover-bg;
|
||||
}
|
||||
|
||||
&-dark&-dark:not(&-horizontal) &-item-selected {
|
||||
background-color: @menu-dark-item-active-bg;
|
||||
}
|
||||
|
||||
&-dark &-item-selected {
|
||||
color: @menu-dark-highlight-color;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
> a,
|
||||
> span > a,
|
||||
> a:hover,
|
||||
> span > a:hover {
|
||||
color: @menu-dark-highlight-color;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
color: @menu-dark-selected-item-icon-color;
|
||||
|
||||
+ span {
|
||||
color: @menu-dark-selected-item-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&&-dark &-item-selected,
|
||||
&-submenu-popup&-dark &-item-selected {
|
||||
background-color: @menu-dark-item-active-bg;
|
||||
}
|
||||
|
||||
// Disabled state sets text to dark gray and nukes hover/tab effects
|
||||
&-dark &-item-disabled,
|
||||
&-dark &-submenu-disabled {
|
||||
&,
|
||||
> a,
|
||||
> span > a {
|
||||
color: @disabled-color-dark !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
> .@{menu-prefix-cls}-submenu-title {
|
||||
color: @disabled-color-dark !important;
|
||||
> .@{menu-prefix-cls}-submenu-arrow {
|
||||
&::before,
|
||||
&::after {
|
||||
background: @disabled-color-dark !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
import type { MenuToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
|
||||
const getHorizontalStyle: GenerateStyle<MenuToken> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
motionDurationSlow,
|
||||
menuHorizontalHeight,
|
||||
colorSplit,
|
||||
lineWidth,
|
||||
lineType,
|
||||
menuItemPaddingInline,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-horizontal`]: {
|
||||
lineHeight: `${menuHorizontalHeight}px`,
|
||||
border: 0,
|
||||
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
|
||||
boxShadow: 'none',
|
||||
|
||||
'&::after': {
|
||||
display: 'block',
|
||||
clear: 'both',
|
||||
height: 0,
|
||||
content: '"\\20"',
|
||||
},
|
||||
|
||||
// ======================= Item =======================
|
||||
[`${componentCls}-item, ${componentCls}-submenu`]: {
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'bottom',
|
||||
paddingInline: menuItemPaddingInline,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item:hover,
|
||||
> ${componentCls}-item-active,
|
||||
> ${componentCls}-submenu ${componentCls}-submenu-title:hover`]: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
transition: [`border-color ${motionDurationSlow}`, `background ${motionDurationSlow}`].join(
|
||||
',',
|
||||
),
|
||||
},
|
||||
|
||||
// ===================== Sub Menu =====================
|
||||
[`${componentCls}-submenu-arrow`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default getHorizontalStyle;
|
|
@ -1,700 +0,0 @@
|
|||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
@import './status';
|
||||
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
@menu-animation-duration-normal: 0.15s;
|
||||
|
||||
.accessibility-focus() {
|
||||
box-shadow: 0 0 0 2px @primary-2;
|
||||
}
|
||||
|
||||
// TODO: Should remove icon style compatible in v5
|
||||
|
||||
// default theme
|
||||
.@{menu-prefix-cls} {
|
||||
.reset-component();
|
||||
|
||||
margin-bottom: 0;
|
||||
padding-left: 0; // Override default ul/ol
|
||||
color: @menu-item-color;
|
||||
font-size: @menu-item-font-size;
|
||||
line-height: 0; // Fix display inline-block gap
|
||||
text-align: left;
|
||||
list-style: none;
|
||||
background: @menu-bg;
|
||||
outline: none;
|
||||
box-shadow: @box-shadow-base;
|
||||
transition: background @animation-duration-slow,
|
||||
width @animation-duration-slow cubic-bezier(0.2, 0, 0, 1) 0s;
|
||||
.clearfix();
|
||||
|
||||
&&-root:focus-visible {
|
||||
.accessibility-focus();
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
// Overflow ellipsis
|
||||
&-overflow {
|
||||
display: flex;
|
||||
|
||||
&-item {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-hidden,
|
||||
&-submenu-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-item-group-title {
|
||||
height: @menu-item-group-height;
|
||||
padding: 8px 16px;
|
||||
color: @menu-item-group-title-color;
|
||||
font-size: @menu-item-group-title-font-size;
|
||||
line-height: @menu-item-group-height;
|
||||
transition: all @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-horizontal &-submenu {
|
||||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
background @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-submenu,
|
||||
&-submenu-inline {
|
||||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
background @animation-duration-slow @ease-in-out,
|
||||
padding @menu-animation-duration-normal @ease-in-out;
|
||||
}
|
||||
|
||||
&-submenu-selected {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&-item:active,
|
||||
&-submenu-title:active {
|
||||
background: @menu-item-active-bg;
|
||||
}
|
||||
|
||||
&-submenu &-sub {
|
||||
cursor: initial;
|
||||
transition: background @animation-duration-slow @ease-in-out,
|
||||
padding @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-title-content {
|
||||
transition: color @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-item a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: transparent;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/19809
|
||||
&-item > .@{ant-prefix}-badge a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-item-divider {
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
border-color: @border-color-split;
|
||||
border-style: solid;
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
|
||||
&-item-divider-dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
&-horizontal &-item,
|
||||
&-horizontal &-submenu {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
&-horizontal > &-item:hover,
|
||||
&-horizontal > &-item-active,
|
||||
&-horizontal > &-submenu &-submenu-title:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&-item-selected {
|
||||
color: @menu-highlight-color;
|
||||
|
||||
a,
|
||||
a:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(&-horizontal) &-item-selected {
|
||||
background-color: @menu-item-active-bg;
|
||||
}
|
||||
|
||||
&-inline,
|
||||
&-vertical,
|
||||
&-vertical-left {
|
||||
border-right: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
|
||||
&-vertical-right {
|
||||
border-left: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
|
||||
&-vertical&-sub,
|
||||
&-vertical-left&-sub,
|
||||
&-vertical-right&-sub {
|
||||
min-width: 160px;
|
||||
max-height: calc(100vh - 100px);
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-right: 0;
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22244
|
||||
// https://github.com/ant-design/ant-design/issues/26812
|
||||
&:not([class*='-active']) {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item {
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
border-right: 0;
|
||||
|
||||
&::after {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-submenu {
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal&-sub {
|
||||
min-width: 114px; // in case of submenu width is too big: https://codesandbox.io/s/qvpwm6mk66
|
||||
}
|
||||
|
||||
&-horizontal &-item,
|
||||
&-horizontal &-submenu-title {
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-item,
|
||||
&-submenu-title {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: @menu-item-padding;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow,
|
||||
padding @animation-duration-slow @ease-in-out;
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
min-width: 14px;
|
||||
font-size: @menu-icon-size;
|
||||
transition: font-size @menu-animation-duration-normal @ease-out,
|
||||
margin @animation-duration-slow @ease-in-out, color @animation-duration-slow;
|
||||
|
||||
+ span {
|
||||
margin-left: @menu-icon-margin-right;
|
||||
opacity: 1;
|
||||
transition: opacity @animation-duration-slow @ease-in-out, margin @animation-duration-slow,
|
||||
color @animation-duration-slow;
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-icon.svg {
|
||||
vertical-align: -0.125em;
|
||||
}
|
||||
|
||||
&.@{menu-prefix-cls}-item-only-child {
|
||||
> .@{iconfont-css-prefix},
|
||||
> .@{menu-prefix-cls}-item-icon {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
.accessibility-focus();
|
||||
}
|
||||
}
|
||||
|
||||
& > &-item-divider {
|
||||
margin: 1px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-submenu {
|
||||
&-popup {
|
||||
position: absolute;
|
||||
z-index: @zindex-dropdown;
|
||||
background: transparent;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: none;
|
||||
transform-origin: 0 0;
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/13955
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.0001;
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/13955
|
||||
&-placement-rightTop::before {
|
||||
top: 0;
|
||||
left: -7px;
|
||||
}
|
||||
|
||||
> .@{menu-prefix-cls} {
|
||||
background-color: @menu-bg;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
&-submenu-title::after {
|
||||
transition: transform @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&-popup > .@{menu-prefix-cls} {
|
||||
background-color: @menu-popup-bg;
|
||||
}
|
||||
|
||||
&-expand-icon,
|
||||
&-arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 16px;
|
||||
width: 10px;
|
||||
color: @menu-item-color;
|
||||
transform: translateY(-50%);
|
||||
transition: transform @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-arrow {
|
||||
// →
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 1.5px;
|
||||
background-color: currentcolor;
|
||||
border-radius: 2px;
|
||||
transition: background @animation-duration-slow @ease-in-out,
|
||||
transform @animation-duration-slow @ease-in-out, top @animation-duration-slow @ease-in-out,
|
||||
color @animation-duration-slow @ease-in-out;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::before {
|
||||
transform: rotate(45deg) translateY(-2.5px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
transform: rotate(-45deg) translateY(2.5px);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover > &-title > &-expand-icon,
|
||||
&:hover > &-title > &-arrow {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-inline-collapsed &-arrow,
|
||||
&-inline &-arrow {
|
||||
// ↓
|
||||
&::before {
|
||||
transform: rotate(-45deg) translateX(2.5px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
transform: rotate(45deg) translateX(-2.5px);
|
||||
}
|
||||
}
|
||||
|
||||
&-horizontal &-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-open&-inline > &-title > &-arrow {
|
||||
// ↑
|
||||
transform: translateY(-2px);
|
||||
|
||||
&::after {
|
||||
transform: rotate(-45deg) translateX(-2.5px);
|
||||
}
|
||||
|
||||
&::before {
|
||||
transform: rotate(45deg) translateX(2.5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical &-submenu-selected,
|
||||
&-vertical-left &-submenu-selected,
|
||||
&-vertical-right &-submenu-selected {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&-horizontal {
|
||||
line-height: @menu-horizontal-line-height;
|
||||
border: 0;
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
box-shadow: none;
|
||||
|
||||
&:not(.@{menu-prefix-cls}-dark) {
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-submenu {
|
||||
margin-top: -1px;
|
||||
margin-bottom: 0;
|
||||
padding: @menu-item-padding;
|
||||
|
||||
&:hover,
|
||||
&-active,
|
||||
&-open,
|
||||
&-selected {
|
||||
color: @menu-highlight-color;
|
||||
|
||||
&::after {
|
||||
border-bottom: 2px solid @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-submenu {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
right: @menu-item-padding-horizontal;
|
||||
bottom: 0;
|
||||
left: @menu-item-padding-horizontal;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: border-color @animation-duration-slow @ease-in-out;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
> .@{menu-prefix-cls}-submenu > .@{menu-prefix-cls}-submenu-title {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> .@{menu-prefix-cls}-item {
|
||||
a {
|
||||
color: @menu-item-color;
|
||||
|
||||
&:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
&::before {
|
||||
bottom: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
&-selected a {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
clear: both;
|
||||
height: 0;
|
||||
content: '\20';
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical,
|
||||
&-vertical-left,
|
||||
&-vertical-right,
|
||||
&-inline {
|
||||
.@{menu-prefix-cls}-item {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-right: @menu-item-active-border-width solid @menu-highlight-color;
|
||||
transform: scaleY(0.0001);
|
||||
opacity: 0;
|
||||
transition: transform @menu-animation-duration-normal @ease-out,
|
||||
opacity @menu-animation-duration-normal @ease-out;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
height: @menu-item-height;
|
||||
margin-top: @menu-item-vertical-margin;
|
||||
margin-bottom: @menu-item-vertical-margin;
|
||||
padding: 0 16px;
|
||||
overflow: hidden;
|
||||
line-height: @menu-item-height;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// disable margin collapsed
|
||||
.@{menu-prefix-cls}-submenu {
|
||||
padding-bottom: 0.02px;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item:not(:last-child) {
|
||||
margin-bottom: @menu-item-boundary-margin;
|
||||
}
|
||||
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-submenu > .@{menu-prefix-cls}-submenu-title {
|
||||
height: @menu-inline-toplevel-item-height;
|
||||
line-height: @menu-inline-toplevel-item-height;
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical {
|
||||
.@{menu-prefix-cls}-item-group-list .@{menu-prefix-cls}-submenu-title,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
padding-right: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
&-inline {
|
||||
width: 100%;
|
||||
.@{menu-prefix-cls}-selected,
|
||||
.@{menu-prefix-cls}-item-selected {
|
||||
&::after {
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
transition: transform @menu-animation-duration-normal @ease-in-out,
|
||||
opacity @menu-animation-duration-normal @ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
width: ~'calc(100% + 1px)';
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-group-list .@{menu-prefix-cls}-submenu-title,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
// Motion enhance for first level
|
||||
&.@{menu-prefix-cls}-root {
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow,
|
||||
padding 0.1s @ease-out;
|
||||
|
||||
> .@{menu-prefix-cls}-title-content {
|
||||
flex: auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&&-inline-collapsed {
|
||||
width: @menu-collapsed-width;
|
||||
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-item-group
|
||||
> .@{menu-prefix-cls}-item-group-list
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-item-group
|
||||
> .@{menu-prefix-cls}-item-group-list
|
||||
> .@{menu-prefix-cls}-submenu
|
||||
> .@{menu-prefix-cls}-submenu-title,
|
||||
> .@{menu-prefix-cls}-submenu > .@{menu-prefix-cls}-submenu-title {
|
||||
left: 0;
|
||||
padding: 0 ~'calc(50% - @{menu-icon-size-lg} / 2)';
|
||||
text-overflow: clip;
|
||||
|
||||
.@{menu-prefix-cls}-submenu-arrow {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
margin: 0;
|
||||
font-size: @menu-icon-size-lg;
|
||||
line-height: @menu-item-height;
|
||||
|
||||
+ span {
|
||||
display: inline-block;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-tooltip {
|
||||
pointer-events: none;
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @text-color-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-group-title {
|
||||
padding-right: 4px;
|
||||
padding-left: 4px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
&-item-group-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
padding: 0 16px 0 28px;
|
||||
}
|
||||
}
|
||||
|
||||
&-root&-vertical,
|
||||
&-root&-vertical-left,
|
||||
&-root&-vertical-right,
|
||||
&-root&-inline {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&-root&-inline-collapsed {
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu .@{menu-prefix-cls}-submenu-title {
|
||||
> .@{menu-prefix-cls}-inline-collapsed-noicon {
|
||||
font-size: @menu-icon-size-lg;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-sub&-inline {
|
||||
padding: 0;
|
||||
background: @menu-inline-submenu-bg;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
& > .@{menu-prefix-cls}-item,
|
||||
& > .@{menu-prefix-cls}-submenu > .@{menu-prefix-cls}-submenu-title {
|
||||
height: @menu-item-height;
|
||||
line-height: @menu-item-height;
|
||||
list-style-position: inside;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
& .@{menu-prefix-cls}-item-group-title {
|
||||
padding-left: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled state sets text to gray and nukes hover/tab effects
|
||||
&-item-disabled,
|
||||
&-submenu-disabled {
|
||||
color: @disabled-color !important;
|
||||
background: none;
|
||||
cursor: not-allowed;
|
||||
|
||||
&::after {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @disabled-color !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
> .@{menu-prefix-cls}-submenu-title {
|
||||
color: @disabled-color !important;
|
||||
cursor: not-allowed;
|
||||
> .@{menu-prefix-cls}-submenu-arrow {
|
||||
&::before,
|
||||
&::after {
|
||||
background: @disabled-color !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Integration with header element so menu items have the same height
|
||||
.@{ant-prefix}-layout-header {
|
||||
.@{menu-prefix-cls} {
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/32950
|
||||
.@{ant-prefix}-menu-inline-collapsed-tooltip {
|
||||
a,
|
||||
a:hover {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
|
||||
@import './light';
|
||||
@import './dark';
|
||||
@import './rtl';
|
|
@ -0,0 +1,581 @@
|
|||
import { TinyColor } from '@ctrl/tinycolor';
|
||||
import type { CSSObject } from '../../_util/cssinjs';
|
||||
import { genCollapseMotion, initSlideMotion, initZoomMotion } from '../../_style/motion';
|
||||
import type { FullToken, GenerateStyle, UseComponentStyleResult } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import getHorizontalStyle from './horizontal';
|
||||
import getRTLStyle from './rtl';
|
||||
import getThemeStyle from './theme';
|
||||
import getVerticalStyle from './vertical';
|
||||
import { clearFix, resetComponent, resetIcon } from '../../_style';
|
||||
import { Ref } from 'vue';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
dropdownWidth: number;
|
||||
zIndexPopup: number;
|
||||
|
||||
// Group
|
||||
colorGroupTitle: string;
|
||||
|
||||
// radius
|
||||
radiusItem: number;
|
||||
radiusSubMenuItem: number;
|
||||
|
||||
// Item Text
|
||||
// > Default
|
||||
colorItemText: string;
|
||||
colorItemTextHover: string;
|
||||
colorItemTextHoverHorizontal: string;
|
||||
colorItemTextSelected: string;
|
||||
colorItemTextSelectedHorizontal: string;
|
||||
|
||||
// > Disabled
|
||||
colorItemTextDisabled: string;
|
||||
|
||||
// > Danger
|
||||
colorDangerItemText: string;
|
||||
colorDangerItemTextHover: string;
|
||||
colorDangerItemTextSelected: string;
|
||||
colorDangerItemBgActive: string;
|
||||
colorDangerItemBgSelected: string;
|
||||
|
||||
// Item Bg
|
||||
colorItemBg: string;
|
||||
colorItemBgHover: string;
|
||||
colorSubItemBg: string;
|
||||
|
||||
// > Default
|
||||
colorItemBgActive: string;
|
||||
colorItemBgSelected: string;
|
||||
colorItemBgSelectedHorizontal: string;
|
||||
|
||||
// Ink Bar
|
||||
colorActiveBarWidth: number;
|
||||
colorActiveBarHeight: number;
|
||||
colorActiveBarBorderSize: number;
|
||||
|
||||
itemMarginInline: number;
|
||||
}
|
||||
|
||||
export interface MenuToken extends FullToken<'Menu'> {
|
||||
menuItemHeight: number;
|
||||
menuHorizontalHeight: number;
|
||||
menuItemPaddingInline: number;
|
||||
menuArrowSize: number;
|
||||
menuArrowOffset: string;
|
||||
menuPanelMaskInset: number;
|
||||
menuSubMenuBg: string;
|
||||
}
|
||||
|
||||
const genMenuItemStyle = (token: MenuToken): CSSObject => {
|
||||
const {
|
||||
componentCls,
|
||||
fontSize,
|
||||
motionDurationSlow,
|
||||
motionDurationMid,
|
||||
motionEaseInOut,
|
||||
motionEaseOut,
|
||||
iconCls,
|
||||
controlHeightSM,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
// >>>>> Item
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
margin: 0,
|
||||
whiteSpace: 'nowrap',
|
||||
cursor: 'pointer',
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow}`,
|
||||
`background ${motionDurationSlow}`,
|
||||
`padding ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
|
||||
[`${componentCls}-item-icon, ${iconCls}`]: {
|
||||
minWidth: fontSize,
|
||||
fontSize,
|
||||
transition: [
|
||||
`font-size ${motionDurationMid} ${motionEaseOut}`,
|
||||
`margin ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`color ${motionDurationSlow}`,
|
||||
].join(','),
|
||||
|
||||
'+ span': {
|
||||
marginInlineStart: controlHeightSM - fontSize,
|
||||
opacity: 1,
|
||||
transition: [
|
||||
`opacity ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`margin ${motionDurationSlow}`,
|
||||
`color ${motionDurationSlow}`,
|
||||
].join(','),
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item-icon`]: {
|
||||
...resetIcon(),
|
||||
},
|
||||
|
||||
[`&${componentCls}-item-only-child`]: {
|
||||
[`> ${iconCls}, > ${componentCls}-item-icon`]: {
|
||||
marginInlineEnd: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Disabled state sets text to gray and nukes hover/tab effects
|
||||
[`${componentCls}-item-disabled, ${componentCls}-submenu-disabled`]: {
|
||||
background: 'none !important',
|
||||
cursor: 'not-allowed',
|
||||
|
||||
'&::after': {
|
||||
borderColor: 'transparent !important',
|
||||
},
|
||||
|
||||
a: {
|
||||
color: 'inherit !important',
|
||||
},
|
||||
|
||||
[`> ${componentCls}-submenu-title`]: {
|
||||
color: 'inherit !important',
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genSubMenuArrowStyle = (token: MenuToken): CSSObject => {
|
||||
const {
|
||||
componentCls,
|
||||
motionDurationSlow,
|
||||
motionEaseInOut,
|
||||
borderRadius,
|
||||
menuArrowSize,
|
||||
menuArrowOffset,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-submenu`]: {
|
||||
[`&-expand-icon, &-arrow`]: {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
insetInlineEnd: token.margin,
|
||||
width: menuArrowSize,
|
||||
color: 'currentcolor',
|
||||
transform: 'translateY(-50%)',
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseInOut}, opacity ${motionDurationSlow}`,
|
||||
},
|
||||
|
||||
'&-arrow': {
|
||||
// →
|
||||
'&::before, &::after': {
|
||||
position: 'absolute',
|
||||
width: menuArrowSize * 0.6,
|
||||
height: menuArrowSize * 0.15,
|
||||
backgroundColor: 'currentcolor',
|
||||
borderRadius,
|
||||
transition: [
|
||||
`background ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`transform ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`top ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`color ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
content: '""',
|
||||
},
|
||||
|
||||
'&::before': {
|
||||
transform: `rotate(45deg) translateY(-${menuArrowOffset})`,
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
transform: `rotate(-45deg) translateY(${menuArrowOffset})`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// =============================== Base ===============================
|
||||
const getBaseStyle: GenerateStyle<MenuToken> = token => {
|
||||
const {
|
||||
antCls,
|
||||
componentCls,
|
||||
fontSize,
|
||||
motionDurationSlow,
|
||||
motionDurationMid,
|
||||
motionEaseInOut,
|
||||
lineHeight,
|
||||
paddingXS,
|
||||
padding,
|
||||
colorSplit,
|
||||
lineWidth,
|
||||
zIndexPopup,
|
||||
borderRadiusLG,
|
||||
radiusSubMenuItem,
|
||||
menuArrowSize,
|
||||
menuArrowOffset,
|
||||
lineType,
|
||||
menuPanelMaskInset,
|
||||
} = token;
|
||||
|
||||
return [
|
||||
// Misc
|
||||
{
|
||||
'': {
|
||||
[`${componentCls}`]: {
|
||||
...clearFix(),
|
||||
|
||||
// Hidden
|
||||
[`&-hidden`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`${componentCls}-submenu-hidden`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
{
|
||||
[componentCls]: {
|
||||
...resetComponent(token),
|
||||
...clearFix(),
|
||||
|
||||
marginBottom: 0,
|
||||
paddingInlineStart: 0, // Override default ul/ol
|
||||
fontSize,
|
||||
lineHeight: 0, // Fix display inline-block gap
|
||||
listStyle: 'none',
|
||||
outline: 'none',
|
||||
transition: [
|
||||
`background ${motionDurationSlow}`,
|
||||
// Magic cubic here but smooth transition
|
||||
`width ${motionDurationSlow} cubic-bezier(0.2, 0, 0, 1) 0s`,
|
||||
].join(','),
|
||||
|
||||
[`ul, ol`]: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
listStyle: 'none',
|
||||
},
|
||||
|
||||
// Overflow ellipsis
|
||||
[`&-overflow`]: {
|
||||
display: 'flex',
|
||||
|
||||
[`${componentCls}-item`]: {
|
||||
flex: 'none',
|
||||
},
|
||||
},
|
||||
[`${componentCls}-item, ${componentCls}-submenu, ${componentCls}-submenu-title`]: {
|
||||
borderRadius: token.radiusItem,
|
||||
},
|
||||
|
||||
[`${componentCls}-item-group-title`]: {
|
||||
padding: `${paddingXS}px ${padding}px`,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
},
|
||||
|
||||
[`&-horizontal ${componentCls}-submenu`]: {
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`background ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu, ${componentCls}-submenu-inline`]: {
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`background ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`padding ${motionDurationMid} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu ${componentCls}-sub`]: {
|
||||
cursor: 'initial',
|
||||
transition: [
|
||||
`background ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`padding ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
},
|
||||
|
||||
[`${componentCls}-title-content`]: {
|
||||
transition: `color ${motionDurationSlow}`,
|
||||
},
|
||||
|
||||
[`${componentCls}-item a`]: {
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
backgroundColor: 'transparent',
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
|
||||
// Removed a Badge related style seems it's safe
|
||||
// https://github.com/ant-design/ant-design/issues/19809
|
||||
|
||||
// >>>>> Divider
|
||||
[`${componentCls}-item-divider`]: {
|
||||
overflow: 'hidden',
|
||||
lineHeight: 0,
|
||||
borderColor: colorSplit,
|
||||
borderStyle: lineType,
|
||||
borderWidth: 0,
|
||||
borderTopWidth: lineWidth,
|
||||
marginBlock: lineWidth,
|
||||
padding: 0,
|
||||
|
||||
'&-dashed': {
|
||||
borderStyle: 'dashed',
|
||||
},
|
||||
},
|
||||
|
||||
// Item
|
||||
...genMenuItemStyle(token),
|
||||
|
||||
[`${componentCls}-item-group`]: {
|
||||
[`${componentCls}-item-group-list`]: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
paddingInline: `${fontSize * 2}px ${padding}px`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ======================= Sub Menu =======================
|
||||
'&-submenu': {
|
||||
'&-popup': {
|
||||
position: 'absolute',
|
||||
zIndex: zIndexPopup,
|
||||
background: 'transparent',
|
||||
borderRadius: borderRadiusLG,
|
||||
boxShadow: 'none',
|
||||
transformOrigin: '0 0',
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/13955
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
inset: `${menuPanelMaskInset}px 0 0`,
|
||||
zIndex: -1,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
opacity: 0,
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/13955
|
||||
'&-placement-rightTop::before': {
|
||||
top: 0,
|
||||
insetInlineStart: menuPanelMaskInset,
|
||||
},
|
||||
|
||||
[`> ${componentCls}`]: {
|
||||
borderRadius: borderRadiusLG,
|
||||
|
||||
...genMenuItemStyle(token),
|
||||
...genSubMenuArrowStyle(token),
|
||||
|
||||
[`${componentCls}-item, ${componentCls}-submenu > ${componentCls}-submenu-title`]: {
|
||||
borderRadius: radiusSubMenuItem,
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-title::after`]: {
|
||||
transition: `transform ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
...genSubMenuArrowStyle(token),
|
||||
|
||||
[`&-inline-collapsed ${componentCls}-submenu-arrow,
|
||||
&-inline ${componentCls}-submenu-arrow`]: {
|
||||
// ↓
|
||||
'&::before': {
|
||||
transform: `rotate(-45deg) translateX(${menuArrowOffset})`,
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
transform: `rotate(45deg) translateX(-${menuArrowOffset})`,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-open${componentCls}-submenu-inline > ${componentCls}-submenu-title > ${componentCls}-submenu-arrow`]:
|
||||
{
|
||||
// ↑
|
||||
transform: `translateY(-${menuArrowSize * 0.2}px)`,
|
||||
|
||||
'&::after': {
|
||||
transform: `rotate(-45deg) translateX(-${menuArrowOffset})`,
|
||||
},
|
||||
|
||||
'&::before': {
|
||||
transform: `rotate(45deg) translateX(${menuArrowOffset})`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Integration with header element so menu items have the same height
|
||||
{
|
||||
[`${antCls}-layout-header`]: {
|
||||
[componentCls]: {
|
||||
lineHeight: 'inherit',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default (prefixCls: Ref<string>, injectStyle: Ref<boolean>): UseComponentStyleResult => {
|
||||
const useOriginHook = genComponentStyleHook(
|
||||
'Menu',
|
||||
(token, { overrideComponentToken }) => {
|
||||
// Dropdown will handle menu style self. We do not need to handle this.
|
||||
if (injectStyle.value === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { colorBgElevated, colorPrimary, colorError, colorErrorHover, colorTextLightSolid } =
|
||||
token;
|
||||
|
||||
const { controlHeightLG, fontSize } = token;
|
||||
|
||||
const menuArrowSize = (fontSize / 7) * 5;
|
||||
|
||||
// Menu Token
|
||||
const menuToken = mergeToken<MenuToken>(token, {
|
||||
menuItemHeight: controlHeightLG,
|
||||
menuItemPaddingInline: token.margin,
|
||||
menuArrowSize,
|
||||
menuHorizontalHeight: controlHeightLG * 1.15,
|
||||
menuArrowOffset: `${menuArrowSize * 0.25}px`,
|
||||
menuPanelMaskInset: -7, // Still a hardcode here since it's offset by rc-align
|
||||
menuSubMenuBg: colorBgElevated,
|
||||
});
|
||||
|
||||
const colorTextDark = new TinyColor(colorTextLightSolid).setAlpha(0.65).toRgbString();
|
||||
|
||||
const menuDarkToken = mergeToken<MenuToken>(
|
||||
menuToken,
|
||||
{
|
||||
colorItemText: colorTextDark,
|
||||
colorItemTextHover: colorTextLightSolid,
|
||||
colorGroupTitle: colorTextDark,
|
||||
colorItemTextSelected: colorTextLightSolid,
|
||||
colorItemBg: '#001529',
|
||||
colorSubItemBg: '#000c17',
|
||||
colorItemBgActive: 'transparent',
|
||||
colorItemBgSelected: colorPrimary,
|
||||
colorActiveBarWidth: 0,
|
||||
colorActiveBarHeight: 0,
|
||||
colorActiveBarBorderSize: 0,
|
||||
|
||||
// Disabled
|
||||
colorItemTextDisabled: new TinyColor(colorTextLightSolid).setAlpha(0.25).toRgbString(),
|
||||
|
||||
// Danger
|
||||
colorDangerItemText: colorError,
|
||||
colorDangerItemTextHover: colorErrorHover,
|
||||
colorDangerItemTextSelected: colorTextLightSolid,
|
||||
colorDangerItemBgActive: colorError,
|
||||
colorDangerItemBgSelected: colorError,
|
||||
|
||||
menuSubMenuBg: '#001529',
|
||||
|
||||
// Horizontal
|
||||
colorItemTextSelectedHorizontal: colorTextLightSolid,
|
||||
colorItemBgSelectedHorizontal: colorPrimary,
|
||||
},
|
||||
{
|
||||
...overrideComponentToken,
|
||||
},
|
||||
);
|
||||
|
||||
return [
|
||||
// Basic
|
||||
getBaseStyle(menuToken),
|
||||
|
||||
// Horizontal
|
||||
getHorizontalStyle(menuToken), // Hard code for some light style
|
||||
|
||||
// Vertical
|
||||
getVerticalStyle(menuToken), // Hard code for some light style
|
||||
|
||||
// Theme
|
||||
getThemeStyle(menuToken, 'light'),
|
||||
getThemeStyle(menuDarkToken, 'dark'),
|
||||
|
||||
// RTL
|
||||
getRTLStyle(menuToken),
|
||||
|
||||
// Motion
|
||||
genCollapseMotion(menuToken),
|
||||
|
||||
initSlideMotion(menuToken, 'slide-up'),
|
||||
initSlideMotion(menuToken, 'slide-down'),
|
||||
initZoomMotion(menuToken, 'zoom-big'),
|
||||
];
|
||||
},
|
||||
token => {
|
||||
const {
|
||||
colorPrimary,
|
||||
colorError,
|
||||
colorTextDisabled,
|
||||
colorErrorBg,
|
||||
colorText,
|
||||
colorTextDescription,
|
||||
colorBgContainer,
|
||||
colorFillAlter,
|
||||
colorFillContent,
|
||||
lineWidth,
|
||||
lineWidthBold,
|
||||
controlItemBgActive,
|
||||
colorBgTextHover,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
dropdownWidth: 160,
|
||||
zIndexPopup: token.zIndexPopupBase + 50,
|
||||
radiusItem: token.borderRadiusLG,
|
||||
radiusSubMenuItem: token.borderRadiusSM,
|
||||
colorItemText: colorText,
|
||||
colorItemTextHover: colorText,
|
||||
colorItemTextHoverHorizontal: colorPrimary,
|
||||
colorGroupTitle: colorTextDescription,
|
||||
colorItemTextSelected: colorPrimary,
|
||||
colorItemTextSelectedHorizontal: colorPrimary,
|
||||
colorItemBg: colorBgContainer,
|
||||
colorItemBgHover: colorBgTextHover,
|
||||
colorItemBgActive: colorFillContent,
|
||||
colorSubItemBg: colorFillAlter,
|
||||
colorItemBgSelected: controlItemBgActive,
|
||||
colorItemBgSelectedHorizontal: 'transparent',
|
||||
colorActiveBarWidth: 0,
|
||||
colorActiveBarHeight: lineWidthBold,
|
||||
colorActiveBarBorderSize: lineWidth,
|
||||
|
||||
// Disabled
|
||||
colorItemTextDisabled: colorTextDisabled,
|
||||
|
||||
// Danger
|
||||
colorDangerItemText: colorError,
|
||||
colorDangerItemTextHover: colorError,
|
||||
colorDangerItemTextSelected: colorError,
|
||||
colorDangerItemBgActive: colorErrorBg,
|
||||
colorDangerItemBgSelected: colorErrorBg,
|
||||
|
||||
itemMarginInline: token.marginXXS,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return useOriginHook(prefixCls);
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
import '../../style/index.less';
|
||||
import './index.less';
|
||||
|
||||
// style dependencies
|
||||
// deps-lint-skip: layout
|
||||
import '../../tooltip/style';
|
|
@ -1,12 +0,0 @@
|
|||
.@{menu-prefix-cls} {
|
||||
// light theme
|
||||
&-light {
|
||||
.@{menu-prefix-cls}-item:hover,
|
||||
.@{menu-prefix-cls}-item-active,
|
||||
.@{menu-prefix-cls}:not(.@{menu-prefix-cls}-inline) .@{menu-prefix-cls}-submenu-open,
|
||||
.@{menu-prefix-cls}-submenu-active,
|
||||
.@{menu-prefix-cls}-submenu-title:hover {
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
|
||||
.@{menu-prefix-cls} {
|
||||
&&-rtl {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&-item-group-title {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&-inline,
|
||||
&-vertical {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
border-right: none;
|
||||
border-left: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-inline,
|
||||
&-dark&-vertical {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical&-sub,
|
||||
&-vertical-left&-sub,
|
||||
&-vertical-right&-sub {
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-submenu {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
transform-origin: top right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-item,
|
||||
&-submenu-title {
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
margin-right: auto;
|
||||
margin-left: @menu-icon-margin-right;
|
||||
}
|
||||
}
|
||||
|
||||
&.@{menu-prefix-cls}-item-only-child {
|
||||
> .@{menu-prefix-cls}-item-icon,
|
||||
> .@{iconfont-css-prefix} {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-submenu {
|
||||
&-rtl.@{menu-prefix-cls}-submenu-popup {
|
||||
transform-origin: 100% 0;
|
||||
}
|
||||
|
||||
&-vertical,
|
||||
&-vertical-left,
|
||||
&-vertical-right,
|
||||
&-inline {
|
||||
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical,
|
||||
&-vertical-left,
|
||||
&-vertical-right {
|
||||
> .@{menu-prefix-cls}-submenu-title .@{menu-prefix-cls}-submenu-arrow {
|
||||
&::before {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
transform: rotate(-45deg) translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
transform: rotate(45deg) translateY(2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical,
|
||||
&-vertical-left,
|
||||
&-vertical-right,
|
||||
&-inline {
|
||||
.@{menu-prefix-cls}-item {
|
||||
&::after {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-inline {
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
padding-right: 0;
|
||||
padding-left: 34px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-vertical {
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
padding-right: 16px;
|
||||
padding-left: 34px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-inline-collapsed&-vertical {
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
padding: 0 ~'calc(50% - @{menu-icon-size-lg} / 2)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-item-group-list {
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
.@{menu-prefix-cls}-rtl & {
|
||||
padding: 0 28px 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-sub&-inline {
|
||||
border: 0;
|
||||
& .@{menu-prefix-cls}-item-group-title {
|
||||
.@{menu-prefix-cls}-rtl& {
|
||||
padding-right: 32px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import type { MenuToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
|
||||
const getRTLStyle: GenerateStyle<MenuToken> = ({ componentCls, menuArrowOffset }) => ({
|
||||
[`${componentCls}-rtl`]: {
|
||||
direction: 'rtl',
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-rtl`]: {
|
||||
transformOrigin: '100% 0',
|
||||
},
|
||||
|
||||
// Vertical Arrow
|
||||
[`${componentCls}-rtl${componentCls}-vertical,
|
||||
${componentCls}-submenu-rtl ${componentCls}-vertical`]: {
|
||||
[`${componentCls}-submenu-arrow`]: {
|
||||
'&::before': {
|
||||
transform: `rotate(-45deg) translateY(-${menuArrowOffset})`,
|
||||
},
|
||||
|
||||
'&::after': {
|
||||
transform: `rotate(45deg) translateY(${menuArrowOffset})`,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default getRTLStyle;
|
|
@ -1,49 +0,0 @@
|
|||
@import (reference) '../../style/themes/index';
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
|
||||
.@{menu-prefix-cls} {
|
||||
// Danger
|
||||
&-item-danger&-item {
|
||||
color: @menu-highlight-danger-color;
|
||||
|
||||
&:hover,
|
||||
&-active {
|
||||
color: @menu-highlight-danger-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: @menu-item-active-danger-bg;
|
||||
}
|
||||
|
||||
&-selected {
|
||||
color: @menu-highlight-danger-color;
|
||||
|
||||
> a,
|
||||
> a:hover {
|
||||
color: @menu-highlight-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}:not(.@{menu-prefix-cls}-horizontal) &-selected {
|
||||
background-color: @menu-item-active-danger-bg;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-inline &::after {
|
||||
border-right-color: @menu-highlight-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Dark ====================
|
||||
&-dark &-item-danger&-item {
|
||||
&,
|
||||
&:hover,
|
||||
& > a {
|
||||
color: @menu-dark-danger-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-dark:not(&-horizontal) &-item-danger&-item-selected {
|
||||
color: @menu-dark-highlight-color;
|
||||
background-color: @menu-dark-item-active-danger-bg;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
import type { CSSInterpolation } from '../../_util/cssinjs';
|
||||
import { genFocusOutline } from '../../_style';
|
||||
import type { MenuToken } from '.';
|
||||
|
||||
const accessibilityFocus = (token: MenuToken) => ({
|
||||
...genFocusOutline(token),
|
||||
});
|
||||
|
||||
const getThemeStyle = (token: MenuToken, themeSuffix: string): CSSInterpolation => {
|
||||
const {
|
||||
componentCls,
|
||||
colorItemText,
|
||||
colorItemTextSelected,
|
||||
colorGroupTitle,
|
||||
colorItemBg,
|
||||
colorSubItemBg,
|
||||
colorItemBgSelected,
|
||||
colorActiveBarHeight,
|
||||
colorActiveBarWidth,
|
||||
colorActiveBarBorderSize,
|
||||
motionDurationSlow,
|
||||
motionEaseInOut,
|
||||
motionEaseOut,
|
||||
menuItemPaddingInline,
|
||||
motionDurationMid,
|
||||
colorItemTextHover,
|
||||
lineType,
|
||||
colorSplit,
|
||||
|
||||
// Disabled
|
||||
colorItemTextDisabled,
|
||||
|
||||
// Danger
|
||||
colorDangerItemText,
|
||||
colorDangerItemTextHover,
|
||||
colorDangerItemTextSelected,
|
||||
colorDangerItemBgActive,
|
||||
colorDangerItemBgSelected,
|
||||
|
||||
colorItemBgHover,
|
||||
menuSubMenuBg,
|
||||
|
||||
// Horizontal
|
||||
colorItemTextSelectedHorizontal,
|
||||
colorItemBgSelectedHorizontal,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-${themeSuffix}`]: {
|
||||
color: colorItemText,
|
||||
background: colorItemBg,
|
||||
|
||||
[`&${componentCls}-root:focus-visible`]: {
|
||||
...accessibilityFocus(token),
|
||||
},
|
||||
|
||||
// ======================== Item ========================
|
||||
[`${componentCls}-item-group-title`]: {
|
||||
color: colorGroupTitle,
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-selected`]: {
|
||||
[`> ${componentCls}-submenu-title`]: {
|
||||
color: colorItemTextSelected,
|
||||
},
|
||||
},
|
||||
|
||||
// Disabled
|
||||
[`${componentCls}-item-disabled, ${componentCls}-submenu-disabled`]: {
|
||||
color: `${colorItemTextDisabled} !important`,
|
||||
},
|
||||
|
||||
// Hover
|
||||
[`${componentCls}-item:hover, ${componentCls}-submenu-title:hover`]: {
|
||||
[`&:not(${componentCls}-item-selected):not(${componentCls}-submenu-selected)`]: {
|
||||
color: colorItemTextHover,
|
||||
},
|
||||
},
|
||||
|
||||
[`&:not(${componentCls}-horizontal)`]: {
|
||||
[`${componentCls}-item:not(${componentCls}-item-selected)`]: {
|
||||
'&:hover': {
|
||||
backgroundColor: colorItemBgHover,
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: colorItemBgSelected,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-title`]: {
|
||||
'&:hover': {
|
||||
backgroundColor: colorItemBgHover,
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: colorItemBgSelected,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Danger - only Item has
|
||||
[`${componentCls}-item-danger`]: {
|
||||
color: colorDangerItemText,
|
||||
|
||||
[`&${componentCls}-item:hover`]: {
|
||||
[`&:not(${componentCls}-item-selected):not(${componentCls}-submenu-selected)`]: {
|
||||
color: colorDangerItemTextHover,
|
||||
},
|
||||
},
|
||||
|
||||
[`&${componentCls}-item:active`]: {
|
||||
background: colorDangerItemBgActive,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item a`]: {
|
||||
'&, &:hover': {
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item-selected`]: {
|
||||
color: colorItemTextSelected,
|
||||
|
||||
// Danger
|
||||
[`&${componentCls}-item-danger`]: {
|
||||
color: colorDangerItemTextSelected,
|
||||
},
|
||||
|
||||
[`a, a:hover`]: {
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
|
||||
[`& ${componentCls}-item-selected`]: {
|
||||
backgroundColor: colorItemBgSelected,
|
||||
|
||||
// Danger
|
||||
[`&${componentCls}-item-danger`]: {
|
||||
backgroundColor: colorDangerItemBgSelected,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
[`&:not(${componentCls}-item-disabled):focus-visible`]: {
|
||||
...accessibilityFocus(token),
|
||||
},
|
||||
},
|
||||
|
||||
[`&${componentCls}-submenu > ${componentCls}`]: {
|
||||
backgroundColor: menuSubMenuBg,
|
||||
},
|
||||
|
||||
[`&${componentCls}-popup > ${componentCls}`]: {
|
||||
backgroundColor: colorItemBg,
|
||||
},
|
||||
|
||||
// ====================== Horizontal ======================
|
||||
[`&${componentCls}-horizontal`]: {
|
||||
...(themeSuffix === 'dark'
|
||||
? {
|
||||
borderBottom: 0,
|
||||
}
|
||||
: {}),
|
||||
|
||||
[`> ${componentCls}-item, > ${componentCls}-submenu`]: {
|
||||
top: colorActiveBarBorderSize,
|
||||
marginTop: -colorActiveBarBorderSize,
|
||||
marginBottom: 0,
|
||||
borderRadius: 0,
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
insetInline: menuItemPaddingInline,
|
||||
bottom: 0,
|
||||
borderBottom: `${colorActiveBarHeight}px solid transparent`,
|
||||
transition: `border-color ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
content: '""',
|
||||
},
|
||||
|
||||
[`&:hover, &-active, &-open`]: {
|
||||
'&::after': {
|
||||
borderBottomWidth: colorActiveBarHeight,
|
||||
borderBottomColor: colorItemTextSelectedHorizontal,
|
||||
},
|
||||
},
|
||||
[`&-selected`]: {
|
||||
color: colorItemTextSelectedHorizontal,
|
||||
backgroundColor: colorItemBgSelectedHorizontal,
|
||||
'&::after': {
|
||||
borderBottomWidth: colorActiveBarHeight,
|
||||
borderBottomColor: colorItemTextSelectedHorizontal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ================== Inline & Vertical ===================
|
||||
//
|
||||
[`&${componentCls}-root`]: {
|
||||
[`&${componentCls}-inline, &${componentCls}-vertical`]: {
|
||||
borderInlineEnd: `${colorActiveBarBorderSize}px ${lineType} ${colorSplit}`,
|
||||
},
|
||||
},
|
||||
|
||||
// ======================== Inline ========================
|
||||
[`&${componentCls}-inline`]: {
|
||||
// Sub
|
||||
[`${componentCls}-sub${componentCls}-inline`]: {
|
||||
background: colorSubItemBg,
|
||||
},
|
||||
|
||||
// Item
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]:
|
||||
colorActiveBarBorderSize && colorActiveBarWidth
|
||||
? {
|
||||
width: `calc(100% + ${colorActiveBarBorderSize}px)`,
|
||||
}
|
||||
: {},
|
||||
|
||||
[`${componentCls}-item`]: {
|
||||
position: 'relative',
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
insetBlock: 0,
|
||||
insetInlineEnd: 0,
|
||||
borderInlineEnd: `${colorActiveBarWidth}px solid ${colorItemTextSelected}`,
|
||||
transform: 'scaleY(0.0001)',
|
||||
opacity: 0,
|
||||
transition: [
|
||||
`transform ${motionDurationMid} ${motionEaseOut}`,
|
||||
`opacity ${motionDurationMid} ${motionEaseOut}`,
|
||||
].join(','),
|
||||
content: '""',
|
||||
},
|
||||
|
||||
// Danger
|
||||
[`&${componentCls}-item-danger`]: {
|
||||
'&::after': {
|
||||
borderInlineEndColor: colorDangerItemTextSelected,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-selected, ${componentCls}-item-selected`]: {
|
||||
'&::after': {
|
||||
transform: 'scaleY(1)',
|
||||
opacity: 1,
|
||||
transition: [
|
||||
`transform ${motionDurationMid} ${motionEaseInOut}`,
|
||||
`opacity ${motionDurationMid} ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default getThemeStyle;
|
|
@ -0,0 +1,231 @@
|
|||
import type { CSSObject } from '../../_util/cssinjs';
|
||||
import { textEllipsis } from '../../_style';
|
||||
import type { MenuToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
|
||||
const getVerticalInlineStyle: GenerateStyle<MenuToken, CSSObject> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
menuItemHeight,
|
||||
itemMarginInline,
|
||||
padding,
|
||||
menuArrowSize,
|
||||
marginXS,
|
||||
marginXXS,
|
||||
} = token;
|
||||
|
||||
const paddingWithArrow = padding + menuArrowSize + marginXS;
|
||||
|
||||
return {
|
||||
[`${componentCls}-item`]: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
height: menuItemHeight,
|
||||
lineHeight: `${menuItemHeight}px`,
|
||||
paddingInline: padding,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
|
||||
marginInline: itemMarginInline,
|
||||
marginBlock: marginXXS,
|
||||
width: `calc(100% - ${itemMarginInline * 2}px)`,
|
||||
},
|
||||
|
||||
// disable margin collapsed
|
||||
[`${componentCls}-submenu`]: {
|
||||
paddingBottom: 0.02,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item,
|
||||
> ${componentCls}-submenu > ${componentCls}-submenu-title`]: {
|
||||
height: menuItemHeight,
|
||||
lineHeight: `${menuItemHeight}px`,
|
||||
},
|
||||
|
||||
[`${componentCls}-item-group-list ${componentCls}-submenu-title,
|
||||
${componentCls}-submenu-title`]: {
|
||||
paddingInlineEnd: paddingWithArrow,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getVerticalStyle: GenerateStyle<MenuToken> = token => {
|
||||
const {
|
||||
componentCls,
|
||||
iconCls,
|
||||
menuItemHeight,
|
||||
colorTextLightSolid,
|
||||
dropdownWidth,
|
||||
controlHeightLG,
|
||||
motionDurationMid,
|
||||
motionEaseOut,
|
||||
paddingXL,
|
||||
fontSizeSM,
|
||||
fontSizeLG,
|
||||
motionDurationSlow,
|
||||
paddingXS,
|
||||
boxShadowSecondary,
|
||||
} = token;
|
||||
|
||||
const inlineItemStyle: CSSObject = {
|
||||
height: menuItemHeight,
|
||||
lineHeight: `${menuItemHeight}px`,
|
||||
listStylePosition: 'inside',
|
||||
listStyleType: 'disc',
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
[componentCls]: {
|
||||
[`&-inline, &-vertical`]: {
|
||||
[`&${componentCls}-root`]: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
|
||||
...getVerticalInlineStyle(token),
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-submenu-popup`]: {
|
||||
[`${componentCls}-vertical`]: {
|
||||
...getVerticalInlineStyle(token),
|
||||
boxShadow: boxShadowSecondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Vertical only
|
||||
{
|
||||
[`${componentCls}-submenu-popup ${componentCls}-vertical${componentCls}-sub`]: {
|
||||
minWidth: dropdownWidth,
|
||||
maxHeight: `calc(100vh - ${controlHeightLG * 2.5}px)`,
|
||||
padding: '0',
|
||||
overflow: 'hidden',
|
||||
borderInlineEnd: 0,
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22244
|
||||
// https://github.com/ant-design/ant-design/issues/26812
|
||||
"&:not([class*='-active'])": {
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Inline Only
|
||||
{
|
||||
[`${componentCls}-inline`]: {
|
||||
width: '100%',
|
||||
|
||||
// Motion enhance for first level
|
||||
[`&${componentCls}-root`]: {
|
||||
[`${componentCls}-item, ${componentCls}-submenu-title`]: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow}`,
|
||||
`background ${motionDurationSlow}`,
|
||||
`padding ${motionDurationMid} ${motionEaseOut}`,
|
||||
].join(','),
|
||||
|
||||
[`> ${componentCls}-title-content`]: {
|
||||
flex: 'auto',
|
||||
minWidth: 0,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
|
||||
'> *': {
|
||||
flex: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// >>>>> Sub
|
||||
[`${componentCls}-sub${componentCls}-inline`]: {
|
||||
padding: 0,
|
||||
border: 0,
|
||||
borderRadius: 0,
|
||||
boxShadow: 'none',
|
||||
|
||||
[`& > ${componentCls}-submenu > ${componentCls}-submenu-title`]: inlineItemStyle,
|
||||
|
||||
[`& ${componentCls}-item-group-title`]: {
|
||||
paddingInlineStart: paddingXL,
|
||||
},
|
||||
},
|
||||
|
||||
// >>>>> Item
|
||||
[`${componentCls}-item`]: inlineItemStyle,
|
||||
},
|
||||
},
|
||||
|
||||
// Inline Collapse Only
|
||||
{
|
||||
[`${componentCls}-inline-collapsed`]: {
|
||||
width: menuItemHeight * 2,
|
||||
|
||||
[`&${componentCls}-root`]: {
|
||||
[`${componentCls}-item, ${componentCls}-submenu ${componentCls}-submenu-title`]: {
|
||||
[`> ${componentCls}-inline-collapsed-noicon`]: {
|
||||
fontSize: fontSizeLG,
|
||||
textAlign: 'center',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`> ${componentCls}-item,
|
||||
> ${componentCls}-item-group > ${componentCls}-item-group-list > ${componentCls}-item,
|
||||
> ${componentCls}-item-group > ${componentCls}-item-group-list > ${componentCls}-submenu > ${componentCls}-submenu-title,
|
||||
> ${componentCls}-submenu > ${componentCls}-submenu-title`]: {
|
||||
insetInlineStart: 0,
|
||||
paddingInline: `calc(50% - ${fontSizeSM}px)`,
|
||||
textOverflow: 'clip',
|
||||
|
||||
[`
|
||||
${componentCls}-submenu-arrow,
|
||||
${componentCls}-submenu-expand-icon
|
||||
`]: {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
[`${componentCls}-item-icon, ${iconCls}`]: {
|
||||
margin: 0,
|
||||
fontSize: fontSizeLG,
|
||||
lineHeight: `${menuItemHeight}px`,
|
||||
|
||||
'+ span': {
|
||||
display: 'inline-block',
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item-icon, ${iconCls}`]: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
|
||||
'&-tooltip': {
|
||||
pointerEvents: 'none',
|
||||
|
||||
[`${componentCls}-item-icon, ${iconCls}`]: {
|
||||
display: 'none',
|
||||
},
|
||||
|
||||
'a, a:hover': {
|
||||
color: colorTextLightSolid,
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-item-group-title`]: {
|
||||
...textEllipsis,
|
||||
paddingInline: paddingXS,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export default getVerticalStyle;
|
|
@ -13,7 +13,7 @@ import './input/style';
|
|||
import './tooltip/style';
|
||||
import './popover/style';
|
||||
import './popconfirm/style';
|
||||
import './menu/style';
|
||||
// import './menu/style';
|
||||
import './mentions/style';
|
||||
import './dropdown/style';
|
||||
// import './divider/style';
|
||||
|
|
|
@ -20,7 +20,7 @@ import type { ComponentToken as DividerComponentToken } from '../../divider/styl
|
|||
// import type { ComponentToken as LayoutComponentToken } from '../../layout/style';
|
||||
// import type { ComponentToken as ListComponentToken } from '../../list/style';
|
||||
// import type { ComponentToken as MentionsComponentToken } from '../../mentions/style';
|
||||
// import type { ComponentToken as MenuComponentToken } from '../../menu/style';
|
||||
import type { ComponentToken as MenuComponentToken } from '../../menu/style';
|
||||
import type { ComponentToken as MessageComponentToken } from '../../message/style';
|
||||
import type { ComponentToken as ModalComponentToken } from '../../modal/style';
|
||||
import type { ComponentToken as NotificationComponentToken } from '../../notification/style';
|
||||
|
@ -102,7 +102,7 @@ export interface ComponentTokenMap {
|
|||
// Tabs?: TabsComponentToken;
|
||||
// Calendar?: CalendarComponentToken;
|
||||
// Steps?: StepsComponentToken;
|
||||
// Menu?: MenuComponentToken;
|
||||
Menu?: MenuComponentToken;
|
||||
Modal?: ModalComponentToken;
|
||||
Message?: MessageComponentToken;
|
||||
// Upload?: UploadComponentToken;
|
||||
|
|
Loading…
Reference in New Issue