Skip to content

Commit 3f70e3e

Browse files
committed
refactor(Icon): migrate to script setup syntax
1 parent b6f0a52 commit 3f70e3e

File tree

1 file changed

+61
-62
lines changed

1 file changed

+61
-62
lines changed

src/components/Icon.vue

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
<script lang="ts">
2-
import { defineComponent, computed, type PropType } from 'vue'
3-
import icons, { DEPRECATED_ICONS } from './icons'
4-
import { type IconSize, type IconIdentifier, type AnyIconName } from './icons/types'
5-
62
export type {
73
IconSize,
84
IconName,
@@ -17,79 +13,82 @@ export type {
1713
LgIconId,
1814
OtherIconId
1915
} from './icons/types'
16+
</script>
17+
18+
<script setup lang="ts">
19+
import { computed } from 'vue'
20+
import icons, { DEPRECATED_ICONS } from './icons'
21+
import { type IconSize, type IconIdentifier, type AnyIconName } from './icons/types'
2022
21-
export default defineComponent({
22-
name: 'AIcon',
23-
props: {
23+
defineOptions({
24+
name: 'AIcon'
25+
})
26+
27+
const props = withDefaults(
28+
defineProps<{
2429
/**
25-
* Type-safe icon identifier in format "name-size" (e.g., "search-sm", "check-md")
30+
* Type-safe icon identifier in format "name-size" (e.g., "search-sm", "check-md").
2631
* This is the recommended way to specify icons as it enforces valid name+size combinations.
2732
*/
28-
icon: {
29-
type: String as PropType<IconIdentifier>,
30-
default: undefined
31-
},
33+
icon?: IconIdentifier
3234
/**
33-
* @deprecated Use `icon` prop instead (e.g., icon="search-sm")
34-
* Icon name in PascalCase (e.g. ArrowDown, Warning) or camelCase (e.g. arrowDown, warning)
35+
* @deprecated Use `icon` prop instead (e.g., icon="search-sm").
36+
* Icon name in PascalCase (e.g. ArrowDown, Warning) or camelCase (e.g. arrowDown, warning).
3537
*/
36-
name: {
37-
type: String as PropType<AnyIconName>,
38-
default: undefined
39-
},
38+
name?: AnyIconName
4039
/**
41-
* @deprecated Use `icon` prop instead (e.g., icon="search-sm")
42-
* Icon size - used to set width and height on an `svg` element
40+
* @deprecated Use `icon` prop instead (e.g., icon="search-sm").
41+
* Icon size - used to set width and height on an `svg` element.
4342
*/
44-
size: {
45-
type: String as PropType<IconSize>,
46-
default: 'md'
47-
}
48-
},
49-
setup(props) {
50-
const iconComponent = computed(() => {
51-
let size: IconSize
52-
let name: string
43+
size?: IconSize
44+
}>(),
45+
{
46+
icon: undefined,
47+
name: undefined,
48+
size: 'md'
49+
}
50+
)
5351
54-
if (props.icon) {
55-
// New format: "search-sm" -> extract size from suffix
56-
const lastDash = props.icon.lastIndexOf('-')
57-
size = props.icon.slice(lastDash + 1) as IconSize
58-
// Convert kebab-case name to PascalCase: "arrow-left" -> "ArrowLeft"
59-
name = props.icon
60-
.slice(0, lastDash)
61-
.split('-')
62-
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
63-
.join('')
64-
} else if (props.name) {
65-
// Legacy format
66-
size = props.size
67-
// Capitalize first letter to handle camelCase input
68-
name = props.name.charAt(0).toUpperCase() + props.name.slice(1)
69-
} else {
70-
console.error('[Honeycomb] a-icon: either icon or name prop is required')
71-
return null
72-
}
52+
const iconComponent = computed(() => {
53+
let size: IconSize
54+
let name: string
7355
74-
if (DEPRECATED_ICONS[size].includes(name)) {
75-
console.warn(
76-
`Icon "${name}" in size "${size}" is deprecated and will be removed in the next major version.
77-
Use another supported size or alternative icon, see storybook docs https://honeycomb.archilogic.com`
78-
)
79-
}
56+
if (props.icon) {
57+
// New format: "search-sm" -> extract size from suffix
58+
const lastDash = props.icon.lastIndexOf('-')
59+
size = props.icon.slice(lastDash + 1) as IconSize
60+
// Convert kebab-case name to PascalCase: "arrow-left" -> "ArrowLeft"
61+
name = props.icon
62+
.slice(0, lastDash)
63+
.split('-')
64+
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
65+
.join('')
66+
} else if (props.name) {
67+
// Legacy format
68+
size = props.size
69+
// Capitalize first letter to handle camelCase input
70+
name = props.name.charAt(0).toUpperCase() + props.name.slice(1)
71+
} else {
72+
console.error('[Honeycomb] a-icon: either icon or name prop is required')
73+
return null
74+
}
8075
81-
if (icons[size][name]) {
82-
return icons[size][name]
83-
} else {
84-
console.error(`Icon ${name} of size ${size} does not exist.`, 'Available icons', icons)
85-
return null
86-
}
87-
})
76+
if (DEPRECATED_ICONS[size].includes(name)) {
77+
console.warn(
78+
`Icon "${name}" in size "${size}" is deprecated and will be removed in the next major version.
79+
Use another supported size or alternative icon, see storybook docs https://honeycomb.archilogic.com`
80+
)
81+
}
8882
89-
return { iconComponent }
83+
if (icons[size][name]) {
84+
return icons[size][name]
85+
} else {
86+
console.error(`Icon ${name} of size ${size} does not exist.`, 'Available icons', icons)
87+
return null
9088
}
9189
})
9290
</script>
91+
9392
<template>
9493
<component :is="iconComponent" v-if="iconComponent" aria-hidden class="flex-shrink-0" />
9594
</template>

0 commit comments

Comments
 (0)