[英]How to always apply focusVisible styling on a focused Material-UI Button component?
For a Material-UI Button component, I would like to have the "focus" styling look the same as "focusVisible" styling.对于 Material-UI Button 组件,我希望“focus”样式看起来与“focusVisible”样式相同。 Meaning I want it to have the same ripple effect visible if the button was focused programatically or with the mouse as if the button was focused with the tab key.
这意味着如果按钮以编程方式或使用鼠标聚焦,我希望它具有相同的涟漪效果,就像按钮通过 tab 键聚焦一样。
A sort-of workaround I have found is to call dispatchEvent(new window.Event("keydown"))
on the element before it is focused, causing keyboard to be the last input type used.我发现的一种解决方法是在元素获得焦点之前调用
dispatchEvent(new window.Event("keydown"))
,导致键盘成为最后使用的输入类型。 This will have the effect of making the button look the way I want UNTIL the onMouseLeave event (from MUI <ButtonBase/>) or another mouse event is fired, causing the visible focus to disappear.这将使按钮看起来像我想要的那样,直到 onMouseLeave 事件(来自 MUI <ButtonBase/>)或另一个鼠标事件被触发,导致可见焦点消失。
I have figured out how to change the focus styling of the component like this:我已经想出了如何改变组件的焦点样式,如下所示:
import React from "react"
import { withStyles } from "@material-ui/core/styles"
import Button from "@material-ui/core/Button"
const styles = {
root: {
'&:focus': {
border: "3px solid #000000"
}
}
}
const CustomButtonRaw = React.forwardRef((props, ref) => {
const { classes, ...rest } = props
return <Button classes={{root: classes.root}} {...rest} ref={ref}/>
}
const CustomButton = withStyles(styles, { name: "CustomButton" })(CustomButtonRaw)
export default CustomButton
So, I can apply some style to the button when it is in "focus" state.因此,当按钮处于“焦点”state 时,我可以对按钮应用一些样式。 (For ex. I applied a border).
(例如,我应用了边框)。 But I am missing how to get the styles to apply.
但我错过了如何让 styles 申请。 I have tried putting the className 'Mui-visibleFocus' on the Button but that did not seem to have an effect.
我尝试将 className 'Mui-visibleFocus' 放在 Button 上,但这似乎没有效果。 Is there some way to get the styles that would be applied if the Button was in visibleFocus state?
如果按钮位于可见焦点 state 中,是否有某种方法可以获得 styles?
ButtonBase
(which Button
delegates to ) has an action prop which provides the ability to set the button's focus-visible state . ButtonBase
( Button
委托给)有一个action属性,可以设置按钮的焦点可见 state 。
ButtonBase
leverages the useImperativeHandle hook for this. ButtonBase
为此利用了useImperativeHandle 钩子。 To leverage it, you pass a ref into the action
prop and then you can later call actionRef.current.focusVisible()
.为了利用它,你将一个 ref 传递给
action
prop,然后你可以稍后调用actionRef.current.focusVisible()
。
However, this by itself is not sufficient, because there are several mouse and touch events that ButtonBase listens to in order to start/stop the ripple.然而,这本身是不够的,因为有几个鼠标和触摸事件ButtonBase 监听以启动/停止涟漪。 If you use the
disableTouchRipple
prop, it prevents ButtonBase from trying to start/stop the ripple based on those events .如果您使用
disableTouchRipple
道具,它会阻止 ButtonBase 根据这些事件尝试启动/停止波纹。
Unfortunately disableTouchRipple
prevents click and touch animations on the button.不幸的是
disableTouchRipple
阻止了按钮上的点击和触摸动画。 These can be restored by adding another TouchRipple
element explicitly that you control.这些可以通过显式添加您控制的另一个
TouchRipple
元素来恢复。 My example below shows handling onMouseDown
and onMouseUp
as a proof-of-concept, but an ideal solution would deal with all the different events that ButtonBase
handles.下面的示例显示了将
onMouseDown
和onMouseUp
处理为概念验证,但理想的解决方案将处理ButtonBase
处理的所有不同事件。
Here's a working example:这是一个工作示例:
import React from "react";
import Button from "@material-ui/core/Button";
import TouchRipple from "@material-ui/core/ButtonBase/TouchRipple";
const FocusRippleButton = React.forwardRef(function FocusRippleButton(
{ onFocus, onMouseDown, onMouseUp, children, ...other },
ref
) {
const actionRef = React.useRef();
const rippleRef = React.useRef();
const handleFocus = (event) => {
actionRef.current.focusVisible();
if (onFocus) {
onFocus(event);
}
};
const handleMouseUp = (event) => {
rippleRef.current.stop(event);
if (onMouseUp) {
onMouseUp(event);
}
};
const handleMouseDown = (event) => {
rippleRef.current.start(event);
if (onMouseDown) {
onMouseDown(event);
}
};
return (
<Button
ref={ref}
action={actionRef}
disableTouchRipple
onFocus={handleFocus}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
{...other}
>
{children}
<TouchRipple ref={rippleRef} />
</Button>
);
});
export default function App() {
return (
<div className="App">
<FocusRippleButton variant="contained" color="primary">
Button 1
</FocusRippleButton>
<br />
<br />
<FocusRippleButton
variant="contained"
color="primary"
onFocus={() => console.log("Some extra onFocus functionality")}
>
Button 2
</FocusRippleButton>
</div>
);
}
We can create a reference to the action
of the material-ui Button
component and use the action reference within useLayoutEffect
to achieve the ripple effect我们可以创建一个对 material-ui
Button
组件的action
的引用,并使用useLayoutEffect
中的动作引用来实现波纹效果
import React, { createRef, useLayoutEffect } from "react";
import Button from "@material-ui/core/Button";
function FocusButton(props) {
const { handleClose } = props;
const actionRef = createRef();
useLayoutEffect(() => {
if (actionRef.current) {
actionRef.current.focusVisible();
}
}, []);
return (
<Button action={actionRef} onClick={handleClose}>
Ok
</Button>
);
}
The above FocusButton
can be used as a replacement to Button
or simply you can add a reference and call the focusVisible()
in the trigger method上面的
FocusButton
可以用作Button
的替代品,或者您可以简单地添加引用并在触发方法中调用focusVisible()
Eg:例如:
const buttonRef = createRef();
const handleButton2Click = () => {
buttonRef.current.focusVisible();
};
.
.
.
.
<Button action={buttonRef} variant="outlined">
Button 1
</Button>
<Button variant="outlined" color="primary" onClick={handleButton2Click}>
Button 2
</Button>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.