0

I have been working on Ant Carousel :- https://ant.design/components/carousel/ . Carousel is placed inside a Modal. I have few children div. Initially arrow keys do not work for navigation. If I click on content of div, then they start to work.

But if div contains image, when clicked on it focus is not set to carousel, also if there is any other text in that div or slide, clicking it sets carousel as focus.

I have tried using focusOnSelect of carousel. Also set refs to Carousel then called this.xyzRef.current.focus() on componentDidMount() but it gives me

error :- A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://reactjs.org/docs/cross-origin-errors.html

code :- https://codesandbox.io/s/pmww228ynj

//JSX file

export default class ABCD extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = React.createRef();
    };


  componentDidMount() {
    console.log(this.textInput);
  }

  render() {
    return (
      <Modal visible wrapClassName="abc">
        <Carousel
          id="abc"
          ref={this.textInput}
          draggable
          arrows
          dots={false}
          onSelectFocus={true}
          infinite={false}
          focusOnSelect
        >
          <div className="slick-slide">
            <div>
              <img
                alt="ads"
                src="https://cdn.pixabay.com/photo/2017/08/30/01/05/milky-way-2695569_960_720.jpg"
              />
              <h3>Page 1</h3>
            </div>
          </div>
          <div>
            <h3>Page 2</h3>
          </div>
          <div>
            <h3>Page 3</h3>
          </div>
          <div>
            <h3>Page 4</h3>
          </div>
        </Carousel>
      </Modal>
    );
  }
}

I expect the output to be able to use left and right arrow keys to navigate in carousel

3 Answers3

0

It seems there is no possible solution for that issue.

And the problem is with antd.

The Carousel in antd is slick and it has no way to set focus on the inner element. And had bad accessibility(can't navigate with tab).

Problem with set focus to inner modal component

0

Use next() and prev() methods given in carousel documentation. Also use action listeners to detect arrow key press.

0

You could capture the after slide event, then trigger the carousel's child method with a delay input.current.focus();

Parent:

class Container extends Component {
    constructor(props) {
        super(props);

        this.state = {
            slide: 0,
            max_slide: 2,
            current_slide_index: 0,
        };
    };

    _nextSlide = (value) =>{
        let slide;
        if( value===null ) slide = this.state.slide + 1;
        else slide = value+1;
        if( slide>=this.state.max_slide ) slide = 0;
        this.setState({slide:slide});
    };

    _onSlid = () =>{
        this.setState({current_slide_index:this.state.slide});
    };

    render() {
        return (
            <React.Fragment>
                <Carousel
                    interval={null}
                    indicators={true}
                    wrap={false}
                    activeIndex={this.state.slide}
                    onSelect={()=>this._nextSlide(null)}
                    onSlid={this._onSlid}
                >
                    <Carousel.Item className="p-3">
                        <StepInput
                            key_for={0}
                            value_key={"first_name"}
                            value_placeholder={"First Name"}
                            label={"What's your first name?"}
                            nextSlide={this._nextSlide}
                            current_slide_index={this.state.current_slide_index}
                            />
                    </Carousel.Item>
                    <Carousel.Item className="p-3">
                        <StepInput
                            key_for={1}
                            value_key={"last_name"}
                            value_placeholder={"Last Name"}
                            label={"What's your last name?"}
                            nextSlide={this._nextSlide}
                            current_slide_index={this.state.current_slide_index}
                            />
                    </Carousel.Item>
                </Carousel>
                <button className="btn btn-outline-secondary" type="button" onClick={()=>this._nextSlide(null)}>Test</button>
            </React.Fragment>
        );
    };
}

export default Container;

Child:

import React, {Component} from 'react';
class StepInput extends Component {
    constructor(props) {
        super(props);

        this.input = React.createRef();

        this.state = {
            current_slide_index: this.props.current_slide_index
        };
    };

    UNSAFE_componentWillReceiveProps = (nextProps) =>{
        if( nextProps.current_slide_index===this.props.key_for ){
            setTimeout(function() {this.input.current.focus();}.bind(this),300);
        }
        this.setState({current_slide_index:nextProps.current_slide_index});
    }

    handleUserInput = (value) => {
        this.setState({value: value});
    }

    render() {
        return (
            <div className="card m-5">
                <div className="card-body">
                    <div className="form-group">
                        <label >{this.props.label}</label>
                        <div className="input-group mb-3">
                            <input ref={this.input} type="text" value={this.state.value} className="form-control" onChange={e=>this.handleUserInput(e.target.value)} />
                        </div>
                    </div>
                </div>
            </div>
        );
    };
}
export default StepInput;
George Peter
  • 69
  • 1
  • 1
  • 6