ui icon indicating copy to clipboard operation
ui copied to clipboard

[Tabs] Tab Component Mobile Responsive Overflow Problem

Open in-ch opened this issue 1 year ago • 6 comments

Hello,

I'm reporting an issue regarding the Tabs component when used in the mobile environment. While there are no problems on laptops or tablets, the issue arises specifically in mobile environments, causing an overflow problem that disrupts the overall layout.

image

To resolve this problem, I'm proposing two potential options:

  1. Adding Overflow Scrolling Effect: Applying the overflow property to the currently overflowing element to add a scrolling effect seems like a good solution. gif

  2. Adding flex-wrap Property: Another option is to add the flex-wrap property to ensure that elements are properly wrapped, allowing for a more responsive layout. image

Related issue

Thank you !!!

in-ch avatar Feb 13 '24 14:02 in-ch

Hi everyone, I have the same issue and we are starting to try to patch it in the quick-and-dirtiest way possible while waiting for an official patch in the component.

@in-ch do you have a snippet of 1 of the 2 solutions so that we can patch our responsive overflow problem please :pray: ?

Thisisjuke avatar Mar 18 '24 11:03 Thisisjuke

Hi everyone, I have the same issue and we are starting to try to patch it in the quick-and-dirtiest way possible while waiting for an official patch in the component.

@in-ch do you have a snippet of 1 of the 2 solutions so that we can patch our responsive overflow problem please 🙏 ?

@Thisisjuke

interface TabValue {
  value: string;
  title: string;
  content: JSX.Element;
}

interface FAQTabsProps {
  data: TabValue[];
}

/**
 * @param {TabValue[]} data - List of tab data
 * @description FAQTabs component
 * @returns {JSX.Element}
 */
export default function FAQTabs({ data }: FAQTabsProps {
  const tabsScrollRef = useRef<HTMLDivElement | null>(null);
  const tabRef = useRef<HTMLDivElement | null>(null);

  /**
   * @param {number} index - Index of the clicked tab
   * @description Scrolls through tabs with animation when tab is clicked
   * @returns {void}
   */
  const tabScrollToIndex = (index: number): void => {
    const tabWidth = (tabRef as MutableRefObject<HTMLDivElement>).current.offsetWidth;
    const targetScrollLeft = (tabWidth * index) / 2;
    const startScrollLeft = (tabsScrollRef as MutableRefObject<HTMLDivElement>).current.scrollLeft;

    const animateScroll = (timestamp: number) => {
      const progress = Math.min(1, (timestamp - startTime) / duration);
      const newScrollLeft = startScrollLeft + progress * (targetScrollLeft - startScrollLeft);
      (tabsScrollRef as MutableRefObject<HTMLDivElement>).current.scrollLeft = newScrollLeft;

      if (progress < 1) {
        requestAnimationFrame(animateScroll);
      }
    };

    const duration = 200; // Duration of animation (ms)
    const startTime = performance.now();

    requestAnimationFrame(animateScroll);
  };

  /**
   * @param {number} index - Index of the clicked tab
   * @description Handles tab click event to scroll with animation
   * @returns {void}
   */
  const handleTabsTriggerClick = (index: number): void => {
    if (tabsScrollRef.current) {
      tabScrollToIndex(index);
    }
  };
  return (
    <ContentLayout className="mt-4">
      <Tabs defaultValue={data[0].value}>
        <TabsList scrollRef={tabsScrollRef}>
          {data.map((tab, index) => (
            <TabsTrigger
              onClick={() => handleTabsTriggerClick(index)}
              key={`tab-trigger-${tab.title}-${index}`}
              value={tab.value}
              ref={tabRef as Ref<HTMLButtonElement>}
            >
              {tab.title}
            </TabsTrigger>
          ))}
        </TabsList>
        {data.map((tab, index) => (
          <TabsContent
            className="w-full"
            key={`tab-content-${tab.title}-${index}`}
            value={tab.value}
          >
            {tab.content}
          </TabsContent>
        ))}
      </Tabs>
    </ContentLayout>
  );
}

FAQTabs.displayName = 'FAQTabs';

If the number of tabs increases, the code will need modifications. Currently, the code functions well with five tabs, but if there are more tabs, adjustments will be necessary. 😃

in-ch avatar Mar 18 '24 13:03 in-ch

Any update on this?

VenoM9078 avatar Apr 05 '24 12:04 VenoM9078

Yeah running into this issue as well, will patch on my end but should be default functionality

calebpeffer avatar May 02 '24 19:05 calebpeffer

I get somewhat workable code as:

<TabsList className='flex items-center justify-start flex-wrap h-auto space-y-1'> </TabsList>

abubakerx1da49 avatar May 18 '24 04:05 abubakerx1da49

@Abubakersiddique761 thanks, that worked for me. Here what I am doing,

<TabsList className="w-[464px] overflow-x-auto items-center justify-start">
          {toolTabs.map((t) => (
            <TabsTrigger
              key={t.link}
              value={t.link}
              onClick={() => setSelectedTab(t.link)}
            >
              {t.title}
            </TabsTrigger>
          ))}
        </TabsList>

heypran avatar May 18 '24 18:05 heypran

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jun 27 '24 23:06 shadcn