Open BenoitSafari opened 2 months ago
J'ai avancé sur l'Input, j'ai juste quelques soucis avec le CSS pour le SVG, je ne suis pas trop sûr de comment faire, j'ai fait un premier push
J'ai avancé sur l'Input, j'ai juste quelques soucis avec le CSS pour le SVG, je ne suis pas trop sûr de comment faire, j'ai fait un premier push
Tu as plusieurs possibilitées, une piste assez simple est transformer ton svg en composant
function SvgIcon() {
return(
<svg width="16" height="17" viewBox="0 0 16 17" xmlns="http://www.w3.org/2000/svg">
<path d="M11.7429 10.843C12.7112 9.52166 13.1449 7.88346 12.9572 6.25612C12.7695 4.62878 11.9743 3.13231 10.7307 2.0661C9.48701 0.999892 7.88665 0.442575 6.24973 0.505648C4.61282 0.568721 3.06008 1.24753 1.90217 2.40628C0.744249 3.56502 0.0665484 5.11825 0.00464653 6.75521C-0.0572553 8.39216 0.501207 9.99213 1.56831 11.235C2.6354 12.4779 4.13244 13.272 5.75992 13.4586C7.38739 13.6451 9.02528 13.2102 10.3459 12.241H10.3449C10.3742 12.281 10.4069 12.3193 10.4429 12.356L14.2929 16.206C14.4804 16.3936 14.7348 16.4991 15 16.4992C15.2653 16.4993 15.5198 16.394 15.7074 16.2065C15.895 16.019 16.0005 15.7646 16.0006 15.4993C16.0007 15.2341 15.8954 14.9796 15.7079 14.792L11.8579 10.942C11.8222 10.9058 11.7837 10.8733 11.7429 10.843ZM12.0009 6.99897C12.0009 7.72124 11.8586 8.43644 11.5822 9.10373C11.3058 9.77102 10.9007 10.3773 10.39 10.8881C9.87926 11.3988 9.27295 11.8039 8.60566 12.0803C7.93837 12.3567 7.22317 12.499 6.5009 12.499C5.77863 12.499 5.06343 12.3567 4.39614 12.0803C3.72885 11.8039 3.12253 11.3988 2.61181 10.8881C2.10109 10.3773 1.69596 9.77102 1.41956 9.10373C1.14316 8.43644 1.0009 7.72124 1.0009 6.99897C1.0009 5.54028 1.58036 4.14133 2.61181 3.10988C3.64326 2.07843 5.04221 1.49897 6.5009 1.49897C7.95959 1.49897 9.35853 2.07843 10.39 3.10988C11.4214 4.14133 12.0009 5.54028 12.0009 6.99897Z" fill="currentColor"/>
</svg>
)
}
Mais dans notre cas on va ré-utiliser pas mal d'assets au format SVG pour nos icones, ce qui implique de rendre ce composant plus generique. Une solution que j'aime bien dans ce cas la c'est d'assigner a mon composants des "sous-composants".
// PropsMapper (donne ses props a ses childs)
export default function usePropsMapper<T extends (Partial<unknown> & React.Attributes) & PropsWithChildren>(
{ children: childFromProps, ...props }: T,
children?: React.ReactNode | undefined,
) {
return React.useMemo(
() =>
React.Children.map(children ?? childFromProps, c =>
React.isValidElement(c) ? React.cloneElement(c, { ...convertToHtmlAttributes(props) }) : c,
),
[props, children, childFromProps],
);
}
export const convertToHtmlAttributes = (props: Record<string, unknown>) => {
for (const key in props) if (typeof props[key] === 'boolean') props[key] = props[key].toString();
return props;
};
// Composant de base
export default function SdBaseIcon(props: Props) {
const resolved = useProps(props, 'SdIcon'); // Equivalent a notre useClassNames
return usePropsMapper(resolved);
}
// Exemple d'une icone
export const SearchIcon = (props: SdIconProps) => (
<SdBaseIcon {...props}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0" />
</svg>
</SdBaseIcon>
);
// index.ts
import Component from './SdBaseIcon';
import { SearchIcon } from './icons/SearchIcon';
export { type SdIconProps } from './types';
export const SdIcon = Object.assign(Component, { SearchIcon });
// Utilisation
<div>
<SdIcon.AccountIcon />
<SdIcon.SearchIcon />
ect...
</div>
Pour les choses que je n'ai pas trop compris :
export default function SdBaseIcon(props: Props) {
const resolved = useProps(props, 'SdIcon'); // Equivalent a notre useClassNames
return usePropsMapper(resolved);
}
useProps renvoie bien une chaine de caractères ? comme useClassNames dans notre projet ?
Si c'est le cas, je ne comprends pas trop ce qu'est SdBaseIcon :
<SdBaseIcon {...props}>
est ce que c'est un véritable élément HTML ? ou bien c'est un bloc 'invisible' qui ne fait qu'envoyer ces props à la balise enfant (ici le svg) ?
Et le usePropsMapper est bien une fonction générique qui permet de transmettre les props au childs, et qu'importe le parent et le children ?
Pour les choses que je n'ai pas trop compris :
export default function SdBaseIcon(props: Props) { const resolved = useProps(props, 'SdIcon'); // Equivalent a notre useClassNames return usePropsMapper(resolved); }
useProps renvoie bien une chaine de caractères ? comme useClassNames dans notre projet ?
Si c'est le cas, je ne comprends pas trop ce qu'est SdBaseIcon :
<SdBaseIcon {...props}>
est ce que c'est un véritable élément HTML ? ou bien c'est un bloc 'invisible' qui ne fait qu'envoyer ces props à la balise enfant (ici le svg) ?
Et le usePropsMapper est bien une fonction générique qui permet de transmettre les props au childs, et qu'importe le parent et le children ?
useProps
resoud toutes les props et notament les classes et usePropsMapper
transfert les props. Ce qui me permet de ne traiter mes props qu'une seule fois, mais ce n'est pas important. SdBaseIcon
est bien un composant React mais il n'a aucune balise HTML, c'est comme si je faisait un composant qui rend un children dans un fragment => <>{children}</>
Ce qu'il faut retenir c'est que SdBaseIcon a sa feuille de style et resoud les props de n'importe quelle icone. On peut soit avoir un composant qui ne rend que son children
et qui lui transfert ses props (comme ce que je fais dans l'exemple a l'aide du mapper), soit rendre la balise SVG et son children en resolvant les classes.
On veut traiter les props qu'une seule fois avec un composant "maitre" (ici SdBaseIcon) et ensuite appeller ce composant pour chaque icone.
Pour cette issue je vais voir avec toi quand j'aurais un peu de temps, je n'arrive pas à passer 'disabled' dans la class de la searchBar
L'input fonctionne correctement, mais je n'ai pas réussi à inclure le propsMapper dedans, Je voudrais bien regarder avec toi à l'occas pour rendre le code plus générique :) Je me lance dans l'issue 8
Input component
Créer un composant web "Input Search" ré-utilisable.
Criteres d'acceptation
value
/onChange
sont controllables par un les props du composantStyle
Maquette
Assets
L'icone SVG