initial
This commit is contained in:
73
layers/ui/components/alert/index.vue
Normal file
73
layers/ui/components/alert/index.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
cn.b(),
|
||||
cn.m(type),
|
||||
cn.m(size),
|
||||
cn.has('title', hasTitle),
|
||||
cn.has('action', hasAction),
|
||||
]"
|
||||
>
|
||||
<div :class="[cn.e('content')]">
|
||||
<div
|
||||
v-if="$slots.title || title"
|
||||
:class="[cn.e('title')]"
|
||||
>
|
||||
<slot name="title">
|
||||
{{ title }}
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div :class="[cn.e('text')]">
|
||||
<slot>{{ text }}</slot>
|
||||
</div>
|
||||
|
||||
<slot name="action" />
|
||||
</div>
|
||||
|
||||
<div :class="cn.e('icon')">
|
||||
<slot name="icon">
|
||||
<Component :is="resolveComponent(`ui-icon-${TYPE_ICON_MAPPING[type]}`)" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import useClassname from '../../composables/use-classname'
|
||||
import type { AlertProps, AlertType } from './types'
|
||||
import type { UiIcon } from '#build/types/ui/icons'
|
||||
|
||||
defineOptions({
|
||||
name: 'UiAlert',
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<AlertProps>(), {
|
||||
type: 'neutral',
|
||||
size: 'normal',
|
||||
})
|
||||
|
||||
const slots = defineSlots<{
|
||||
default(props: NonNullable<unknown>): never
|
||||
title(props: NonNullable<unknown>): never
|
||||
action(props: NonNullable<unknown>): never
|
||||
}>()
|
||||
|
||||
const TYPE_ICON_MAPPING: Record<AlertType, UiIcon> = {
|
||||
neutral: 'exclamation-filled',
|
||||
positive: 'confirmed-filled',
|
||||
warning: 'danger-filled',
|
||||
negative: 'cancel-filled',
|
||||
marketing: 'ask-for-discount-filled',
|
||||
}
|
||||
|
||||
const cn = useClassname('ui-alert')
|
||||
|
||||
const hasTitle = computed(() => !!props.title || slots.title)
|
||||
const hasAction = computed(() => slots.action)
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use 'styles';
|
||||
</style>
|
||||
83
layers/ui/components/alert/styles.scss
Normal file
83
layers/ui/components/alert/styles.scss
Normal file
@@ -0,0 +1,83 @@
|
||||
@use '../../styles/mixins' as *;
|
||||
@use '../../styles/variables' as *;
|
||||
|
||||
.ui-alert {
|
||||
$self: &;
|
||||
|
||||
--icon-color: var(--alert-icon-color);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
border-radius: 12px;
|
||||
background-color: var(--alert-background);
|
||||
text-align: left;
|
||||
|
||||
&__title {
|
||||
@include txt-i-b('alert-title');
|
||||
|
||||
grid-area: title;
|
||||
margin-bottom: var(--alert-title-margin, 4px);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
&__text {
|
||||
@include txt-i-m('alert-text');
|
||||
|
||||
grid-area: text;
|
||||
color: $clr-black;
|
||||
|
||||
#{$self}.has-title & {
|
||||
color: var(--alert-text-color, $clr-grey-500);
|
||||
}
|
||||
|
||||
#{$self}.has-action & {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
grid-area: icon;
|
||||
align-self: center;
|
||||
color: var(--icon-color);
|
||||
padding: 8px;
|
||||
|
||||
#{$self}.has-title &,
|
||||
#{$self}.has-action & {
|
||||
align-self: flex-start
|
||||
}
|
||||
}
|
||||
|
||||
&__content{
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@include element-variant('alert', 'large', (
|
||||
'padding': 16px,
|
||||
));
|
||||
|
||||
@include element-variant('alert', 'neutral', (
|
||||
'icon-color': $clr-grey-500,
|
||||
'background': $clr-grey-200,
|
||||
));
|
||||
|
||||
@include element-variant('alert', 'positive', (
|
||||
'icon-color': $clr-green-500,
|
||||
'background': $clr-green-100,
|
||||
));
|
||||
|
||||
@include element-variant('alert', 'warning', (
|
||||
'icon-color': $clr-warn-500,
|
||||
'background': $clr-warn-100,
|
||||
));
|
||||
|
||||
@include element-variant('alert', 'negative', (
|
||||
'icon-color': $clr-red-500,
|
||||
'background': $clr-red-100,
|
||||
));
|
||||
|
||||
@include element-variant('alert', 'marketing', (
|
||||
'icon-color': $clr-market-500,
|
||||
'background': $clr-market-100,
|
||||
));
|
||||
}
|
||||
16
layers/ui/components/alert/types.ts
Normal file
16
layers/ui/components/alert/types.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export const ALERT_TYPES = [
|
||||
'neutral',
|
||||
'positive',
|
||||
'warning',
|
||||
'negative',
|
||||
'marketing',
|
||||
] as const
|
||||
|
||||
export type AlertType = (typeof ALERT_TYPES)[number]
|
||||
|
||||
export interface AlertProps {
|
||||
type?: AlertType
|
||||
title?: string
|
||||
text?: string
|
||||
size?: string
|
||||
}
|
||||
Reference in New Issue
Block a user