Skip to content

Commit

Permalink
feat(VsNotice): add vs-notice component
Browse files Browse the repository at this point in the history
  • Loading branch information
seaneez committed Dec 26, 2023
1 parent 216cae6 commit 06d5299
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 9 deletions.
7 changes: 7 additions & 0 deletions packages/vlossom/.storybook/examples/style-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
VsSectionStyleSet,
VsPageStyleSet,
VsValueTagStyleSet,
VsNoticeStyleSet,
} from '@/components/types';

const vsButton: VsButtonStyleSet = {
Expand All @@ -24,6 +25,11 @@ const vsInput: VsInputStyleSet = {
fontColor: '#1e88e5',
};

const vsNotice: VsNoticeStyleSet = {
backgroundColor: '#1e88e5',
color: 'white',
};

const vsSection: VsSectionStyleSet = {
backgroundColor: '#90caf9',
fontColor: 'white',
Expand All @@ -46,6 +52,7 @@ export const styleSet: StyleSet = {
VsButton: { myStyleSet: vsButton },
VsDivider: { myStyleSet: vsDivider },
VsInput: { myStyleSet: vsInput },
VsNotice: { myStyleSet: vsNotice },
VsSection: { myStyleSet: vsSection },
VsPage: { myStyleSet: vsPage },
VsValueTag: { myStyleSet: vsValueTag },
Expand Down
6 changes: 6 additions & 0 deletions packages/vlossom/src/assets/icons/close.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
template: `
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
<path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
</svg>`,
};
1 change: 1 addition & 0 deletions packages/vlossom/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type * from './vs-input';
export type * from './vs-input-wrapper';
export type * from './vs-message';
export type * from './vs-page';
export type * from './vs-notice';
export type * from './vs-section';
export type * from './vs-value-tag';
export type * from './vs-wrapper';
7 changes: 1 addition & 6 deletions packages/vlossom/src/components/vs-button/VsButton.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
<template>
<button
type="button"
:class="['vs-button', `vs-${computedColorScheme}`, { ...classObj }]"
:style="customProperties"
:disabled="disabled"
>
<button type="button" :class="['vs-button', `vs-${computedColorScheme}`, { ...classObj }]" :style="customProperties" :disabled="disabled">
<span v-if="!loading" class="content">
<slot />
</span>
Expand Down
52 changes: 52 additions & 0 deletions packages/vlossom/src/components/vs-notice/VsNotice.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.vs-notice {
display: flex;
align-items: center;
position: relative;
min-height: 3rem;
padding: 0.8rem 4rem 0.8rem 2.4rem;
overflow: hidden;
background-color: var(--vs-notice-backgroundColor, var(--vs-comp-backgroundColor));
color: var(--vs-notice-color, var(--vs-comp-color));

.sub-title {
display: flex;
justify-content: center;
align-items: center;
margin: 0 2rem 0 0;
font-size: 1.2rem;
font-weight: 600;

&:after {
content: '';
width: 1px;
height: 1rem;
opacity: 0.6;
margin-left: 2rem;
background-color: black;
}
}

.vs-notice-close {
background: none;
border: none;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0.8rem;
right: 0.8rem;
font-weight: 500;
cursor: pointer;

.close-icon {
width: 1rem;
height: 1.5rem;
}
}

// primary
&.primary {
background-color: var(--vs-notice-backgroundColor, var(--vs-comp-backgroundColor-primary));
color: var(--vs-notice-color, var(--vs-comp-color-primary));
}
}
76 changes: 76 additions & 0 deletions packages/vlossom/src/components/vs-notice/VsNotice.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<div v-if="isVisible" :class="['vs-notice', `vs-${computedColorScheme}`, { ...classObj }]" :style="customProperties">
<strong class="sub-title">Notice</strong>
<p>
<slot />
</p>
<button type="button" class="vs-notice-close" @click.stop="closeNotice()">
<close aria-label="close" class="close-icon" />
</button>
</div>
</template>

<script lang="ts">
import { PropType, defineComponent, ref, toRefs, watch, computed } from 'vue';
import { useColorScheme, useCustomStyle } from '@/composables';
import { ColorScheme, VsComponent } from '@/declaration/types';
import Close from '@/assets/icons/close';
interface NoticeStyleSet {
backgroundColor: string;
color: string;
fontSize: string;
fontWeight: string;
}
export type VsNoticeStyleSet = Partial<NoticeStyleSet>;
const name = VsComponent.VsNotice;
export default defineComponent({
name,
components: { Close },
props: {
colorScheme: { type: String as PropType<ColorScheme> },
styleSet: { type: [String, Object] as PropType<string | VsNoticeStyleSet>, default: '' },
primary: { type: Boolean, default: false },
// v-model
modelValue: { type: Boolean, default: true },
},
emits: ['update:modelValue'],
setup(props, { emit }) {
const { colorScheme, styleSet, modelValue, primary } = toRefs(props);
const { computedColorScheme } = useColorScheme(name, colorScheme);
const { customProperties } = useCustomStyle<VsNoticeStyleSet>(name, styleSet);
const isVisible = ref(true);
watch(
modelValue,
(visibie: boolean) => {
isVisible.value = visibie;
},
{ immediate: true },
);
const closeNotice = () => {
isVisible.value = false;
emit('update:modelValue', false);
};
const classObj = computed(() => ({
primary: primary.value,
}));
return {
computedColorScheme,
customProperties,
isVisible,
closeNotice,
classObj,
};
},
});
</script>

<style lang="scss" scoped src="./VsNotice.scss" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { beforeEach, afterEach, describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import VsNotice from '../VsNotice.vue';

function mountComponent() {
return mount(VsNotice);
}

describe('vs-notice', () => {
describe('visibility', () => {
let wrapper: ReturnType<typeof mountComponent>;

beforeEach(() => {
wrapper = mount(VsNotice, {
props: {
modelValue: true,
'onUpdate:modelValue': (v: boolean) => wrapper.setProps({ modelValue: v }),
},
});
});

afterEach(() => {
wrapper.unmount();
});

it('modelValue의 초깃값이 true이면 Notice가 나타난다', () => {
// then
expect(wrapper.props('modelValue')).toBe(true);
expect(wrapper.find('.vs-notice').exists()).toBe(true);
});

it('modelValue가 false로 업데이트되면 Notice가 사라진다', async () => {
//when
await wrapper.setProps({ modelValue: false });

// then
expect(wrapper.props('modelValue')).toBe(false);
expect(wrapper.find('.vs-notice').exists()).toBe(false);
});
});
});
12 changes: 12 additions & 0 deletions packages/vlossom/src/components/vs-notice/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { VsComponent } from '@/declaration/types';
import VsNotice from './VsNotice.vue';
import type { VsNoticeStyleSet } from './VsNotice.vue';

type VsNoticeInstance = InstanceType<typeof VsNotice>;

export type { VsNoticeInstance, VsNoticeStyleSet };

export default {
name: VsComponent.VsNotice,
component: VsNotice,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { Meta, StoryObj } from '@storybook/vue3';
import { colorScheme } from '@/storybook/args';
import VsNotice from '../VsNotice.vue';

const meta: Meta<typeof VsNotice> = {
title: 'Components/Base Components/VsNotice',
component: VsNotice,
render: (args: any) => ({
components: { VsNotice },
setup() {
return { args };
},
template: '<vs-notice v-bind="args">Hello! This is Notice</vs-notice>',
}),
tags: ['autodocs'],
argTypes: {
colorScheme,
},
};

export default meta;
type Story = StoryObj<typeof VsNotice>;

export const Default: Story = {};

export const ColorScheme: Story = {
render: (args: any) => ({
components: { VsNotice },
setup() {
return { args };
},
template: `
<div>
<vs-notice color-scheme="red">Hello! This is red notice</vs-notice>
<vs-notice color-scheme="amber">Hello! This is amber notice</vs-notice>
<vs-notice color-scheme="green">Hello! This is green notice</vs-notice>
<vs-notice color-scheme="teal">Hello! This is teal notice</vs-notice>
<vs-notice color-scheme="blue">Hello! This is blue notice</vs-notice>
<vs-notice color-scheme="indigo">Hello! This is indigo notice</vs-notice>
<vs-notice color-scheme="purple">Hello! This is purple notice</vs-notice>
<vs-notice color-scheme="pink">Hello! This is pink notice</vs-notice>
</div>
`,
}),
};

export const Primary: Story = {
render: (args: any) => ({
components: { VsNotice },
setup() {
return { args };
},
template: `
<div>
<vs-notice color-scheme="red" primary>Hello! This is red notice</vs-notice>
<vs-notice color-scheme="amber" primary>Hello! This is amber notice</vs-notice>
<vs-notice color-scheme="green" primary>Hello! This is green notice</vs-notice>
<vs-notice color-scheme="teal" primary>Hello! This is teal notice</vs-notice>
<vs-notice color-scheme="blue" primary>Hello! This is blue notice</vs-notice>
<vs-notice color-scheme="indigo" primary>Hello! This is indigo notice</vs-notice>
<vs-notice color-scheme="purple" primary>Hello! This is purple notice</vs-notice>
<vs-notice color-scheme="pink" primary>Hello! This is pink notice</vs-notice>
</div>
`,
}),
};

export const StyleSet: Story = {
args: {
styleSet: { backgroundColor: '#a5d6ad', fontSize: '2rem' },
},
};

export const PreDefinedStyleSet: Story = {
args: {
styleSet: 'myStyleSet',
},
};
7 changes: 4 additions & 3 deletions packages/vlossom/src/declaration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
VsInputStyleSet,
VsPageStyleSet,
VsSectionStyleSet,
VsValueTagStyleSet,
VsNoticeStyleSet,
} from '@/components/types';
import type { Ref } from 'vue';

Expand All @@ -16,6 +16,7 @@ export enum VsComponent {
VsInput = 'VsInput',
VsInputWrapper = 'VsInputWrapper',
VsMessage = 'VsMessage',
VsNotice = 'VsNotice',
VsPage = 'VsPage',
VsSection = 'VsSection',
VsValueTag = 'VsValueTag',
Expand All @@ -30,9 +31,9 @@ export interface StyleSet {
VsButton?: { [key: string]: VsButtonStyleSet };
VsDivider?: { [key: string]: VsDividerStyleSet };
VsInput?: { [key: string]: VsInputStyleSet };
VsSection?: { [key: string]: VsSectionStyleSet };
VsNotice?: { [key: string]: VsNoticeStyleSet };
VsPage?: { [key: string]: VsPageStyleSet };
VsValueTag?: { [key: string]: VsValueTagStyleSet };
VsSection?: { [key: string]: VsSectionStyleSet };
}

export interface VlossomStore {
Expand Down

0 comments on commit 06d5299

Please sign in to comment.