Is there a way to hide the left/right button once the scroll reaches the end of the container?

I've implemented a tab item list enclosed in a <ul> container with specified max-width and overflow-x properties causing the tab items to overflow.

Below is the foundational code for the <ul> wrapper containing the mapped tab item list:


    <ul className="tabs" ref={wrapperRef}> 
        {tabs.map((tab) => ( 
            <li 
                onClick={() => setActive(tab)} 
                className={`tab ${tab === active ? "active" : ""}`} 
                key={tab}>
                    {tab} 
            </li> 
        ))}
    </ul> 

Furthermore, I have incorporated two absolute positioned buttons on either side that scroll to the ends of the container. These buttons automatically disappear when reaching the respective end of the container. Here is the code snippet:


     <div className="tabs__wrapper">
         <ul className="tabs" ref={wrapperRef}>
             {tabs.map((tab) => (
                 <li 
                     onClick={() => setActive(tab)}
                     className={`tab ${tab === active ? "active" : ""}`}
                     key={tab}>
                         {tab}
                 </li>
             ))}
         </ul>
         
         <button className="left" onClick={() => adjustView("left")}>
             Left
         </button>
         
         <button className="right" onClick={() => adjustView("right")}>
             Right
         </button>
     }
     </div>

The issue arises when manually scrolling the content as the buttons remain hidden based on previous interactions. The desired behavior is for the buttons to dynamically appear or disappear depending on scrolling direction. How can this be achieved?

Additionally, I'd prefer the buttons to disappear only after the scrolling process is completed. Any suggestions on achieving this without conditional button rendering?

For a comprehensive view, the full Sandbox link is provided below: https://codesandbox.io/s/tab-scroll-3tzi80

Answer №1

If you want to achieve this functionality, you can follow these steps (check out the codesandbox for reference):

Firstly, listen for the scroll event:

      <ul className="tabs" ref={wrapperRef} onScroll={handleScroll}>

Calculate whether we are positioned left, right, or in between based on the scroll event parameters, and update the state accordingly:

  const handleScroll = () => {
    if (wrapperRef.current) {
      const { scrollLeft, scrollWidth, clientWidth } = wrapperRef.current;
      switch (scrollLeft + clientWidth) {
        // Scroll is all the way left
        case clientWidth:
          setDisableButton("left");
          break;
        // Scroll is all the way right
        case scrollWidth:
          setDisableButton("right");
          break;
        // Scroll position is somewhere in between
        default:
          setDisableButton("none");
      }
    }
  };
  
  // Adjust the view based on the state
  function adjustView(position) {
    if (position === "left") {
      scrollTabbar(wrapperRef?.current, 0);
    } else {
      scrollTabbar(wrapperRef?.current, wrapperRef.current?.scrollWidth);
    }
  }

In addition, the buttons only disappear once scrolling has finished, ensuring that both buttons are displayed when the view is neither left nor right.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Execute Javascript after modification of the DOM

I have developed two custom directives known as app-content and app-content-item. These directives are intended to be utilized in upcoming projects to provide a basic structure with simple styling. They will be incorporated into a module and should be nest ...

Angular backslash is encoded

Experiencing the same issue as this individual: angularjs-slash-after-hashbang-gets-encoded The URL is getting encoded and not routing correctly, causing it to fall to the otherwise in my route config. I have not been able to identify the root cause yet, ...

Simulation of Submitting Form Arrays in HTML

