22import { computed , defineComponent , PropType } from ' vue'
33import ASpinner from ' ./Spinner.vue'
44import AIcon from ' ./Icon.vue'
5+ import { type IconIdentifier , type AnyIconName } from ' ./icons/types'
56
67type ButtonVariant = ' primary' | ' subtle' | ' standard'
78
89type ButtonSize = ' sm' | ' md' | ' lg' | ' auto'
910
11+ const isIconIdentifier = (str : string ): boolean => {
12+ return / -(sm| md| lg| other)$ / .test (str )
13+ }
14+
1015export default defineComponent ({
1116 name: ' AButton' ,
1217 components: { ASpinner , AIcon },
@@ -45,11 +50,11 @@ export default defineComponent({
4550 * deprecated usage: Boolean
4651 * removes horizontal padding, use size `auto` instead
4752 *
48- * recommended usage: icon name as a String
49- * the icon size will be inferred from the button size prop
53+ * recommended usage: IconIdentifier (e.g., "search-sm", "check-md")
54+ * or icon name as a String (e.g., "Search") where size is inferred from button size
5055 */
5156 icon: {
52- type: [Boolean , String ],
57+ type: [Boolean , String ] as PropType < boolean | AnyIconName | IconIdentifier > ,
5358 default: false
5459 },
5560 /**
@@ -99,9 +104,16 @@ export default defineComponent({
99104 return tagName .value === ' button' && (props .disabled || props .loading )
100105 })
101106
107+ const iconIdentifier = computed (() => {
108+ if (typeof props .icon === ' string' && props .icon .length && isIconIdentifier (props .icon )) {
109+ return props .icon as IconIdentifier
110+ }
111+ return undefined
112+ })
113+
102114 const iconName = computed (() => {
103- if (typeof props .icon === ' string' && props .icon .length ) {
104- return props .icon as import ( ' ./icons/types ' ). AnyIconName
115+ if (typeof props .icon === ' string' && props .icon .length && ! isIconIdentifier ( props . icon ) ) {
116+ return props .icon as AnyIconName
105117 }
106118 return undefined
107119 })
@@ -123,6 +135,7 @@ export default defineComponent({
123135 return {
124136 tagName ,
125137 isDisabled ,
138+ iconIdentifier ,
126139 iconName ,
127140 iconSize ,
128141 ariaLabel
@@ -164,7 +177,10 @@ export default defineComponent({
164177 the value of label prop or an icon
165178 -->
166179 <slot >
167- <template v-if =" !! (iconName && iconSize )" >
180+ <template v-if =" iconIdentifier " >
181+ <a-icon :icon =" iconIdentifier" ></a-icon >
182+ </template >
183+ <template v-else-if =" !! (iconName && iconSize )" >
168184 <a-icon :name =" iconName" :size =" iconSize" ></a-icon >
169185 </template >
170186 <template v-else >{{ label }}</template >
0 commit comments