react-tailwindcss-select
react-tailwindcss-select copied to clipboard
some idea of label styles (highlighting searchinput value) with preview sceenshot
Hi there π Thanks for woderful components. I have some idea for label styles. (highlight searchinput value) If you like it, i will make a PR
Preview
before
highlight
Some Code
Item.tsx
import React, { useCallback, useMemo } from 'react';
import DisabledItem from './DisabledItem';
import { useSelectContext } from './SelectProvider';
import { Option } from './type';
import { COLORS, DEFAULT_THEME, THEME_DATA } from '../constants';
interface ItemProps {
item: Option;
primaryColor: string;
searchInput?: string;
}
const Item: React.FC<ItemProps> = ({ item, primaryColor, searchInput }) => {
const { classNames, value, handleValueChange, formatOptionLabel } =
useSelectContext();
const isSelected = useMemo(() => {
return (
value !== null && !Array.isArray(value) && value.value === item.value
);
}, [item.value, value]);
const textHoverColor = useMemo(() => {
if (COLORS.includes(primaryColor)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return THEME_DATA.textHover[primaryColor];
}
return THEME_DATA.textHover[DEFAULT_THEME];
}, [primaryColor]);
const bgColor = useMemo(() => {
if (COLORS.includes(primaryColor)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return THEME_DATA.bg[primaryColor];
}
return THEME_DATA.bg[DEFAULT_THEME];
}, [primaryColor]);
const bgHoverColor = useMemo(() => {
if (COLORS.includes(primaryColor)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return THEME_DATA.bgHover[primaryColor];
}
return THEME_DATA.bgHover[DEFAULT_THEME];
}, [primaryColor]);
const getItemClass = useCallback(() => {
const baseClass =
'block transition duration-200 px-2 py-2 pl-5 cursor-pointer select-none truncate rounded';
const selectedClass = isSelected
? `text-white ${bgColor}`
: `text-gray-500 ${bgHoverColor} ${textHoverColor}`;
return classNames && classNames.listItem
? classNames.listItem({ isSelected })
: `${baseClass} ${selectedClass}`;
}, [bgColor, bgHoverColor, classNames, isSelected, textHoverColor]);
// HEREπππ
const getItemLabelWithColor = () => {
if (searchInput) {
const upperSearchInput = searchInput?.toUpperCase();
const start = item.label.indexOf(upperSearchInput);
const end = start + searchInput.length;
const labelArray = item.label.split('');
return labelArray.map((label, idx) => {
if (idx >= start && idx < end) {
<span className={`font-bold text-${primaryColor}-500`}>
{label}
</span>
} else {
return <span>{label}</span>;
}
});
} else {
return item.label;
}
};
//
return (
<>
{formatOptionLabel ? (
<div onClick={() => handleValueChange(item)}>
{formatOptionLabel({ ...item, isSelected })}
</div>
) : (
<>
{item.disabled ? (
<DisabledItem>{item.label}</DisabledItem>
) : (
<li
aria-selected={isSelected}
role='option'
onClick={() => handleValueChange(item)}
className={getItemClass()}
>
{/* {item.label} */}πππ
{getItemLabelWithColor()}
</li>
)}
</>
)}
</>
);
};
export default Item;