My goal is to create a basic HTML form that mimics an HTTP POST from an external source. Upon examining the incoming POST data, it appears as follows: array ( 'submission_id' => '1234567890', 'name' => array ( ...

Difficulties arise when trying to align text vertically between two floating images

After running the code, I noticed that the text "Text Here" is positioned at the bottom of the div instead of the top. I have attempted to adjust it using properties like vertical-align, padding, and margin-top within the .subText styling, but so far, I ha ...

In React Typescript, the input type="checkbox" does not show any value in the value attribute

I'm facing an issue with displaying text next to a checkbox in React Typescript. When I try to use the value attribute, it doesn't seem to work as expected. Also, attempting to set innerHTML throws an error stating that input is a void element ta ...

Google Map API using Ajax - {"readyState":4,"status":200,"statusText":"success"} but encountering parsererror

Here is the AJAX call: var url_map = "http://maps.googleapis.com/maps/api/geocode/json?latlng="+lat+","+lon+"&sensor=false?callback?"; $.ajax({ type: "GET", dataType : "json", url: url_map, crossDomain:true, success: ...

"Sweet syntax" for assigning object property if the value is true

In the project I'm working on, I find myself dealing with a lot of parsing and validating tasks. This often results in 5-10+ lines of code like if(value) object.value = value. I considered using object.value = value || (your favorite falsy value) app ...

JavaScript will only recognize the first two elements of an array when used in an if statement

I have recently rebuilt my game in HTML/CSS/JS from scratch, based on an old question. Everything seems to work fine when there is only one player and one brick present. However, as soon as I introduce multiple bricks, things start to go wrong. I used an ...

React Hook Form – Difficulties with error handling when utilizing multiple forms simultaneously in react hook form version 7.5.2

Previously, in the earlier versions of react hook form, multiple forms could function if another form object was created using the following code: const { register: register2, handleSubmit: handleSubmit2, errors: errors2 } = useForm() H ...

Elements powered by jQuery failing to load upon dynamic webpage(s) loading via ajax

Dynamic loading of jQuery elements, such as Ibuttons, seems to be causing issues when implemented with an ajax dynamic content loader. The entirety of my website is rendered through Ajax just like this: <html> <header> {jQuery} </header> ...

Ways to confine the tabindex within a specific div container

I am currently working on identifying examples of bad accessibility practices. Specifically, I am focusing on issues related to Keyboard Focus. The first example I have encountered is the lack of visibility when trying to navigate through a set of buttons. ...

Tips for managing an interval for play, pause, and stop functions in JavaScript or Node.js

In my main file, I have an API to control the playback of a video. main.js const { mainModule } = require('process'); const { startVideo, pauseVideo, stopVideo } = require('./modules/video.js'); function init(payload) { if(payl ...

The Electron/React/Typescript module is missing: Error: Unable to locate 'fs' in the /node_modules/electron directory

Within my Electron application, I have a file named App.ts. It contains the following code snippet: import { ipcRenderer } from 'electron'; // remaining code However, during the app development process, I encountered this error message: Error: ...

I'm having trouble with the DaisyUi navbar; it's not opening the dropdown menu as smoothly as it does on the DaisyUi website when using

Currently, I am experimenting with daisy and tailwind in my project without making many changes to the JavaScript. However, I am facing an issue where it does not behave the same as on the daisyUI website. When I click on 'Parent' in my script, t ...

The essence of typography remains unaltered by primary colors

My goal is to set up global or app-level theming effectively. In theme.js, I have defined the 'primary' color, expecting it to apply to <Typography> as well. // Demo.js import * as React from "react"; import { createTheme, ThemeP ...

I utilized the explode function in PHP to transform a string into an array. Now, I require assistance with manipulating

Currently, I am facing a challenge where I have converted a string into an array in PHP using explode. I need to pass this array to a separate JavaScript page and then access the data values from within. Below is the structure of the array in JavaScript o ...

Collection of clickable images that lead to creatively designed individual pages

Being relatively new to JavaScript and jQuery, my knowledge is solid when it comes to HTML & CSS. Currently, I have a page with 20 minimized pictures (with plans to increase to 500+ images) that open into a new page when clicked. Although I have no issues ...

"Steer clear of using `useEffect` to fetch data upon mounting if the dependency relies on user input

When a React component mounts, the useEffect hook is triggered. However, if this effect relies on user input, running it on mount might be unnecessary. In such cases, would it be acceptable to validate the dependency before executing the hook? Check out t ...

Having issues with ng-repeat not displaying any content

Let me describe the current situation I am facing: app.controller('ResourceController', function($scope, $sce){ var resourceData; $scope.data = ''; $scope.loadResources = function(){ $.get('con ...

Template ID not found

I've been experimenting with integrating Knockout.js to merge an HTML view on a web page with HTML code stored in a database table. Although the database code is successfully appended to the DOM, Knockout seems unable to locate the specified ID. Here ...