feat: float button support badge (#6738)

* docs(FloatButton): add badge demo

* fix(Badge): color attribute invalid
pull/6757/head
selicens 2023-07-17 09:35:19 +08:00 committed by GitHub
parent 4ea318be30
commit 7591d5c3e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 31 deletions

View File

@ -107,7 +107,7 @@ export default defineComponent({
const statusCls = computed(() => ({
[`${prefixCls.value}-status-dot`]: hasStatus.value,
[`${prefixCls.value}-status-${props.status}`]: !!props.status,
[`${prefixCls.value}-status-${props.color}`]: isInternalColor.value,
[`${prefixCls.value}-color-${props.color}`]: isInternalColor.value,
}));
const statusStyle = computed(() => {
@ -125,7 +125,7 @@ export default defineComponent({
[`${prefixCls.value}-multiple-words`]:
!isDotRef.value && displayCount.value && displayCount.value.toString().length > 1,
[`${prefixCls.value}-status-${props.status}`]: !!props.status,
[`${prefixCls.value}-status-${props.color}`]: isInternalColor.value,
[`${prefixCls.value}-color-${props.color}`]: isInternalColor.value,
}));
return () => {

View File

@ -73,9 +73,12 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
const ribbonPrefixCls = `${antCls}-ribbon`;
const ribbonWrapperPrefixCls = `${antCls}-ribbon-wrapper`;
const statusPreset = genPresetColor(token, (colorKey, { darkColor }) => ({
[`${componentCls}-status-${colorKey}`]: {
const colorPreset = genPresetColor(token, (colorKey, { darkColor }) => ({
[`&${componentCls} ${componentCls}-color-${colorKey}`]: {
background: darkColor,
[`&:not(${componentCls}-count)`]: {
color: darkColor,
},
},
}));
@ -150,9 +153,9 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
insetInlineEnd: 0,
transform: 'translate(50%, -50%)',
transformOrigin: '100% 0%',
[`${iconCls}-spin`]: {
[`&${iconCls}-spin`]: {
animationName: antBadgeLoadingCircle,
animationDuration: token.motionDurationMid,
animationDuration: '1s',
animationIterationCount: 'infinite',
animationTimingFunction: 'linear',
},
@ -207,13 +210,13 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
[`${componentCls}-status-warning`]: {
backgroundColor: token.colorWarning,
},
...statusPreset,
[`${componentCls}-status-text`]: {
marginInlineStart: marginXS,
color: token.colorText,
fontSize: token.fontSize,
},
},
...colorPreset,
[`${componentCls}-zoom-appear, ${componentCls}-zoom-enter`]: {
animationName: antZoomBadgeIn,
animationDuration: token.motionDurationSlow,
@ -284,7 +287,6 @@ const genSharedBadgeStyle: GenerateStyle<BadgeToken> = (token: BadgeToken): CSSO
...resetComponent(token),
position: 'absolute',
top: marginXS,
height: badgeFontHeight,
padding: `0 ${token.paddingXS}px`,
color: token.colorPrimary,
lineHeight: `${badgeFontHeight}px`,

View File

@ -1,6 +1,7 @@
import classNames from '../_util/classNames';
import { defineComponent, computed, ref } from 'vue';
import Tooltip from '../tooltip';
import Badge from '../badge';
import Content from './FloatButtonContent';
import useConfigInject from '../config-provider/hooks/useConfigInject';
import { useInjectFloatButtonGroupContext } from './context';
@ -37,6 +38,7 @@ const FloatButton = defineComponent({
shape = 'circle',
description = slots.description?.(),
tooltip,
badge = {},
...restProps
} = props;
@ -60,6 +62,7 @@ const FloatButton = defineComponent({
? () => (slots.tooltip && slots.tooltip()) || tooltip
: undefined,
default: () => (
<Badge {...badge}>
<div class={`${prefixCls.value}-body`}>
<Content
prefixCls={prefixCls.value}
@ -69,6 +72,7 @@ const FloatButton = defineComponent({
}}
></Content>
</div>
</Badge>
),
}}
></Tooltip>

View File

@ -20,6 +20,44 @@ exports[`renders ./components/float-button/demo/back-top.vue correctly 1`] = `
</div>
`;
exports[`renders ./components/float-button/demo/badge.vue correctly 1`] = `
<button style="right: 164px;" class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="file-text" class="anticon anticon-file-text"><svg focusable="false" class="" data-icon="file-text" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494zM504 618H320c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM312 490v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H320c-4.4 0-8 3.6-8 8z"></path></svg></span></div>
</div>
</div><sup data-show="true" class="ant-scroll-number ant-badge-dot"></sup>
<!----></span>
<!---->
</button>
<div style="right: 94px;" class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-circle-shadow"><button class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="file-text" class="anticon anticon-file-text"><svg focusable="false" class="" data-icon="file-text" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494zM504 618H320c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM312 490v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H320c-4.4 0-8 3.6-8 8z"></path></svg></span></div>
</div>
</div><sup data-show="true" class="ant-scroll-number ant-badge-count ant-badge-color-blue" title="5"><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">5</p></span></sup>
<!----></span>
<!----></button><button class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="file-text" class="anticon anticon-file-text"><svg focusable="false" class="" data-icon="file-text" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494zM504 618H320c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM312 490v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H320c-4.4 0-8 3.6-8 8z"></path></svg></span></div>
</div>
</div><sup data-show="true" class="ant-scroll-number ant-badge-count" title="5"><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">5</p></span></sup>
<!----></span>
<!---->
</button></div>
<div class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-circle-shadow"><button class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="question-circle" class="anticon anticon-question-circle"><svg focusable="false" class="" data-icon="question-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M623.6 316.7C593.6 290.4 554 276 512 276s-81.6 14.5-111.6 40.7C369.2 344 352 380.7 352 420v7.6c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V420c0-44.1 43.1-80 96-80s96 35.9 96 80c0 31.1-22 59.6-56.1 72.7-21.2 8.1-39.2 22.3-52.1 40.9-13.1 19-19.9 41.8-19.9 64.9V620c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-22.7a48.3 48.3 0 0130.9-44.8c59-22.7 97.1-74.7 97.1-132.5.1-39.3-17.1-76-48.3-103.3zM472 732a40 40 0 1080 0 40 40 0 10-80 0z"></path></svg></span></div>
<!---->
</div>
</div><sup data-show="true" class="ant-scroll-number ant-badge-count ant-badge-multiple-words" title="12"><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">1</p></span><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">2</p></span></sup>
<!----></span>
<!----></button><button class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="file-text" class="anticon anticon-file-text"><svg focusable="false" class="" data-icon="file-text" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494zM504 618H320c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zM312 490v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H320c-4.4 0-8 3.6-8 8z"></path></svg></span></div>
</div>
</div><sup data-show="true" class="ant-scroll-number ant-badge-count ant-badge-multiple-words" title="123"><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">1</p></span><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">2</p></span><span class="ant-scroll-number-only" style="transition: none;"><p class="ant-scroll-number-only-unit current">3</p></span></sup>
<!----></span>
<!---->
</button><button class="ant-float-btn ant-float-btn-default ant-float-btn-circle fade-enter fade-enter-prepare fade-enter-start" type="button"><span class="ant-badge"><div class="ant-float-btn-body"><div class="ant-float-btn-content"><div class="ant-float-btn-icon"><span role="img" aria-label="vertical-align-top" class="anticon anticon-vertical-align-top"><svg focusable="false" class="" data-icon="vertical-align-top" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M859.9 168H164.1c-4.5 0-8.1 3.6-8.1 8v60c0 4.4 3.6 8 8.1 8h695.8c4.5 0 8.1-3.6 8.1-8v-60c0-4.4-3.6-8-8.1-8zM518.3 355a8 8 0 00-12.6 0l-112 141.7a7.98 7.98 0 006.3 12.9h73.9V848c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V509.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 355z"></path></svg></span></div>
<!---->
</div>
</div><sup data-show="false" class="ant-scroll-number ant-badge-count" style="display: none;">
<!---->
</sup>
<!----></span>
<!---->
</button></div>
`;
exports[`renders ./components/float-button/demo/basic.vue correctly 1`] = `
<button class="ant-float-btn ant-float-btn-default ant-float-btn-circle" type="button">
<!---->

View File

@ -0,0 +1,42 @@
<docs>
---
order: 8
iframe: 360
title:
zh-CN: 徽标数
en-US: Badge
---
## zh-CN
右上角附带圆形徽标数字的悬浮按钮
## en-US
FloatButton with Badge.
</docs>
<template>
<a-float-button shape="circle" :badge="{ dot: true }" :style="{ right: '164px' }" />
<a-float-button-group shape="circle" :style="{ right: '94px' }">
<a-float-button :badge="{ count: 5, color: 'blue' }">
<template #tooltip>
<div>custom badge color</div>
</template>
</a-float-button>
<a-float-button :badge="{ count: 5 }"></a-float-button>
</a-float-button-group>
<a-float-button-group shape="circle">
<a-float-button :badge="{ count: 12 }">
<template #icon>
<QuestionCircleOutlined />
</template>
</a-float-button>
<a-float-button :badge="{ count: 123, overflowCount: 999 }"></a-float-button>
<a-back-top :visibility-height="0" />
</a-float-button-group>
</template>
<script setup>
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
</script>

View File

@ -23,6 +23,9 @@
<template v-else-if="iframeName === 'backtop'">
<back-top></back-top>
</template>
<template v-else-if="iframeName === 'badge'">
<badge></badge>
</template>
<demo-sort v-else>
<basic></basic>
<type></type>
@ -32,6 +35,7 @@
<group></group>
<group-menu></group-menu>
<back-top></back-top>
<badge></badge>
</demo-sort>
</template>
@ -44,6 +48,7 @@ import Tooltip from './tooltip.vue';
import group from './group.vue';
import GroupMenu from './group-menu.vue';
import BackTop from './back-top.vue';
import Badge from './badge.vue';
import { defineComponent, provide } from 'vue';
import US from '../index.en-US.md';
@ -61,6 +66,7 @@ export default defineComponent({
group,
GroupMenu,
BackTop,
Badge,
},
props: {
iframeName: String,
@ -78,6 +84,7 @@ export default defineComponent({
'floatbutton-group': '/iframe/float-button/#floatbutton-group',
'menu-mode': '/iframe/float-button/#menu-mode',
backtop: '/iframe/float-button/#backtop',
badge: '/iframe/float-button/#badge',
}
: {},
);

View File

@ -28,6 +28,7 @@ FloatButton. Available since `4.0.0`.
| shape | Setting button shape | `circle` \| `square` | `circle` | |
| href | The target of hyperlink | string | - | |
| target | Specifies where to display the linked URL | string | - | |
| badge | Attach Badge to FloatButton. `status` and other props related are not supported. | [BadgeProps](/components/badge#api) | - | |
### common events

View File

@ -30,6 +30,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*a0hwTY_rOSUAAA
| onClick | 点击按钮时的回调 | (event) => void | - | |
| href | 点击跳转的地址,指定此属性 button 的行为和 a 链接一致 | string | - | |
| target | 相当于 a 标签的 target 属性href 存在时生效 | string | - | |
| badge | 带徽标数字的悬浮按钮(不支持 status 以及相关属性) | [BadgeProps](/components/badge-cn#api) | - | |
### common events

View File

@ -1,7 +1,8 @@
import type { ExtractPropTypes } from 'vue';
import PropTypes from '../_util/vue-types';
import type { MouseEventHandler } from '../_util/EventInterface';
import { stringType, booleanType, functionType } from '../_util/type';
import { stringType, booleanType, functionType, objectType } from '../_util/type';
import type { BadgeProps } from '../badge';
export type FloatButtonType = 'default' | 'primary';
@ -9,6 +10,8 @@ export type FloatButtonShape = 'circle' | 'square';
export type FloatButtonGroupTrigger = 'click' | 'hover';
export type FloatButtonBadgeProps = Omit<BadgeProps, 'status' | 'text' | 'title' | 'children'>;
export const floatButtonProps = () => {
return {
prefixCls: String,
@ -18,6 +21,7 @@ export const floatButtonProps = () => {
tooltip: PropTypes.any,
href: String,
target: functionType<() => Window | HTMLElement | null>(),
badge: objectType<FloatButtonBadgeProps>(),
onClick: functionType<MouseEventHandler>(),
};
};

View File

@ -5,6 +5,7 @@ import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { initFadeMotion } from '../../style/motion/fade';
import { resetComponent } from '../../style';
import { initMotion } from '../../style/motion/motion';
import getOffset from '../util';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
@ -18,6 +19,11 @@ type FloatButtonToken = FullToken<'FloatButton'> & {
floatButtonFontSize: number;
floatButtonSize: number;
floatButtonIconSize: number;
floatButtonBodySize: number;
floatButtonBodyPadding: number;
badgeOffset: number;
dotOffsetInCircle: number;
dotOffsetInSquare: number;
// Position
floatButtonInsetBlockEnd: number;
@ -80,7 +86,16 @@ const initFloatButtonGroupMotion = (token: FloatButtonToken) => {
// ============================== Group ==============================
const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token => {
const { componentCls, floatButtonSize, margin, borderRadiusLG } = token;
const {
antCls,
componentCls,
floatButtonSize,
margin,
borderRadiusLG,
borderRadiusSM,
badgeOffset,
floatButtonBodyPadding,
} = token;
const groupPrefixCls = `${componentCls}-group`;
return {
[groupPrefixCls]: {
@ -116,6 +131,7 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
[`${componentCls}-body`]: {
width: floatButtonSize,
height: floatButtonSize,
borderRadius: '50%',
},
},
},
@ -134,17 +150,22 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
'&:not(:last-child)': {
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
},
[`${antCls}-badge`]: {
[`${antCls}-badge-count`]: {
top: -(floatButtonBodyPadding + badgeOffset),
insetInlineEnd: -(floatButtonBodyPadding + badgeOffset),
},
},
},
[`${groupPrefixCls}-wrap`]: {
display: 'block',
borderRadius: borderRadiusLG,
boxShadow: token.boxShadowSecondary,
overflow: 'hidden',
[`${componentCls}-square`]: {
boxShadow: 'none',
marginTop: 0,
borderRadius: 0,
padding: token.paddingXXS,
padding: floatButtonBodyPadding,
'&:first-child': {
borderStartStartRadius: borderRadiusLG,
borderStartEndRadius: borderRadiusLG,
@ -157,8 +178,8 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
},
[`${componentCls}-body`]: {
width: floatButtonSize - token.paddingXXS * 2,
height: floatButtonSize - token.paddingXXS * 2,
width: token.floatButtonBodySize,
height: token.floatButtonBodySize,
},
},
},
@ -171,10 +192,11 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
boxShadow: token.boxShadowSecondary,
[`${componentCls}-square`]: {
boxShadow: 'none',
padding: token.paddingXXS,
padding: floatButtonBodyPadding,
[`${componentCls}-body`]: {
width: floatButtonSize - token.paddingXXS * 2,
height: floatButtonSize - token.paddingXXS * 2,
width: token.floatButtonBodySize,
height: token.floatButtonBodySize,
borderRadius: borderRadiusSM,
},
},
},
@ -183,14 +205,23 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
// ============================== Shared ==============================
const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = token => {
const { componentCls, floatButtonIconSize, floatButtonSize, borderRadiusLG } = token;
const {
antCls,
componentCls,
floatButtonBodyPadding,
floatButtonIconSize,
floatButtonSize,
borderRadiusLG,
badgeOffset,
dotOffsetInSquare,
dotOffsetInCircle,
} = token;
return {
[componentCls]: {
...resetComponent(token),
border: 'none',
position: 'fixed',
cursor: 'pointer',
overflow: 'hidden',
zIndex: 99,
display: 'block',
justifyContent: 'center',
@ -210,7 +241,16 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
'&:empty': {
display: 'none',
},
[`${antCls}-badge`]: {
width: '100%',
height: '100%',
[`${antCls}-badge-count`]: {
transform: 'translate(0, 0)',
transformOrigin: 'center',
top: -badgeOffset,
insetInlineEnd: -badgeOffset,
},
},
[`${componentCls}-body`]: {
width: '100%',
height: '100%',
@ -226,7 +266,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
padding: `2px 4px`,
padding: `${floatButtonBodyPadding / 2}px ${floatButtonBodyPadding}px`,
[`${componentCls}-icon`]: {
textAlign: 'center',
margin: 'auto',
@ -237,9 +277,18 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
},
},
},
[`${componentCls}-rtl`]: {
direction: 'rtl',
},
[`${componentCls}-circle`]: {
height: floatButtonSize,
borderRadius: '50%',
[`${antCls}-badge`]: {
[`${antCls}-badge-dot`]: {
top: dotOffsetInCircle,
insetInlineEnd: dotOffsetInCircle,
},
},
[`${componentCls}-body`]: {
borderRadius: '50%',
},
@ -248,9 +297,15 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = token
height: 'auto',
minHeight: floatButtonSize,
borderRadius: borderRadiusLG,
[`${antCls}-badge`]: {
[`${antCls}-badge-dot`]: {
top: dotOffsetInSquare,
insetInlineEnd: dotOffsetInSquare,
},
},
[`${componentCls}-body`]: {
height: 'auto',
borderRadius: token.borderRadiusSM,
borderRadius: borderRadiusLG,
},
},
[`${componentCls}-default`]: {
@ -312,6 +367,8 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', token => {
fontSize,
fontSizeIcon,
controlItemBgHover,
paddingXXS,
borderRadiusLG,
} = token;
const floatButtonToken = mergeToken<FloatButtonToken>(token, {
floatButtonBackgroundColor: colorBgElevated,
@ -323,6 +380,12 @@ export default genComponentStyleHook<'FloatButton'>('FloatButton', token => {
floatButtonInsetBlockEnd: marginXXL,
floatButtonInsetInlineEnd: marginLG,
floatButtonBodySize: controlHeightLG - paddingXXS * 2,
// 这里的 paddingXXS 是简写,完整逻辑是 (controlHeightLG - (controlHeightLG - paddingXXS * 2)) / 2,
floatButtonBodyPadding: paddingXXS,
badgeOffset: paddingXXS * 1.5,
dotOffsetInCircle: getOffset(controlHeightLG / 2),
dotOffsetInSquare: getOffset(borderRadiusLG),
});
return [
floatButtonGroupStyle(floatButtonToken),

View File

@ -0,0 +1,10 @@
const getOffset = (radius: number): number => {
if (radius === 0) {
return 0;
}
// 如果要考虑通用性,这里应该用三角函数 Math.sin(45)
// 但是这个场景比较特殊,始终是等腰直角三角形,所以直接用 Math.sqrt() 开方即可
return radius - Math.sqrt(radius ** 2 / 2);
};
export default getOffset;