Search code examples
htmlcsstailwind-cssdaisyui

How to prevent visible sliding drawer while shifting HTML direction?


I'm using Daisy UI drawer component in my page but when I try to shift the page direction via JS function the drawer animated visibly from left to right or right to left like the sample code below which is undesirable move, it should be hidden somehow while shifting directions.

I tried to hide it using hidden class but I couldn't find a way to show it again.

I tried the z-index but again I couldn't trigger it back.. I tried <div class="drawer-side invisible peer-checked:visible"> which works a little bit but the drawer is not sliding back again smoothly it just hide itself immediately!

So how to prevent this behavior of the visible sliding drawer while shifting HTML direction and keep the drawer smoothly slide in and out please?

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.min.css" rel="stylesheet" type="text/css" />
  <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
  <label id="lng" class="btn btn-primary drawer-button m-1" onclick="switchDir()">Switch Html Dir</label>

  <div class="drawer">
    <input id="my-drawer" type="checkbox" class="drawer-toggle" />
    <div class="drawer-content">
      <!-- Page content here -->
      <label for="my-drawer" class="btn btn-primary drawer-button m-1">Open drawer</label>
    </div>
    
    <div class="drawer-side">
      <label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
      <ul class="menu p-4 w-80 min-h-full bg-base-200 text-base-content">
        <!-- Sidebar content here -->
        <li><a>Sidebar Item 1</a></li>
        <li><a>Sidebar Item 2</a></li>
      </ul>
    </div>
  </div>

  <script>
    // Function to switch the HTML direction
    function switchDir() {
      let page = document.getElementsByTagName('html')[0];
      if (page.dir == 'rtl') {
        page.dir = 'ltr';
      } else {
        page.dir = 'rtl';
      }
    };
  </script>
</body>


Solution

  • Before the dir change is made, get all the .drawer-side elements and hide them from view:

    const drawers = document.querySelectorAll('.drawer-side');
    drawers.forEach(drawer => {
      drawer.style.display = 'none';
    });
    

    Make the dir change, then wait one render frame before resetting the style. This is so that CSS transitions don't play:

    requestAnimationFrame(() => {
      drawers.forEach(drawer => {
        drawer.style.display = '';
      });
    });
    

    // Function to switch the HTML direction
    function switchDir() {
      let page = document.getElementsByTagName('html')[0];
      
      const drawers = document.querySelectorAll('.drawer-side');
      drawers.forEach(drawer => {
        drawer.style.display = 'none';
      });
    
      if (page.dir == 'rtl') {
        page.dir = 'ltr';
      } else {
        page.dir = 'rtl';
      }
      
      requestAnimationFrame(() => {
        drawers.forEach(drawer => {
          drawer.style.display = '';
        });
      });
    };
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.min.css" rel="stylesheet" type="text/css" />
      <script src="https://cdn.tailwindcss.com"></script>
    </head>
    
    <body>
      <label id="lng" class="btn btn-primary drawer-button m-1" onclick="switchDir()">Switch Html Dir</label>
    
      <div class="drawer">
        <input id="my-drawer" type="checkbox" class="drawer-toggle" />
        <div class="drawer-content">
          <!-- Page content here -->
          <label for="my-drawer" class="btn btn-primary drawer-button m-1">Open drawer</label>
        </div>
        
        <div class="drawer-side">
          <label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
          <ul class="menu p-4 w-80 min-h-full bg-base-200 text-base-content">
            <!-- Sidebar content here -->
            <li><a>Sidebar Item 1</a></li>
            <li><a>Sidebar Item 2</a></li>
          </ul>
        </div>
      </div>
    </body>