Skip to content

Commit

Permalink
feat(banner): add banner component
Browse files Browse the repository at this point in the history
  • Loading branch information
adenvt committed Mar 31, 2022
1 parent 1601d4a commit 360f0e8
Show file tree
Hide file tree
Showing 19 changed files with 901 additions and 50 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"css.customData": [".vscode/tailwind.json"]
}
45 changes: 45 additions & 0 deletions .vscode/tailwind.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"version": 1.1,
"atDirectives": [
{
"name": "@tailwind",
"description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
}
]
},
{
"name": "@responsive",
"description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
}
]
},
{
"name": "@screen",
"description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#screen"
}
]
},
{
"name": "@variants",
"description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#variants"
}
]
}
]
}
22 changes: 21 additions & 1 deletion components/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
import { defineConfig } from 'vitepress'
import fonts from 'vite-plugin-fonts'

export default defineConfig({
title : 'Design Sistem',
themeConfig: {
sidebar: [
{
text : 'Guide',
collapsable: true,
children : [
{
text: 'Banner',
link: '/banner/guide'
}
]
},
{
text : 'Components',
collapsable: true,
children : [
{
text: 'Banner',
link: '/banner/playground'
},
{
text: 'Button',
link: '/button/index'
link: '/button/playground'
}
]
},
]
},
vite: {
plugins: [
fonts({ google: { families: ['DM Sans'] } }),
]
}
})
5 changes: 5 additions & 0 deletions components/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:root {
--font-family-base: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
}
6 changes: 6 additions & 0 deletions components/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import './tailwind.css'
import DefaultTheme from 'vitepress/theme'
import 'virtual:fonts.css'
import './custom.css'

export default DefaultTheme
3 changes: 3 additions & 0 deletions components/.vitepress/theme/tailwind.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
88 changes: 88 additions & 0 deletions components/banner/Banner.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import '@testing-library/jest-dom'
import { vi } from 'vitest'
import { fireEvent, render } from "@testing-library/vue"
import Banner from './Banner.vue'


it('should rendered properly without any props', () => {
const screen = render({
components: { Banner },
template : `
<Banner>
Hello
</Banner>
`,
})

const banner = screen.queryByTestId('banner')
const text = screen.queryByText('Hello')

expect(banner).toBeInTheDocument()
expect(banner).toHaveClass('banner', 'banner--info')
expect(text).toBeInTheDocument()
})

it('should dismissed when close button clicked', async () => {
const screen = render({
components: { Banner },
template : `
<Banner>
Hello
</Banner>
`,
})

const banner = screen.queryByTestId('banner')
const text = screen.queryByText('Hello')
const close = screen.queryByTestId('banner-close')

expect(banner).toBeInTheDocument()
expect(text).toBeInTheDocument()

await fireEvent.click(close)

expect(banner).not.toBeInTheDocument()
expect(text).not.toBeInTheDocument()
})

it('should emit event "dismissed" if close button clicked', async () => {
const spy = vi.fn()
const screen = render({
components: { Banner },
template : `
<Banner @dismissed="onDismissed">
Hello
</Banner>
`,
methods: {
onDismissed: spy
}
})

const banner = screen.queryByTestId('banner')
const text = screen.queryByText('Hello')
const close = screen.queryByTestId('banner-close')

expect(banner).toBeInTheDocument()
expect(text).toBeInTheDocument()

await fireEvent.click(close)

expect(spy).toBeCalled()
})


it('should have no close button if props "dismissable" set to false', () => {
const screen = render({
components: { Banner },
template : `
<Banner :dismissable="false">
Hello
</Banner>
`,
})

const close = screen.queryByTestId('banner-close')

expect(close).not.toBeInTheDocument()
})
82 changes: 82 additions & 0 deletions components/banner/Banner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<div
v-if="show"
data-testid="banner"
:class="classNames">
<div class="banner__icon">
I
</div>
<div class="banner__body">
<slot />
</div>
<div
v-if="dismissable"
data-testid="banner-close"
class="banner__close" @click="dismiss()">
&times;
</div>
</div>
</template>

<script lang="ts">
import { defineComponent, PropType, ref, computed } from "vue-demi"
export default defineComponent({
props: {
variant: {
type : String as PropType<'info' | 'danger'>,
default: 'info',
},
dismissable: {
type : Boolean,
default: true,
},
},
setup (props, { emit }) {
const show = ref(true)
const classNames = computed(() => {
const result: string[] = ['banner']
if (props.variant)
result.push(`banner--${props.variant}`)
return result
})
function dismiss (): void {
show.value = false
emit('dismissed')
}
return {
classNames,
show,
dismiss,
}
}
})
</script>

<style lang="postcss">
.banner {
@apply p-3 flex gap-2;
}
.banner--info {
@apply bg-background-100;
}
.banner--danger {
@apply bg-danger-25;
}
.banner__icon,
.banner__close {
@apply flex-shrink-0 gap-2;
}
.banner__body {
@apply flex-grow;
}
</style>
13 changes: 13 additions & 0 deletions components/banner/guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup>
import Banner from './Banner.vue'
</script>

# Alert

## Usage

Banner Alert is use to convey information or actions, can be put in a card or in modal. For example, you might show a banner that inform user there is input need to filled but not required to be specific

<Banner>This form will be privately saved and not be shared to any third parties, please filled in with correct information</Banner>

Default banners contain lower priority information and should always be dismissible, this also use to update users about a change or give them advice. Title banner is optional
71 changes: 71 additions & 0 deletions components/banner/playground.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script setup>
import Banner from './Banner.vue'
</script>

# Alert

## Usage

### Simple Banner

<Banner>Your enterprise Privy Balance is running out. Please topup now.</Banner>

```vue
<template>
<Banner>Your enterprise Privy Balance is running out. Please topup now.</Banner>
</template>
```

### Banner with Title

<Banner>Your enterprise Privy Balance is running out. Please topup now.</Banner>

```vue
<template>
<Banner>Your enterprise Privy Balance is running out. Please topup now.</Banner>
</template>
```

## Banner Variants

Banner have 2 variants: `info` and `danger`, default is `info`

<Banner variant="info">Your enterprise Privy Balance is running out. Please topup now.</Banner>
<Banner variant="danger">Your enterprise Privy Balance is running out. Please topup now.</Banner>

```vue
<template>
<Banner variant="info">Your enterprise Privy Balance is running out. Please topup now.</Banner>
<Banner variant="danger">Your enterprise Privy Balance is running out. Please topup now.</Banner>
</template>
```

## Hide close button

You can hide close button with `dismissable` set to `false`

<Banner :dismissable="false">Your enterprise Privy Balance is running out. Please topup now.</Banner>

```vue
<Banner :dismissable="false">Your enterprise Privy Balance is running out. Please topup now.</Banner>
```

## API

### Props

| Props | Type | Default | Description |
|---------------|-----------|----------|-------------------------------------------------|
| `variant` | `String` | `'info'` | Banner variant, valid value is `info`, `danger` |
| `dismissable` | `Boolean` | `true` | Show / Hide dismiss button |

### Slots
| Name | Description |
|-----------|----------------------------|
| `default` | Content to place in banner |

### Events

| Name | Argunments | Description |
|-------------|------------|---------------------------------|
| `dismissed` | | Event when close button clicked |
11 changes: 0 additions & 11 deletions components/button/Button.spec.js

This file was deleted.

Loading

0 comments on commit 360f0e8

Please sign in to comment.