React - CSS Modules como props de estilo para un componente
El problema a resolver es el siguiente. Supongamos que creamos un componente, en este caso SelectableList
, que recibe un array de elementos y permite seleccionar uno o varios elementos de la lista. Este componente tiene un estilo por defecto, pero queremos que el usuario pueda pasar un objeto de estilos personalizados a través de props y que ese objeto provenga de un archivo de estilos CSS Modules.
El código de SelectableList
es el siguiente:
import { useState, useEffect } from "react";
import defaultStyles from "./SelectableList.module.css";
interface SelectableListProps {
items: string[];
onSelectionChange?: (selectedItems: string[]) => void;
styles?: { [key: string]: string }; // Objeto para los estilos
mode?: "single" | "multiple";
}
export default function SelectableList({
items,
onSelectionChange,
styles = defaultStyles,
mode = "single",
}: SelectableListProps) {
const [selectedItems, setSelectedItems] = useState<string[]>([]);
// Llamamos a la función de callback cuando cambia la selección
useEffect(() => {
if (onSelectionChange) {
onSelectionChange(selectedItems);
}
}, [selectedItems, onSelectionChange]);
function toggleItemSelection(item: string) {
if (mode === "single") {
setSelectedItems([item]);
return;
}
if (mode === "multiple") {
setSelectedItems((prevSelected) =>
prevSelected.includes(item)
? prevSelected.filter((selectedItem) => selectedItem !== item)
: [...prevSelected, item]
);
}
}
return (
<div>
{items.map((item, index) => (
<div
key={index}
onClick={() => toggleItemSelection(item)}
className={`${styles.item} ${
selectedItems.includes(item)
? styles.selected
: styles.notSelected
}
`}
>
{item}
</div>
))}
</div>
);
}
Si al usarse el componente no se pasa un objeto de estilos personalizados,styles
tomara los defaultStyles
definidos en SelectableList.module.css
para pasarlos como clases a los elementos del componente.
En cambio, si utilizamos el componente del siguiente modo:
import customStyles from "./customStyles.module.css";
//...
<SelectableList
items={itemsList}
onSelectionChange={handleSelectionChange}
styles={customStyles}
mode="single"
/>;
//...
Los estilos seran tomados del objeto customStyles
proveniente de customStyles.module.css
.