[英]How to always apply focusVisible styling on a focused Material-UI Button component?
對於 Material-UI Button 組件,我希望“focus”樣式看起來與“focusVisible”樣式相同。 這意味着如果按鈕以編程方式或使用鼠標聚焦,我希望它具有相同的漣漪效果,就像按鈕通過 tab 鍵聚焦一樣。
我發現的一種解決方法是在元素獲得焦點之前調用dispatchEvent(new window.Event("keydown"))
,導致鍵盤成為最后使用的輸入類型。 這將使按鈕看起來像我想要的那樣,直到 onMouseLeave 事件(來自 MUI <ButtonBase/>)或另一個鼠標事件被觸發,導致可見焦點消失。
我已經想出了如何改變組件的焦點樣式,如下所示:
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
因此,當按鈕處於“焦點”state 時,我可以對按鈕應用一些樣式。 (例如,我應用了邊框)。 但我錯過了如何讓 styles 申請。 我嘗試將 className 'Mui-visibleFocus' 放在 Button 上,但這似乎沒有效果。 如果按鈕位於可見焦點 state 中,是否有某種方法可以獲得 styles?
ButtonBase
( Button
委托給)有一個action屬性,可以設置按鈕的焦點可見 state 。
ButtonBase
為此利用了useImperativeHandle 鈎子。 為了利用它,你將一個 ref 傳遞給action
prop,然后你可以稍后調用actionRef.current.focusVisible()
。
然而,這本身是不夠的,因為有幾個鼠標和觸摸事件ButtonBase 監聽以啟動/停止漣漪。 如果您使用disableTouchRipple
道具,它會阻止 ButtonBase 根據這些事件嘗試啟動/停止波紋。
不幸的是disableTouchRipple
阻止了按鈕上的點擊和觸摸動畫。 這些可以通過顯式添加您控制的另一個TouchRipple
元素來恢復。 下面的示例顯示了將onMouseDown
和onMouseUp
處理為概念驗證,但理想的解決方案將處理ButtonBase
處理的所有不同事件。
這是一個工作示例:
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>
);
}
我們可以創建一個對 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>
);
}
上面的FocusButton
可以用作Button
的替代品,或者您可以簡單地添加引用並在觸發方法中調用focusVisible()
例如:
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.