tremorlabs / tremor

React components to build charts and dashboards
https://npm.tremor.so
Apache License 2.0
16.16k stars 465 forks source link

[Bug]: The selected elements don't change their background color #1067

Closed alamenai closed 4 months ago

alamenai commented 4 months ago

Tremor Version

3.11.0

Link to minimal reproduction

None

Steps to reproduce


  <MultiSelect
          defaultValue={selectDefaultRoofs}
          icon={InspectIcon}
          className='[&>*]:h-12
                  [&>button>div>div>div]:bg-blue-900 
                  [&>button>div>div>div>div]:text-white 
                    [&>button>div>div>div>div]:text-base 
                  [&>button>div>div_svg]:stroke-white'
          onValueChange={(values) => selectRoof(values)}
          placeholder='Wählen Sie ein Dach aus'
          placeholderSearch='Suchen'
        >

What is expected?

It was like this ( And it's on production ):

image

What is actually happening?

I did not change anything but it became like this :

image

What browsers are you seeing the problem on?

Chrome, Firefox

Any additional comments?

This is the full code :

"use client"

import { MultiSelect, MultiSelectItem } from "@tremor/react"
import { Info, InspectIcon } from "lucide-react"
import { useParams } from "next/navigation"
import { useEffect, useMemo } from "react"
import { useDispatch, useSelector } from "react-redux"

import { RootState } from "@/redux/store"

import { InfoDialog } from "@/components/core/info-dialog"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"

import { SELECTED_ROOFS_DESCRIPTION } from "../info"
import { Roof, updateSelectedRoofs } from "../state/slice"

/* eslint-disable */

export function SelectRoofs({ roofs }: { roofs: Roof[] }) {
  const params = useParams()

  const dispatch = useDispatch()

  const id = params.id as string

  const addressId: number | undefined = useSelector((state: RootState) => state.user.address.addressId)

  const initialSelectedRoofs: Roof[] | undefined = useSelector(
    (state: RootState) => state.customInstallation.selectedRoofs
  )

  const selectRoof = (values: string[]) => {
    const selectedRoofs = roofs.filter((roof) => values.includes(roof.roofId.toString()))
    dispatch(updateSelectedRoofs(selectedRoofs))
  }

  // When the id is changed from the URL
  // The selected roofs should be updated based on the roofs prop
  // The roof prop is coming from the API
  useEffect(() => {
    if (addressId !== parseInt(id)) {
      dispatch(updateSelectedRoofs(roofs))
    }
  }, [id])

  useEffect(() => {
    if (!initialSelectedRoofs) {
      dispatch(updateSelectedRoofs(roofs))
    }
  }, [])

  // Select the default selected roofs based on the initial state or props

  const selectDefaultRoofs = useMemo(() => {
    // When the id is changed from the URL
    if (!initialSelectedRoofs || addressId !== parseInt(id)) {
      return roofs.map(({ roofId }) => roofId.toString())
    }

    // Whne the page is refreshed
    return initialSelectedRoofs.map(({ roofId }) => roofId.toString())
  }, [addressId, id, initialSelectedRoofs])

  return (
    <Card className='w-full mx-auto rounded-2xl'>
      <CardHeader>
        <div className='flex justify-between'>
          <CardTitle className='text-base font-medium'>Dachauswahl</CardTitle>
          <InfoDialog title='Dachauswahl'>
            <p className='text-sm leading-7'>{SELECTED_ROOFS_DESCRIPTION}</p>
          </InfoDialog>
        </div>
        <CardDescription className='text-[13px]'>Wählen Sie ein oder mehrere Dächer aus.</CardDescription>
      </CardHeader>
      <CardContent>
        <MultiSelect
          defaultValue={selectDefaultRoofs}
          icon={InspectIcon}
          className='[&>*]:h-12
                  [&>button>div>div>div]:bg-blue-900 
                  [&>button>div>div>div>div]:text-white 
                    [&>button>div>div>div>div]:text-base 
                  [&>button>div>div_svg]:stroke-white'
          onValueChange={(values) => selectRoof(values)}
          placeholder='Wählen Sie ein Dach aus'
          placeholderSearch='Suchen'
        >
          {roofs?.map(({ roofId }) => (
            <MultiSelectItem className='text-lg font-bold' key={roofId} value={roofId.toString()}>
              {roofId.toString()}
            </MultiSelectItem>
          ))}
        </MultiSelect>

        {initialSelectedRoofs?.length === 0 ? (
          <div className='flex items-center mt-2'>
            <Info className='stroke-red-500 w-4 h-4 mr-2' />
            <p className='text-red-500 text-sm'>Bitte wählen Sie mindestens ein Dach aus</p>
          </div>
        ) : null}
      </CardContent>
    </Card>
  )
}
alamenai commented 4 months ago

After I Inspected the MultiSelected, I have found that I have to change the CSS classess hierarchy to be like this :


 <MultiSelect
          defaultValue={selectDefaultRoofs}
          icon={InspectIcon}
          className='[&>div]:h-12 [&>div>div>button]:h-12 
                   [&>div>div>button>div>div>div]:bg-blue-900         
                   [&>div>div>button>div>div>div]:border-slate-950                
                   [&>div>div>button>div>div>div]:text-white
                     [&>div>div>button>div>div>div>div]:text-base
                   [&>div>div>button>div>div>div>div>svg]:stroke-white'
          onValueChange={(values) => selectRoof(values)}
          placeholder='Wählen Sie ein Dach aus'
          placeholderSearch='Suchen'
        >
          {roofs?.map(({ roofId }) => (
            <MultiSelectItem className='text-lg font-bold' key={roofId} value={roofId.toString()}>
              {roofId.toString()}
            </MultiSelectItem>
          ))}
        </MultiSelect>