primefaces / primereact

The Most Complete React UI Component Library
https://primereact.org
MIT License
6.79k stars 1.04k forks source link

Tabview: Tabs are not styled when use PrimeReact & Tailwind default style #6868

Closed LB-sx closed 2 months ago

LB-sx commented 3 months ago

Describe the bug

When I'm using PrimeReact in unstyled mode with tailwind the tabview is not styled with the default pt tailwind style while it is working for the other components.

image

Reproducer

https://stackblitz.com/edit/q1g8yj

PrimeReact version

10.7.0

React version

18.x

Language

TypeScript

Build / Runtime

Vite

Browser(s)

Edge & Chrome 126

Steps to reproduce the behavior

Execute the Stackblitz, as an output the tabView tabs are shown unstyled.

Expected behavior

Default Tailwind style to be applied.

eklee commented 2 months ago

Still happening on the latest 10.8.2 build. I tried passing in the default tabview styling (here: https://github.com/primefaces/primereact/blob/e99a280091851ec8a80b5677ead6690edc571e78/components/lib/passthrough/tailwind/index.js#L237) manually and it also doesn't work. Any ideas on how to workaround this?

melloware commented 2 months ago

@gcko @ivanpajon need some more Tailwind expertise here.

ivanpajon commented 2 months ago

I downloaded to local the reproducer and without any change it works fine for me.

image

But the fact that in the reproducer looks bad is weird... As a workaround maybe you @LB-sx @eklee can try this:

image

melloware commented 2 months ago

@LB-sx could it just be a StackBlitz thing with Tailwind?

eklee commented 2 months ago

Interestingly, adding 'unstyled' and the pt properties seem to work. But visually there seems to be issue when a tab is clicked: a highlighted border is drawn around the tab name (this doesn't happen on the styled theme version):

image

LB-sx commented 2 months ago

@eklee it is exactly the workaround I am using at the moment.

Interestingly, adding 'unstyled' and the pt properties seem to work. But visually there seems to be issue when a tab is clicked: a highlighted border is drawn around the tab name (this doesn't happen on the styled theme version):

image

LB-sx commented 2 months ago

@LB-sx could it just be a StackBlitz thing with Tailwind?

No I am currently prototyping a framework including PrimeReact in a R&D project, and I'm facing this issue in this project

melloware commented 2 months ago

Its weird you shouldn't have to add unstyled if you are in unstyled mode. Something has to be wrong with TabView.

melloware commented 2 months ago

@gcko any chance you can look at this one too. This is very strange.

gcko commented 2 months ago

@gcko any chance you can look at this one too. This is very strange.

Sure I'll check it out in a bit

gcko commented 2 months ago

Ahh, so this is related to TabView and TabPanel @melloware @eklee @LB-sx

Yea I ran into this issue back when it was first released in November, and I handled it locally. I guess I should look at addressing it directly in the PrimeReact codebase 🤔

While I am working on that, here is my current solution (in Typescript)

export const tabPanelPassThrough = (contentClassNames = '') => {
  const headerActionClassnames = (
    parent: TabViewPassThroughMethodOptions,
    context: TabViewContext,
  ) => {
    return classNames(
      'items-center cursor-pointer flex overflow-hidden relative select-none text-decoration-none user-select-none', // Flex and overflow styles.
      'border-b-2 p-2 font-medium rounded-t-lg transition-shadow duration-200 m-0', // Border, padding, font, and transition styles.
      'transition-colors duration-200', // Transition duration style.
      'focus:outline-none focus:outline-offset-0 focus:shadow-[inset_0_0_0_0.2rem_rgba(147,197,253,0.5)]', // Focus styles.
      {
        // Below are for the INACTIVE tab
        'border-slate-700 bg-blue-900 text-white/60 hover:bg-blue-900 hover:text-white/80':
          parent.state.activeIndex !== context.index, // Condition-based hover styles.
        // Below are for the ACTIVE Tab
        'bg-blue-900 border-blue-900 text-white': parent.state.activeIndex === context.index, // Condition-based active styles.
      },
    );
  };
  return {
    header: ({ props }: { props: TabPanelProps }) => ({
      className: classNames('mr-0', {
        'cursor-default pointer-events-none select-none user-select-none opacity-60':
          props.disabled,
      }), // Margin and condition-based styles.
    }),
    headerAction: ({
      parent,
      context,
    }: {
      parent: TabViewPassThroughMethodOptions;
      context: TabViewContext;
    }) => ({
      className: headerActionClassnames(parent, context),
      style: { marginBottom: '-.5rem' }, // Negative margin style.
    }),
    headerTitle: {
      className: classNames('leading-none whitespace-nowrap'), // Leading and whitespace styles.
    },
    content: {
      className: classNames(
        'bg-gray-900 p-2 border-slate-700 text-white/80 rounded-bl-2xl rounded-br-2xl',
        'overflow-y-auto scrollbar-styled',
        contentClassNames,
      ), // Background, padding, border, and text styles.
    },
  };
};

Below is a basic example of of this in use:

import { ReactNode, useMemo } from 'react';
import { TabPanel, TabView } from 'primereact/tabview';
import { tabPanelPassThrough } from 'path/to/tabPanelPassThrough';

interface TabItem {
  header: string;
  node: ReactNode;
}

export default function TDPanel(): ReactNode {
  const tabs: TabItem[] = useMemo(
    () => [
      { header: 'Risk', node: <div className="min-h-72">Risk</div> },
      { header: 'Spot', node: <div className="min-h-72">Spot</div> },
      { header: 'Loan', node: <div className="min-h-72">Loan</div> },
    ],
    [],
  );
  return (
    <div>
      <TabView>
        {tabs.map((t) => (
          <TabPanel header={t.header} key={t.header} pt={tabPanelPassThrough()}>
            {t.node}
          </TabPanel>
        ))}
      </TabView>
    </div>
  );
}
melloware commented 2 months ago

@gcko thank you a PR would be welcome!