Css 如何始终在聚焦材质UI按钮组件上应用focusVisible样式?

Css 如何始终在聚焦材质UI按钮组件上应用focusVisible样式?,css,reactjs,button,material-ui,focus,Css,Reactjs,Button,Material Ui,Focus,对于材质UI按钮组件,我希望“焦点”样式与“焦点可见”样式相同。这意味着我希望它具有相同的涟漪效应,如果按钮通过编程或鼠标聚焦,就像按钮通过tab键聚焦一样 我发现的一种解决方法是在元素聚焦之前调用dispatchEvent(newwindow.Event(“keydown”)),从而使键盘成为最后使用的输入类型。这将使按钮看起来像我想要的那样,直到onMouseLeave事件(来自MUI)或另一个鼠标事件被触发,导致可见焦点消失 我已经知道如何更改组件的焦点样式,如下所示: import Re

对于材质UI按钮组件,我希望“焦点”样式与“焦点可见”样式相同。这意味着我希望它具有相同的涟漪效应,如果按钮通过编程或鼠标聚焦,就像按钮通过tab键聚焦一样

我发现的一种解决方法是在元素聚焦之前调用
dispatchEvent(newwindow.Event(“keydown”))
,从而使键盘成为最后使用的输入类型。这将使按钮看起来像我想要的那样,直到onMouseLeave事件(来自MUI)或另一个鼠标事件被触发,导致可见焦点消失

我已经知道如何更改组件的焦点样式,如下所示:

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
从“React”导入React
从“@material ui/core/styles”导入{withStyles}”
从“@material ui/core/Button”导入按钮
常量样式={
根目录:{
“&:焦点”:{
边框:“3px固体#000000”
}
}
}
const CustomButtonRaw=React.forwardRef((props,ref)=>{
常量{classes,…rest}=props
返回
}
const CustomButton=with样式(样式,{name:“CustomButton”})(CustomButtonRaw)
导出默认自定义按钮
因此,当按钮处于“焦点”状态时,我可以对其应用一些样式。(例如,我应用了边框)。但我不知道如何应用样式。我尝试将类名“Mui visibleFocus”放在按钮上,但似乎没有效果。是否有某种方法可以获取按钮处于visibleFocus状态时将应用的样式?

按钮库
(哪个
按钮
)具有提供以下功能的

ButtonBase
为此利用了。要利用它,请将ref传递到
操作
属性,然后可以稍后调用
actionRef.current.focusVisible()

但是,这本身是不够的,因为有几个鼠标和触摸事件可用于启动/停止ripple。如果使用
disableTouchRipple
道具,它将被禁用

不幸的是,
disableTouchRipple
阻止了按钮上的点击和触摸动画。可以通过添加另一个明确由您控制的
TouchRipple
元素来恢复这些动画。下面的示例显示了如何处理
onMouseDown
onMouseUp
作为概念证明,但理想的解决方案是处理all
按钮库
处理的不同事件

下面是一个工作示例:

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>
  );
}
从“React”导入React;
从“@物料界面/核心/按钮”导入按钮;
从“@material ui/core/ButtonBase/TouchRipple”导入TouchRipple;
const FocusRippleButton=React.forwardRef(函数FocusRippleButton(
{onFocus,onMouseDown,onmousedup,children,…other},
裁判
) {
const actionRef=React.useRef();
常量rippleRef=React.useRef();
const handleFocus=(事件)=>{
actionRef.current.focusVisible();
if(onFocus){
聚焦(事件);
}
};
const handleMouseUp=(事件)=>{
rippleRef.current.stop(事件);
如果(onMouseUp){
onMouseUp(事件);
}
};
常量handleMouseDown=(事件)=>{
rippleRef.current.start(事件);
if(onMouseDown){
onMouseDown(事件);
}
};
返回(
{儿童}
);
});
导出默认函数App(){
返回(
按钮1


log(“一些额外的onFocus功能”)} > 按钮2 ); }

我们可以创建对物料ui
按钮的
操作的引用,并使用
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>
  );
}

你可以在这个

中找到演示。嗨,Ryan,这很好,而且正是我要求的。但是使用这个应用“disableTouchRipple”道具的解决方案有一个问题:现在按钮不再有点击动画。你知道我如何从按钮库访问“rippleRef”,以便我自己触发涟漪吗?或者有没有一种方法可以让点击动画再次工作?点击动画的意思是,当你点击时,焦点涟漪会立即开始;尽管我意识到这是不同的——点击一个已经有焦点的按钮不会提供任何反馈。我找不到一种方法让焦点涟漪在没有
di的情况下为点击工作sableTouchRipple
(我尝试了几种方法).Material UI不公开任何访问
rippleRef
的方法。如果您试图通过
触摸Ripplereprops
传递它,那么它会断开
按钮库,因为它无法访问
rippleRef
。如果不更改Material-UI,我看不到任何方法。似乎您是对的。我一直在尝试找到访问它的方法他
rippleRef
但我认为没有一个…这很不幸。现在我想知道,是否可以使用一个单独的
元素自己创建动画?@user3044553是的,可以为点击动画添加一个单独的
元素。我已经更新了我的答案,以包含一个过于简单的元素(不处理
ButtonBase
处理的所有事件)此版本。我面临同样的问题,遗憾的是仍然不起作用,发布了一条谚语“尝试了此方法,并使用ButtonBase的action ref提出了解决方案”
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>