diff --git a/client/src/components/Button/_variables.scss b/client/src/components/Button/_variables.scss new file mode 100644 index 000000000..43478b11b --- /dev/null +++ b/client/src/components/Button/_variables.scss @@ -0,0 +1,3 @@ +/// Marge entre l'icône et le texte des boutons (quand il y en a une, d'icône) +/// @type Number +$icon-margin: 0.3571rem !default; diff --git a/client/src/components/Button/index.scss b/client/src/components/Button/index.scss new file mode 100644 index 000000000..ad690e4a5 --- /dev/null +++ b/client/src/components/Button/index.scss @@ -0,0 +1,21 @@ +@use './variables' as *; + +.Button { + // - Icône + &::before, + &__icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.1em; + height: 1.1em; + font-size: 1.1em; + line-height: 1.35em; + text-align: center; + vertical-align: -0.05rem; + } + + &__icon + &__content { + margin-left: $icon-margin; + } +} diff --git a/client/src/components/Button/index.tsx b/client/src/components/Button/index.tsx new file mode 100644 index 000000000..9b212060d --- /dev/null +++ b/client/src/components/Button/index.tsx @@ -0,0 +1,78 @@ +import './index.scss'; +import { toRefs, computed } from '@vue/composition-api'; +import Icon from '@/components/Icon'; + +import type { Component, SetupContext } from '@vue/composition-api'; +import type { Props as IconProps } from '@/components/Icon'; + +type Props = { + /** + * Le type de bouton pour l'attribut `type` de la balise ` + ); + }; +}; + +Button.props = { + htmlType: { + default: 'button', + validator: (value: unknown) => ( + typeof value === 'string' && + ['button', 'submit', 'reset'].includes(value) + ), + }, + icon: { type: String, default: undefined }, + disabled: { type: Boolean, default: false }, +}; + +export default Button; diff --git a/client/src/components/FormField/index.scss b/client/src/components/FormField/index.scss index 6952cc743..a29dc5142 100644 --- a/client/src/components/FormField/index.scss +++ b/client/src/components/FormField/index.scss @@ -25,6 +25,10 @@ width: 90%; } + &__switch { + display: flex; + } + &__addon { display: inline-block; min-width: 2.7rem; diff --git a/client/src/components/Icon/index.tsx b/client/src/components/Icon/index.tsx new file mode 100644 index 000000000..d2785370a --- /dev/null +++ b/client/src/components/Icon/index.tsx @@ -0,0 +1,44 @@ +import { toRefs, computed } from '@vue/composition-api'; + +import type { Component } from '@vue/composition-api'; + +export type Props = { + /** + * Le nom de l'icône à afficher. + * + * Pour une liste exhaustive des codes, voir : https://fontawesome.com/v5.15/icons?m=free + */ + name: string, + + /** Quelle variante faut-il utiliser pour l'icône ? */ + variant?: 'regular' | 'solid' | 'brands', + + /** Des éventuelles classes supplémentaires qui seront ajoutées au component. */ + class?: string, +}; + +const VARIANT_MAP = { + 'regular': 'far', + 'solid': 'fas', + 'brands': 'fab', +} as const; + +// @vue/component +const Icon: Component = (props: Props) => { + const { name, variant } = toRefs(props as Required); + const baseClass = computed(() => VARIANT_MAP[variant.value]); + return () =>