fix: button and icon types

`defineProps` somehow collided with the `IconProp` type of fontawesome:

> Expression produces a union type that is too complex to represent.

By using the original type the FontAwesome component types work again. Sadly autocompletion of the icon names doesn't work anymore (since the lib itself types it only as string), but I think because of that union problem that was already broken before.
This commit is contained in:
Dominik Pschenitschni 2025-01-26 18:26:29 +01:00
parent b09d0ab711
commit 1e08e914f9
10 changed files with 36 additions and 76 deletions

View File

@ -43,7 +43,7 @@
</template>
<script lang="ts">
const BASE_BUTTON_TYPES_MAP = {
export const BASE_BUTTON_TYPES_MAP = {
BUTTON: 'button',
SUBMIT: 'submit',
} as const
@ -58,16 +58,16 @@ export type BaseButtonTypes = typeof BASE_BUTTON_TYPES_MAP[keyof typeof BASE_BUT
// the component tries to heuristically determine what it should be checking the props
// NOTE: Do NOT use buttons with @click to push routes. => Use router-links instead!
// NOTE: Do NOT use buttons with @click to push routes. => Define the `to` prop instead to use router-links instead!
import {unrefElement} from '@vueuse/core'
import {ref, type HTMLAttributes} from 'vue'
import type {RouteLocationRaw} from 'vue-router'
import {ref} from 'vue'
import type {RouterLinkProps} from 'vue-router'
export interface BaseButtonProps extends /* @vue-ignore */ HTMLAttributes {
export interface BaseButtonProps {
type?: BaseButtonTypes
disabled?: boolean
to?: RouteLocationRaw
to?: RouterLinkProps['to']
href?: string
openExternalInNewTab?: boolean
}

View File

@ -33,16 +33,24 @@
</BaseButton>
</template>
<script lang="ts">
export const VARIANT_CLASS_MAP = {
primary: 'is-primary',
secondary: 'is-outlined',
tertiary: 'is-text is-inverted underline-none',
} as const
export type ButtonTypes = keyof typeof VARIANT_CLASS_MAP | undefined
</script>
<script setup lang="ts">
import {computed} from 'vue'
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import BaseButton, { type BaseButtonProps } from '@/components/base/BaseButton.vue'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
export type ButtonTypes = keyof typeof VARIANT_CLASS_MAP
export interface ButtonProps extends /* @vue-ignore */ BaseButtonProps {
export interface ButtonProps extends BaseButtonProps {
variant?: ButtonTypes
icon?: IconProp
icon?: FontAwesomeIconProps['icon']
iconColor?: string
loading?: boolean
disabled?: boolean
@ -62,12 +70,6 @@ const props = withDefaults(defineProps<ButtonProps>(), {
defineOptions({name: 'XButton'})
const VARIANT_CLASS_MAP = {
primary: 'is-primary',
secondary: 'is-outlined',
tertiary: 'is-text is-inverted underline-none',
} as const
const variantClass = computed(() => VARIANT_CLASS_MAP[props.variant])
</script>

View File

@ -44,14 +44,14 @@
</template>
<script setup lang="ts">
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
import BaseButton from '@/components/base/BaseButton.vue'
withDefaults(defineProps<{
title?: string
padding?: boolean
closeIcon?: IconProp
closeIcon?: FontAwesomeIconProps['icon']
shadow?: boolean
hasContent?: boolean
loading?: boolean

View File

@ -49,12 +49,12 @@
</template>
<script setup lang="ts">
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
withDefaults(defineProps<{
title: string,
primaryLabel?: string,
primaryIcon?: IconProp,
primaryIcon?: FontAwesomeIconProps['icon'],
primaryDisabled?: boolean,
hasPrimaryAction?: boolean,
tertiary?: string,

View File

@ -39,13 +39,13 @@
<script setup lang="ts">
import {ref} from 'vue'
import {onClickOutside} from '@vueuse/core'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import BaseButton from '@/components/base/BaseButton.vue'
withDefaults(defineProps<{
triggerIcon?: IconProp
triggerIcon?: FontAwesomeIconProps['icon']
}>(), {
triggerIcon: 'ellipsis-h',
})

View File

@ -20,10 +20,10 @@
<script lang="ts" setup>
import BaseButton, {type BaseButtonProps} from '@/components/base//BaseButton.vue'
import Icon from '@/components/misc/Icon'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
export interface DropDownItemProps extends /* @vue-ignore */ BaseButtonProps {
icon?: IconProp,
export interface DropDownItemProps extends BaseButtonProps {
icon?: FontAwesomeIconProps['icon'],
iconClass?: object | string,
disabled?: boolean,
}

View File

@ -94,8 +94,6 @@ import {
} from '@fortawesome/free-regular-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
import type {FontAwesomeIcon as FontAwesomeIconFixedTypes} from '@/types/vue-fontawesome'
library.add(faBold)
library.add(faUndo)
library.add(faRedo)
@ -195,4 +193,5 @@ library.add(faUnderline)
library.add(faFaceLaugh)
// overwriting the wrong types
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
// export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
export default FontAwesomeIcon

View File

@ -44,7 +44,7 @@ import SubscriptionModel from '@/models/subscription'
import type {ISubscription} from '@/modelTypes/ISubscription'
import {success} from '@/message'
import type { IconProp } from '@fortawesome/fontawesome-svg-core'
import type {FontAwesomeIconProps} from '@fortawesome/vue-fontawesome'
const props = withDefaults(defineProps<{
modelValue: ISubscription | null,
@ -92,7 +92,7 @@ const tooltipText = computed(() => {
})
const buttonText = computed(() => props.modelValue ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
const iconName = computed<IconProp>(() => props.modelValue ? ['far', 'bell-slash'] : 'bell')
const iconName = computed<FontAwesomeIconProps['icon']>(() => props.modelValue ? ['far', 'bell-slash'] : 'bell')
const disabled = computed(() => props.modelValue && subscriptionEntity.value !== props.entity || false)
function changeSubscription() {

View File

@ -1,7 +1,6 @@
import type { FunctionalComponent } from 'vue'
import type { Notifications } from '@kyvg/vue3-notification'
// import FontAwesomeIcon from '@/components/misc/Icon'
import type { FontAwesomeIcon as FontAwesomeIconFixedTypes } from './vue-fontawesome'
import type FontAwesomeIcon from '@/components/misc/Icon'
import type XButton from '@/components/input/Button.vue'
import type Modal from '@/components/misc/Modal.vue'
import type Card from '@/components/misc/Card.vue'
@ -10,8 +9,8 @@ import type Card from '@/components/misc/Card.vue'
// See: https://github.com/vuejs/language-tools/wiki/Global-Component-Types
declare module 'vue' {
export interface GlobalComponents {
Icon: FontAwesomeIconFixedTypes
Notifications: FunctionalComponent<Notifications>
Icon: typeof FontAwesomeIcon
Toaster: FunctionalComponent<Notifications>
XButton: typeof XButton,
Modal: typeof Modal,
Card: typeof Card,

View File

@ -1,40 +0,0 @@
// copied and slightly modified from unmerged pull request that corrects types
// https://github.com/FortAwesome/vue-fontawesome/pull/355
import type { FaSymbol, FlipProp, IconLookup, IconProp, PullProp, SizeProp, Transform } from '@fortawesome/fontawesome-svg-core'
import type { DefineComponent } from 'vue'
interface FontAwesomeIconProps {
border?: boolean
fixedWidth?: boolean
flip?: FlipProp
icon: IconProp
mask?: IconLookup
listItem?: boolean
pull?: PullProp
pulse?: boolean
rotation?: 90 | 180 | 270 | '90' | '180' | '270'
swapOpacity?: boolean
size?: SizeProp
spin?: boolean
transform?: Transform
symbol?: FaSymbol
title?: string | string[]
inverse?: boolean
}
interface FontAwesomeLayersProps {
fixedWidth?: boolean
}
interface FontAwesomeLayersTextProps {
value: string | number
transform?: object | string
counter?: boolean
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'
}
export type FontAwesomeIcon = DefineComponent<FontAwesomeIconProps>
export type FontAwesomeLayers = DefineComponent<FontAwesomeLayersProps>
export type FontAwesomeLayersText = DefineComponent<FontAwesomeLayersTextProps>