Skip to content

Commit 3c60a38

Browse files
Samuell1marcosmoura
authored andcommitted
comp(MdBadge): new md-badge component (#1465)
* comp(MdBadge): add md-badge * docs(MdBadge): add missing props, description * feat(MdBadge): add z-index * docs(MdBadge): add more examples * feat(MdBadge): separate badge component * feat(MdBadge): add dense prop * docs(MdBadge): dense example, docs
1 parent a30d84c commit 3c60a38

File tree

14 files changed

+359
-0
lines changed

14 files changed

+359
-0
lines changed

docs/app/i18n/en-US/pages.js

+4
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ export default {
134134
title: 'Avatar',
135135
description: 'Avatars can be used to represent people. When used with a specific logo, avatars can also be used to represent a brand.'
136136
},
137+
badge: {
138+
title: 'Badge',
139+
description: 'Small status descriptors for UI elements.'
140+
},
137141
bottomBar: {
138142
title: 'Bottom Bar',
139143
description: 'Bottom navigation bars make it easy to explore and switch between top-level views in a single tap.'
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<example src="./examples/Buttons.vue" />
2+
<example src="./examples/Lists.vue" />
3+
<example src="./examples/Dense.vue" />
4+
5+
<template>
6+
<page-container centered :title="$t('pages.badge.title')">
7+
<div class="page-container-section">
8+
<p>Small status descriptors for UI elements.</p>
9+
</div>
10+
11+
<div class="page-container-section">
12+
13+
<p>Some components like <b>button, avatar</b> needs to be wrapped with <code>md-badge</code> component.</p>
14+
<code-example title="Example with buttons" :component="examples['buttons']" />
15+
16+
<code-example title="Example with lists" :component="examples['lists']" />
17+
18+
<code-example title="Dense" :component="examples['dense']" />
19+
20+
<api-item title="API - md-badge">
21+
<p>The following option can be applied to any badge:</p>
22+
23+
<api-table :headings="props.headings" :props="props.props" slot="props" />
24+
<api-table :headings="classes.headings" :props="classes.props" slot="classes" />
25+
</api-item>
26+
</div>
27+
</page-container>
28+
</template>
29+
30+
<script>
31+
import examples from 'docs-mixins/docsExample'
32+
33+
export default {
34+
name: 'DocBadge',
35+
mixins: [examples],
36+
data: () => ({
37+
classes: {
38+
headings: ['Name', 'Description'],
39+
props: [
40+
{
41+
name: 'md-square',
42+
description: 'Created square type badge.'
43+
}
44+
]
45+
},
46+
props: {
47+
headings: ['Name', 'Description', 'Default'],
48+
props: [
49+
{
50+
name: 'md-content',
51+
type: 'String, Number',
52+
description: 'A content for badge'
53+
},
54+
{
55+
name: 'md-position',
56+
type: 'String',
57+
description: 'Position of badge <code>top</code> or <code>bottom</code>',
58+
defaults: 'top'
59+
},
60+
{
61+
name: 'md-dense',
62+
type: 'Boolean',
63+
description: 'Enables the dense layout',
64+
defaults: 'false'
65+
},
66+
]
67+
}
68+
})
69+
}
70+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<template>
2+
<div class="demo-badge">
3+
<div>
4+
<md-badge md-content="1">
5+
<md-button class="md-icon-button">
6+
<md-icon>notifications</md-icon>
7+
</md-button>
8+
</md-badge>
9+
10+
<md-badge class="md-primary" md-content="1">
11+
<md-button class="md-icon-button">
12+
<md-icon>home</md-icon>
13+
</md-button>
14+
</md-badge>
15+
16+
<md-badge md-position="bottom" md-content="2">
17+
<md-button class="md-icon-button">
18+
<md-icon>home</md-icon>
19+
</md-button>
20+
</md-badge>
21+
</div>
22+
23+
<div>
24+
<md-badge class="md-primary" md-content="12">
25+
<md-avatar>
26+
<img src="/assets/examples/avatar.png" alt="Avatar">
27+
</md-avatar>
28+
</md-badge>
29+
</div>
30+
31+
<div>
32+
<md-badge class="md-primary md-square" md-position="bottom" md-content="12">
33+
<md-button>
34+
Button with
35+
</md-button>
36+
</md-badge>
37+
</div>
38+
</div>
39+
</template>
40+
41+
<script>
42+
export default {
43+
name: 'Buttons'
44+
}
45+
</script>
46+
47+
<style lang="scss" scoped>
48+
.demo-badge {
49+
> div {
50+
margin-bottom: 16px;
51+
}
52+
}
53+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<template>
2+
<div class="demo-badge">
3+
<div>
4+
<md-badge md-content="1" md-dense>
5+
<md-button class="md-icon-button">
6+
<md-icon>notifications</md-icon>
7+
</md-button>
8+
</md-badge>
9+
10+
<md-badge class="md-primary" md-content="12" md-dense>
11+
<md-button class="md-icon-button">
12+
<md-icon>home</md-icon>
13+
</md-button>
14+
</md-badge>
15+
</div>
16+
</div>
17+
</template>
18+
19+
<script>
20+
export default {
21+
name: 'Dense'
22+
}
23+
</script>
24+
25+
<style lang="scss" scoped>
26+
.demo-badge {
27+
> div {
28+
margin-bottom: 16px;
29+
}
30+
}
31+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<template>
2+
<div>
3+
<md-list>
4+
<md-list-item>
5+
<md-icon>move_to_inbox</md-icon>
6+
<span class="md-list-item-text">Inbox</span>
7+
<md-badge class="md-primary md-square" md-content="6" />
8+
</md-list-item>
9+
10+
<md-list-item>
11+
<md-icon>send</md-icon>
12+
<span class="md-list-item-text">Sent Mail</span>
13+
</md-list-item>
14+
15+
<md-list-item>
16+
<md-icon>delete</md-icon>
17+
<span class="md-list-item-text">Trash</span>
18+
<md-badge class="md-primary" md-content="6" />
19+
</md-list-item>
20+
21+
<md-list-item>
22+
<md-icon>error</md-icon>
23+
<span class="md-list-item-text">Spam</span>
24+
<md-badge class="md-square" md-content="New" />
25+
</md-list-item>
26+
</md-list>
27+
</div>
28+
</template>
29+
30+
<script>
31+
export default {
32+
name: 'Lists'
33+
}
34+
</script>
35+
36+
<style lang="scss" scoped>
37+
.md-list {
38+
width: 320px;
39+
max-width: 100%;
40+
display: inline-block;
41+
vertical-align: top;
42+
border: 1px solid rgba(#000, .12);
43+
}
44+
</style>

docs/app/routes.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
export const routes = [
2+
{
3+
path: '/components/badge',
4+
name: 'components/badge',
5+
page: 'Components/Badge/Badge.vue'
6+
},
27
{
38
path: '/components/autocomplete',
49
name: 'components/autocomplete',

docs/app/template/MainNavContent.vue

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<div class="main-nav-level">
2525
<router-link to="/components/app">{{ $t('pages.app.title') }}</router-link>
2626
<router-link to="/components/avatar">{{ $t('pages.avatar.title') }}</router-link>
27+
<router-link to="/components/badge">{{ $t('pages.badge.title') }}</router-link>
2728
<router-link to="/components/bottom-bar">{{ $t('pages.bottomBar.title') }}</router-link>
2829
<router-link to="/components/button">{{ $t('pages.button.title') }}</router-link>
2930
<router-link to="/components/card">{{ $t('pages.card.title') }}</router-link>
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import mountTemplate from 'test/utils/mountTemplate'
2+
import MdBadge from './MdBadge.vue'
3+
4+
test('should render the badge', async () => {
5+
const template = '<md-badge>Lorem ipsum</md-badge>'
6+
const wrapper = await mountTemplate(MdBadge, template)
7+
8+
expect(wrapper.hasClass('md-badge')).toBe(true)
9+
expect(wrapper.text()).toBe('Lorem ipsum')
10+
})
11+
12+
test('should render the theme class', async () => {
13+
const template = '<md-badge md-theme="alt">Lorem ipsum</md-badge>'
14+
const wrapper = await mountTemplate(MdBadge, template)
15+
16+
expect(wrapper.hasClass('md-theme-alt')).toBe(true)
17+
})

src/components/MdBadge/MdBadge.vue

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<template>
2+
<div class="md-badge-content" v-if="hasDefaultSlot">
3+
<slot />
4+
<md-badge-standalone :class="badgeClasses">
5+
<div>
6+
{{ mdContent }}
7+
</div>
8+
</md-badge-standalone>
9+
</div>
10+
<md-badge-standalone :class="badgeClasses" v-else>
11+
{{ mdContent }}
12+
</md-badge-standalone>
13+
</template>
14+
15+
<script>
16+
import MdComponent from 'core/MdComponent'
17+
18+
import MdBadgeStandalone from './MdBadgeStandalone'
19+
20+
export default new MdComponent({
21+
name: 'MdBadge',
22+
components: {
23+
MdBadgeStandalone
24+
},
25+
props: {
26+
mdContent: [String, Number],
27+
mdPosition: {
28+
type: String,
29+
default: 'top'
30+
},
31+
mdDense: Boolean
32+
},
33+
computed: {
34+
hasDefaultSlot () {
35+
return !!this.$slots.default
36+
},
37+
badgeClasses () {
38+
return {
39+
['md-position-' + this.mdPosition]: true,
40+
'md-dense': this.mdDense
41+
}
42+
}
43+
}
44+
})
45+
</script>
46+
47+
<style lang="scss">
48+
@import "~components/MdAnimation/variables";
49+
50+
.md-badge-content {
51+
position: relative;
52+
display: inline-block;
53+
.md-position {
54+
&-top {
55+
top: -4px;
56+
}
57+
&-bottom {
58+
bottom: -4px;
59+
}
60+
}
61+
}
62+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<template>
2+
<div class="md-badge" :class="[$mdActiveTheme]">
3+
<slot />
4+
</div>
5+
</template>
6+
7+
<script>
8+
import MdComponent from 'core/MdComponent'
9+
10+
export default new MdComponent({
11+
name: 'MdBadgeStandalone'
12+
})
13+
</script>
14+
15+
<style lang="scss">
16+
@import "~components/MdAnimation/variables";
17+
18+
.md-badge {
19+
position: absolute;
20+
transition: .3s $md-transition-default-timing;
21+
display: flex;
22+
align-items: center;
23+
justify-content: center;
24+
right: -4px;
25+
font-size: 10px;
26+
font-style: normal;
27+
width: 22px;
28+
height: 22px;
29+
border-radius: 50%;
30+
color: #fff;
31+
pointer-events: none;
32+
z-index: 11;
33+
.md-list-item-content & {
34+
position: relative;
35+
top: 0;
36+
bottom: 0;
37+
right: 0;
38+
}
39+
&.md-dense {
40+
width: 18px;
41+
height: 18px;
42+
font-size: 8px;
43+
}
44+
&.md-square {
45+
width: auto;
46+
border-radius: 3px;
47+
height: 18px;
48+
padding: 0 4px;
49+
}
50+
}
51+
</style>

src/components/MdBadge/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import material from 'vue-material/material'
2+
import MdBadge from './MdBadge'
3+
4+
export default Vue => {
5+
material(Vue)
6+
Vue.component(MdBadge.name, MdBadge)
7+
}

src/components/MdBadge/theme.scss

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.md-badge {
2+
@include md-theme-component() {
3+
@include md-theme-property(color, text-primary, accent);
4+
@include md-theme-property(background-color, accent);
5+
6+
&.md-primary {
7+
@include md-theme-property(color, text-primary, primary);
8+
@include md-theme-property(background-color, primary);
9+
}
10+
}
11+
}

src/components/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import MdApp from './MdApp'
2+
import MdBadge from './MdBadge'
23
import MdAutocomplete from './MdAutocomplete'
34
import MdAvatar from './MdAvatar'
45
import MdBottomBar from './MdBottomBar'
@@ -37,6 +38,7 @@ import MdToolbar from './MdToolbar'
3738
import MdTooltip from './MdTooltip'
3839

3940
export {
41+
MdBadge,
4042
MdApp,
4143
MdAutocomplete,
4244
MdAvatar,

0 commit comments

Comments
 (0)