-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement
WCard
and WInput
components
- Loading branch information
Showing
16 changed files
with
591 additions
and
8 deletions.
There are no files selected for viewing
4 changes: 1 addition & 3 deletions
4
src/components/icons/IconRightArrow.vue → src/assets/svg/icon-right-arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { describe, it, expect } from 'vitest' | ||
|
||
import { mount } from '@vue/test-utils' | ||
import WCard from './WCard.vue' | ||
import { CardType } from './WCard' | ||
import AnimatedArrow from '../AnimatedArrow.vue' | ||
|
||
describe('WCard', () => { | ||
it('base', () => { | ||
const wrapper = mount(WCard, { | ||
props: { | ||
type: CardType.base | ||
}, | ||
slots: { | ||
default: 'Button' | ||
} | ||
}) | ||
expect(wrapper.element).toMatchSnapshot() | ||
}) | ||
|
||
it('icon', () => { | ||
const wrapper = mount(WCard, { | ||
props: { | ||
type: CardType.icon, | ||
title: 'Custom title', | ||
description: 'Custom description', | ||
url: '#url', | ||
urlLabel: 'Link to' | ||
}, | ||
slots: { | ||
icon: 'WIcon' | ||
} | ||
}) | ||
|
||
expect(wrapper.element).toMatchSnapshot() | ||
}) | ||
|
||
it('link', () => { | ||
const wrapper = mount(WCard, { | ||
props: { | ||
type: CardType.link, | ||
title: 'Custom link title', | ||
}, | ||
slots: { | ||
description: '<p>Link description</p>' | ||
} | ||
}) | ||
|
||
const found = wrapper.findComponent(AnimatedArrow) | ||
expect(found.exists()).toBe(true) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import type { Meta, StoryObj } from '@storybook/vue3' | ||
import WCard from './WCard.vue' | ||
import { CardType } from './WCard' | ||
|
||
const meta: any = { | ||
title: 'Example/WCard', | ||
component: WCard, | ||
tags: ['autodocs'], | ||
argTypes: { | ||
type: { control: 'select', options: ['base', 'icon', 'link'] } | ||
}, | ||
args: { | ||
type: CardType.base | ||
} | ||
} satisfies Meta<typeof WCard> | ||
|
||
export default meta | ||
type Story = StoryObj<typeof meta> | ||
|
||
export const Base: Story = { | ||
render: (args: any) => ({ | ||
components: { WCard }, | ||
setup() { | ||
return { args } | ||
}, | ||
template: `<WCard v-bind="args"><template #content>Link description</template></WCard>` | ||
}), | ||
args: { | ||
type: 'base' | ||
} | ||
} | ||
|
||
export const Icon: Story = { | ||
parameters: { | ||
backgrounds: { default: 'grey' } | ||
}, | ||
render: (args: any) => ({ | ||
components: { WCard }, | ||
setup() { | ||
return { args } | ||
}, | ||
template: `<WCard v-bind="args" />` | ||
}), | ||
args: { | ||
type: 'icon', | ||
title: 'Custom title', | ||
description: 'Custom description', | ||
url: '#url', | ||
urlLabel: 'Link to' | ||
} | ||
} | ||
|
||
export const Link: Story = { | ||
render: (args: any) => ({ | ||
components: { WCard }, | ||
setup() { | ||
return { args } | ||
}, | ||
template: `<WCard v-bind="args"><template #description>Link description</template></WCard>` | ||
}), | ||
args: { | ||
type: 'link', | ||
title: 'Custom link title', | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export enum CardType { | ||
base = 'base', | ||
icon = 'icon', | ||
link = 'link', | ||
} | ||
|
||
export const cardTypes = Object.values(CardType) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
<template> | ||
<div v-if="isLinkCard"> | ||
<a | ||
:href="url" | ||
:aria-label="title" | ||
target="_blank" | ||
class="cursor-pointer" | ||
@mouseenter="toggleHover" | ||
@mouseleave="toggleHover" | ||
> | ||
<div | ||
class="card border rounded-lg px-xl py-xl mr-sm mb-sm max-w-md h-full" | ||
> | ||
<div class="flex justify-between items-center"> | ||
<h3 class="text-xl text-black-950 font-semibold leading-4"> | ||
{{ title }} | ||
</h3> | ||
<AnimatedArrow :hover="hover" /> | ||
</div> | ||
<hr class="hr my-md" /> | ||
<slot name="description" class="text-sm text-black-950"></slot> | ||
</div> | ||
</a> | ||
</div> | ||
<div | ||
v-else class="h-full w-auto out-of-boundaries card border-2 border-black-950 bg-white-50 rounded-lg px-xl py-xl max-w-sm" | ||
> | ||
<div v-if="isBaseCard"> | ||
<slot name="content"></slot> | ||
</div> | ||
<div v-if="isIconCard"> | ||
<RoundedIcon class="rounded-icon" icon-size="60px"> | ||
<slot name="icon">Icon</slot> | ||
</RoundedIcon> | ||
<div class="ml-xl px-sm"> | ||
<h3 class="text-2xl text-black-950 font-semibold leading-4 pl-14"> | ||
{{ title }} | ||
</h3> | ||
<hr class="hr my-md ml-14" /> | ||
</div> | ||
<p class="text text-black-950 mb-lg"> | ||
{{ description }} | ||
</p> | ||
|
||
<SlashesIcon class="slashes w-[68px] sm:hidden"></SlashesIcon> | ||
<a :href="url" :aria-label="urlLabel" target="_blank"> | ||
<WButton class="action" type="arrow">{{ urlLabel }}</WButton> | ||
</a> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { cardTypes, CardType } from './WCard.ts' | ||
import { PropType, computed, ref } from 'vue' | ||
import AnimatedArrow from '../AnimatedArrow.vue' | ||
import SlashesIcon from '@/assets/svg/slashes.svg?component' | ||
import WButton from '../Button/WButton.vue' | ||
import RoundedIcon from '../RoundedIcon.vue' | ||
const hover = ref(false) | ||
const props = defineProps({ | ||
type: { | ||
type: String as PropType<CardType>, | ||
default: CardType.base, | ||
validator(value: CardType) { | ||
return cardTypes.includes(value) | ||
} | ||
}, | ||
title: { | ||
type: String, | ||
default: 'Title', | ||
}, | ||
description: { | ||
type: String, | ||
default: 'Description', | ||
}, | ||
urlLabel: { | ||
type: String, | ||
required: false, | ||
}, | ||
url: { | ||
type: String, | ||
required: false, | ||
}, | ||
}) | ||
const isIconCard = computed(() => props.type === CardType.icon) | ||
const isLinkCard = computed(() => props.type === CardType.link) | ||
const isBaseCard = computed(() => props.type === CardType.base) | ||
function toggleHover() { | ||
hover.value = !hover.value | ||
} | ||
</script> | ||
|
||
<style scoped lang="scss"> | ||
:slotted(svg) { | ||
width: 60px; | ||
height: 60px; | ||
} | ||
.out-of-boundaries { | ||
// add margin equal to out of boundaries | ||
margin: 15px 30px 25px 15px; | ||
} | ||
.rounded-icon { | ||
position: absolute; | ||
top: -15px; | ||
left: -15px; | ||
} | ||
.action { | ||
position: absolute; | ||
right: -30px; | ||
bottom: 16px; | ||
} | ||
.slashes { | ||
position: absolute; | ||
bottom: 32px; | ||
} | ||
.card { | ||
box-shadow: 7px 10px 0px rgb(0, 0, 0); | ||
position: relative; | ||
} | ||
.title-h2 { | ||
font-weight: bold; | ||
} | ||
.hr { | ||
height: 3px; /* Modern Browsers */ | ||
@apply bg-black-950; | ||
} | ||
.circle { | ||
line-height: 1; | ||
font-size: 24px; | ||
height: 48px; | ||
min-width: 48px; | ||
align-content: center; | ||
text-align: center; | ||
@apply bg-wit-blue-500; | ||
} | ||
</style> | ||
|
Oops, something went wrong.