feat. 버튼 액션별 아이콘 추가

This commit is contained in:
clkim
2025-10-16 10:48:41 +09:00
parent d61f5aa875
commit 15174baa36
6 changed files with 111 additions and 46 deletions

View File

@@ -15,6 +15,10 @@
after:bg-[var(--text-color)] after:opacity-20 after:z-[2]; after:bg-[var(--text-color)] after:opacity-20 after:z-[2];
} }
.btn-base .btn-content {
@apply relative flex items-center gap-1 z-[1];
}
.size-large { .size-large {
@apply px-10 h-16 text-lg; @apply px-10 h-16 text-lg;
} }

View File

@@ -1,9 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ButtonType } from '#layers/types/components/button' import type { ButtonType } from '#layers/types/components/button'
interface ButtonProps { interface props {
type?: ButtonType type?: ButtonType
icon?: string
target?: '_self' | '_blank' target?: '_self' | '_blank'
href?: string href?: string
rel?: string rel?: string
@@ -11,35 +10,15 @@ interface ButtonProps {
backgroundImage?: string backgroundImage?: string
textColor?: string textColor?: string
disabled?: boolean disabled?: boolean
class?: string
} }
const props = withDefaults(defineProps<ButtonProps>(), { const props = withDefaults(defineProps<props>(), {
type: 'action', type: 'action',
backgroundColor: 'var(--primary)', backgroundColor: 'var(--primary)',
textColor: 'var(--alternative-02)', textColor: 'var(--alternative-02)',
disabled: false, disabled: false,
}) })
const buttonClasses = computed(() =>
['btn-base group', props.class].filter(Boolean)
)
const buttonStyles = computed(() => {
const styles: Record<string, string> = {
backgroundColor: props.backgroundColor,
color: props.textColor,
'--text-color': props.textColor,
}
if (props.backgroundImage) {
styles.backgroundImage = `url(${props.backgroundImage})`
styles.backgroundSize = 'contain'
styles.backgroundPosition = 'center'
styles.backgroundRepeat = 'no-repeat'
}
return styles
})
const componentTag = computed((): string => { const componentTag = computed((): string => {
switch (props.type) { switch (props.type) {
case 'download': case 'download':
@@ -72,18 +51,39 @@ const componentProps = computed(() => {
return baseProps return baseProps
}) })
const buttonStyles = computed(() => {
const styles: Record<string, string> = {
backgroundColor: props.backgroundColor,
color: props.textColor,
}
if (props.backgroundImage) {
styles.backgroundImage = `url(${props.backgroundImage})`
styles.backgroundSize = 'contain'
styles.backgroundPosition = 'center'
styles.backgroundRepeat = 'no-repeat'
}
return styles
})
</script> </script>
<template> <template>
<component <component
:is="componentTag" :is="componentTag"
v-bind="componentProps" v-bind="{ ...componentProps, ...$attrs }"
:class="buttonClasses" :class="['btn-base', $attrs?.class]"
:style="buttonStyles" :style="buttonStyles"
> >
<span class="relative flex items-center gap-2 z-[1]"> <span class="btn-content">
<slot /> <slot />
<span v-if="props.icon" class="flex-shrink-0" v-html="props.icon" /> <AtomsIconsLongArrowRightLine v-if="props.type === 'internal'" />
<AtomsIconsWebLinkLine
v-if="props.type === 'external'"
size="24"
color="#ebebeb"
/>
<AtomsIconsDownloadLine v-if="props.type === 'download'" />
</span> </span>
</component> </component>
</template> </template>

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
interface Props {
size?: number | string
color?: string
className?: string
}
withDefaults(defineProps<Props>(), {
size: 24,
color: '#EBEBEB',
className: '',
})
</script>
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
:width="size"
:height="size"
viewBox="0 0 24 24"
fill="none"
:class="className"
>
<path
d="M10.75 3.25L10.75 12.2322L6.88391 8.36611C6.39576 7.87796 5.6043 7.87796 5.11615 8.36611C4.62799 8.85427 4.62799 9.64573 5.11615 10.1339L11.1161 16.1339C11.3506 16.3683 11.6685 16.5 12 16.5C12.3316 16.5 12.6495 16.3683 12.8839 16.1339L18.8839 10.1339C19.3721 9.64573 19.3721 8.85427 18.8839 8.36611C18.3958 7.87796 17.6043 7.87796 17.1161 8.36611L13.25 12.2322L13.25 3.25C13.25 2.55964 12.6904 2 12 2C11.3097 2 10.75 2.55964 10.75 3.25Z"
:fill="color"
/>
<path
d="M20 21C20.6904 21 21.25 20.4404 21.25 19.75L21.25 17.75C21.25 17.0596 20.6904 16.5 20 16.5C19.3097 16.5 18.75 17.0596 18.75 17.75L18.75 18.5L5.25003 18.5L5.25003 17.75C5.25003 17.0596 4.69039 16.5 4.00003 16.5C3.30967 16.5 2.75003 17.0596 2.75003 17.75L2.75003 19.75C2.75003 20.4404 3.30967 21 4.00003 21L20 21Z"
:fill="color"
/>
</svg>
</template>

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
interface Props {
size?: number | string
color?: string
className?: string
}
withDefaults(defineProps<Props>(), {
size: 24,
color: '#EBEBEB',
className: '',
})
</script>
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
:width="size"
:height="size"
viewBox="0 0 24 24"
fill="none"
:class="className"
>
<path
d="M11.7929 18.2929C11.4024 18.6834 11.4024 19.3166 11.7929 19.7071C12.1834 20.0976 12.8166 20.0976 13.2071 19.7071L20.2071 12.7071C20.5976 12.3166 20.5976 11.6834 20.2071 11.2929L13.2071 4.29289C12.8166 3.90237 12.1834 3.90237 11.7929 4.29289C11.4024 4.68342 11.4024 5.31658 11.7929 5.70711L17.0858 11L4.5 11C3.94771 11 3.5 11.4477 3.5 12C3.5 12.5523 3.94771 13 4.5 13L17.0858 13L11.7929 18.2929Z"
:fill="color"
/>
</svg>
</template>

View File

@@ -11,7 +11,6 @@ interface ButtonListProps {
const props = defineProps<ButtonListProps>() const props = defineProps<ButtonListProps>()
// 상수 정의
const BUTTON_TYPE_MAP = { const BUTTON_TYPE_MAP = {
URL: { URL: {
_self: 'internal' as const, _self: 'internal' as const,
@@ -35,23 +34,6 @@ const getButtonType = (btnInfo: PageDataResourceGroupBtnInfo): ButtonType => {
return DEFAULT_BUTTON_TYPE return DEFAULT_BUTTON_TYPE
} }
const getButtonProps = (button: PageDataResourceGroup) => ({
type: getButtonType(button.btn_info),
target: button.btn_info?.detail?.action?.link_target,
href: button.btn_info?.detail?.action?.url,
rel: button.btn_info?.detail?.action?.rel,
backgroundColor: getColorCode({
colorName: button.btn_info?.color_name_btn,
colorCode: button.btn_info?.color_code_btn,
}),
textColor: getColorCode({
colorName: button.btn_info?.color_name_txt,
colorCode: button.btn_info?.color_code_txt,
}),
disabled: button.btn_info?.disabled,
text: button.btn_info?.txt_btn_name,
})
</script> </script>
<template> <template>
@@ -62,7 +44,23 @@ const getButtonProps = (button: PageDataResourceGroup) => ({
<AtomsButton <AtomsButton
v-for="(button, index) in props.resourcesData" v-for="(button, index) in props.resourcesData"
:key="index" :key="index"
v-bind="getButtonProps(button)" :type="getButtonType(button.btn_info)"
:target="button.btn_info?.detail?.action?.link_target"
:href="button.btn_info?.detail?.action?.url"
:rel="button.btn_info?.detail?.action?.rel"
:background-color="
getColorCode({
colorName: button.btn_info?.color_name_btn,
colorCode: button.btn_info?.color_code_btn,
})
"
:text-color="
getColorCode({
colorName: button.btn_info?.color_name_txt,
colorCode: button.btn_info?.color_code_txt,
})
"
:disabled="button.btn_info?.disabled"
class="size-extra-small md:size-medium" class="size-extra-small md:size-medium"
> >
{{ button.btn_info?.txt_btn_name }} {{ button.btn_info?.txt_btn_name }}

View File

@@ -1,2 +1,3 @@
export type ButtonType = 'internal' | 'external' | 'download' | 'action' export type ButtonType = 'internal' | 'external' | 'download' | 'action'
export type ButtonSize = 'large' | 'medium' | 'small' | 'extra-small' export type ButtonSize = 'large' | 'medium' | 'small' | 'extra-small'
export type ButtonVariant = 'filled' | 'outlined'