skip to Main Content

the problem is that when ever in focusing the password input the button show up but when i try to click the button its lose the focus on the input and then the button disappear.

<div className='input-wrapper'>
      <input
        onFocus={() => setShowButton(true)}
        onBlur={() => setShowButton(false)}
        title='password'
        type={
          type === 'password' && toggle ?
            "text" : "password"
        }
        {...props}
      />
      {showButton && <button
        type='button'
        className={type === 'password' ? "password" : ""}
        onClick={() => setToggle(!toggle)}
      >
        {toggle ? <ShowPasswordIcon /> : <HidePasswordIcon />}
      </button>}
    </div>

well i want that the button will be somehow included in the input focus (if that make sense somehow)

2

Answers


  1. I believe you are looking for :focus-within:

    .input-wrapper button {
      display: none;
    }
    .input-wrapper:focus-within button {
      display: inline-block;
    }
    

    React example, with focus management:

    const { useState, useRef, useEffect } = React
    
    const App = () => {
      const [showPassword, setShowPassword] = useState(false)
      const toggle = () => setShowPassword((prev) => !prev)
      const input = useRef(null)
      const wrapper = useRef(null)
      useEffect(() => {
        if (input && wrapper) {
    
          // set cursor at end of input
          const l = input.current.value.length
          if (l) {
            input.current.setSelectionRange(l, l)
          }
    
          // prevent focusing on initial render
          if (wrapper.current.contains(document.activeElement)) {
            input.current.focus()
          }
        }
      }, [showPassword])
    
      return (
        <div className="input-wrapper" ref={wrapper}>
          <input
            type={showPassword ? 'text' : 'password'}
            defaultValue="password"
            ref={input}
          />
          <button onClick={toggle}>
            {showPassword ? 'Hide' : 'Show'}
          </button>
        </div>
      )
    }
    
    ReactDOM.createRoot(root).render(<App />)
    .input-wrapper button {
      display: none;
    }
    .input-wrapper:focus-within button {
      display: inline-block;
    }
    <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
    <div id="root"></div>
    Login or Signup to reply.
  2. You can use the css pseudo-class :focus-within on the wrapper. When the wrapper on any of it’s children (button / input) is focused, the button would be visible:

    .input-wrapper:not(:focus-within) > button {
      display: none;
    }
    <div class="input-wrapper"> <!-- className in JSX -->
      <input>
      
      <button>Toogle</button>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search