-
-
Notifications
You must be signed in to change notification settings - Fork 215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
为 Bubble 和 BubbleList 组件的 footer 属性增加可控的 hover 样式 #489
Comments
非常感谢!我看了后有几个点在犹豫:
|
感谢回复,视野局限于当前需求,确实没有考虑全面。 目前思考了两点:
我这边尝试实现了个版本: 1:首先实现 Bubble 组件 Semantic DOM 基本的触发操作。 1.1 定义 SemanticContentProps
...
export type SemanticTrigger='never'|'always'|'hover'|'click';
export interface SemanticContentProps {
/**
* @default always
*/
trigger?: SemanticTrigger;
content: React.ReactNode;
}
...
export interface BubbleProps<ContentType extends BubbleContentType=string> extends Omit<React.HTMLAttributes<HTMLDivElement>,'content'> {
prefixCls?: string;
...
header?: SemanticContentProps|React.ReactNode;
footer?: SemanticContentProps|React.ReactNode;
} 1.2 实现 useSemanticContent Hook
/**
* Return semantic content rendering logic and classNames.
*/
const useSemanticContent = (semanticProps, type, prefixCls, disableTrigger = false) => {
const isSemanticProps = typeof semanticProps === 'object' && semanticProps !== null && 'trigger' in semanticProps;
const trigger = disableTrigger ? undefined : isSemanticProps ? semanticProps.trigger : 'always';
const content = isSemanticProps ? semanticProps.content : semanticProps;
const resolvedContent = trigger === 'never' ? null : content;
const className = classnames(`${prefixCls}-${type}`, {
[`${prefixCls}-${type}-hover`]: trigger === 'hover',
[`${prefixCls}-${type}-click`]: trigger === 'click',
[`${prefixCls}-${type}-visible`]: trigger === 'always',
});
return {
content: resolvedContent,
className,
trigger,
};
};
export default useSemanticContent; 2:给 BubbleList 组件新增 triggerRange 接口,动态控制列表中不同气泡 Semantic DOM 的触发行为。 triggerRange 用于控制 Bubble 组件中 Semantic DOM 的触发行为是否失效(即强制变为 always)。
const shouldDisableTrigger = (triggerRange, isLatest, roleMatch) => {
if (triggerRange === 'latest') {
return isLatest; // 仅最新气泡的 trigger 失效
}
if (triggerRange === 'all') {
return true; // 所有气泡的 trigger 失效
}
if (triggerRange) {
return roleMatch; // 匹配 role 的气泡的 trigger 失效
}
return false; // 默认情况下,trigger 行为正常生效
}; 这样组合起来有很多玩法:
1:历史气泡的 header 不显示,footer hover 触发 <Bubble.List
roles={roles}
triggerRange="latest"
items={messages.map((message, index) => {
return {
header: {
trigger: "never",
content: headerContent
},
footer: {
trigger: "hover",
content: footerContent
),
},
key: index,
role: message.isBot ? "bot" : "user",
content: message.text,
loading: loading,
};
})}
/> 2:历史气泡的 header 显示,footer click 触发 <Bubble.List
roles={roles}
triggerRange="latest"
items={messages.map((message, index) => {
return {
header: headerContent,
footer: {
trigger: "hover",
content: footerContent
),
},
key: index,
role: message.isBot ? "bot" : "user",
content: message.text,
loading: loading,
};
})}
/> |
赞! |
这点我有个想法:不新增 // before
export type RolesType = Record<string, RoleType> | ((bubbleDataP: BubbleDataType) => RoleType);
// now
export type RolesType = Record<string, RoleType> | ((bubbleDataP: BubbleDataType, index: number) => RoleType); 这样还可以顺手把 #475 支持了,😄 你觉得如何? |
1:给
#17 export type RolesType = Record<string, RoleType> | ((bubbleDataP: BubbleDataType, index: number) => RoleType);
export default function useListData(items, roles) {
const getRoleBubbleProps = React.useCallback((bubble, index) => {
if (typeof roles === 'function') {
return roles(bubble, index);
}
if (roles) {
return roles[bubble.role] || {};
}
return {};
}, [roles]);
return React.useMemo(() => (items || []).map((bubbleData, i) => {
const mergedKey = bubbleData.key ?? `preset_${i}`;
return {
...getRoleBubbleProps(bubbleData, i),
...bubbleData,
key: mergedKey
};
}), [items, getRoleBubbleProps]);
} 2:最新气泡的 Semantic DOM 正常显示,历史气泡按 trigger 触发 const roles = (bubble, index) => {
const isLatest = index == (messages.length - 1).toString();
switch (bubble.role) {
case "bot":
return {
placement: "start",
avatar: { icon: <UserOutlined />, style: fooAvatar },
typing: { step: 2, interval: 50 },
header: {
trigger: isLatest ? "always" : "never",
content: botHeaderContent
},
footer: {
trigger: isLatest ? "always" : "hover",
content: footerHeaderContent
},
};
case "user":
return {
placement: "end",
avatar: { icon: <UserOutlined />, style: barAvatar },
header: {
trigger: "never",
content: userHeaderContent
},
footer: {
trigger: "hover",
content: userFooterContent
},
};
}
}; <Bubble.List
ref={listRef}
className="bubble-list"
roles={roles}
items={messages.map((msg, index) => ({
key: index,
role: msg.role,
content: msg.text,
time: msg.time,
}))}
/> |
看起来没什么问题了,RFC 之吧,这个 issue 我指派给你,感谢参与! |
需求动机
问题描述
Bubble
组件中实现footer
的 hover 效果。虽然可以直接使用 CSS 样式来实现,但在BubbleList
组件中,使用 CSS 样式可能会导致样式污染。因此,希望在Bubble
和BubbleList
组件中增加一个属性,以便能够更灵活地控制footer
的 hover 样式;Bubble
组件中footer
建议默认在typeing
和loading
完后再加载。解决方案
建议在
Bubble
和BubbleList
组件中增加属性,允许自定义footer
的 hover 样式。预期效果
Bubble
组件中,footer
部分能够根据footerDisplayMode
属性设置显示 hover 效果。BubbleList
组件中,可以根据hoverableBubbleFooter
属性设置符合条件的Bubble
,其footer
部分的 hover 效果。提议的 API 是什么样的?
Bubble:
always
/hover
bubble/Bubble.js
bubble/style/index.js
Bubble.List:
latest
/all
/none
/与 role 匹配
bubble/BubbleList.js
The text was updated successfully, but these errors were encountered: