Skip to content

Commit

Permalink
fix: (re-showing border for dropdown-activator in outline variant - u…
Browse files Browse the repository at this point in the history
…sed in navigation)
  • Loading branch information
Afiq Yasin Ramadhan authored and Afiq Yasin Ramadhan committed Mar 9, 2023
2 parents f9ac1fa + cf9123d commit 5a633c8
Show file tree
Hide file tree
Showing 19 changed files with 842 additions and 23 deletions.
4 changes: 4 additions & 0 deletions src/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ export default defineConfig({
text : 'Dashboard',
collapsed: true,
items : [
{
text: 'Breadcrumbs',
link: '/components/breadcrumbs/',
},
{
text: 'Filterbar',
link: '/components/filterbar/',
Expand Down
54 changes: 54 additions & 0 deletions src/components/breadcrumbs/Breadcrumb.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { render } from '@testing-library/vue'
import Breadcrumb from './Breadcrumb.vue'
import { defineNavigation } from '.'

const items = defineNavigation([
{
text: 'Dashboard',
href: '#',
},
{
text : 'Setting',
href : '#',
subitem: [
{
text: 'User',
href: '#',
},
],
},
])

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

const breadcrumbs = screen.queryByTestId('breadcrumbs')

expect(breadcrumbs).toBeInTheDocument()
expect(breadcrumbs).toHaveClass('breadcrumbs')
})

it('should be able to render navigation', () => {
const screen = render({
components: { Breadcrumb },
template : `
<Breadcrumb :items="items" />
`,
setup () {
return { items }
},
})

const breadcrumbs = screen.queryByTestId('breadcrumbs')
const text = screen.getAllByText('Dashboard')
const dropdown = screen.getByTestId('breadcrumbs-dropdown')

expect(breadcrumbs).toBeInTheDocument()
expect(breadcrumbs).toContainElement(dropdown)
expect(text).toHaveLength(1)
})
59 changes: 59 additions & 0 deletions src/components/breadcrumbs/Breadcrumb.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<ul
class="breadcrumbs"
data-testid="breadcrumbs">
<slot>
<template
v-for="(item, id) in items"
:key="id">
<BreadcrumbItemDropdown
v-if="item.subitem"
:text="item.text"
:active="item.active"
:href="item.href">
<template
v-for="(subitem, idx) in item.subitem"
:key="idx">
<DropdownItem
:active="subitem.active"
:href="subitem.href">
{{ subitem.text }}
</DropdownItem>
</template>
</BreadcrumbItemDropdown>
<BreadcrumbItem
v-else
:active="item.active"
:href="item.href">
{{ item.text }}
</BreadcrumbItem>
</template>
</slot>
</ul>
</template>

<script lang="ts">
import { defineComponent } from 'vue-demi'
import { BreadcrumbItems } from '.'
import BreadcrumbItem from './BreadcrumbItem.vue'
import BreadcrumbItemDropdown from './BreadcrumbItemDropdown.vue'
import DropdownItem from '../dropdown/DropdownItem.vue'
export default defineComponent({
components: {
BreadcrumbItem, BreadcrumbItemDropdown, DropdownItem,
},
props: {
items: {
type : Array<BreadcrumbItems>,
default: () => {},
},
},
})
</script>

<style lang="postcss">
.breadcrumbs {
@apply flex space-x-3 items-center;
}
</style>
53 changes: 53 additions & 0 deletions src/components/breadcrumbs/BreadcrumbItem.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { render } from '@testing-library/vue'
import BreadcrumbItem from './BreadcrumbItem.vue'

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

const breadcrumbItem = screen.getByTestId('breadcrumbs-item')
const breadcrumbIcon = screen.queryByTestId('breadcrumbs-icon')

expect(breadcrumbItem).toBeInTheDocument()
expect(breadcrumbItem).toHaveClass('breadcrumbs__item')
expect(breadcrumbIcon).toBeInTheDocument()
})

it('should be able to set active via prop `active`', () => {
const screen = render({
components: { BreadcrumbItem },
template : `
<BreadcrumbItem active />
`,
})

const breadcrumbItem = screen.getByTestId('breadcrumbs-item')
const dropdownIcon = screen.queryByTestId('dropdown-icon')

expect(breadcrumbItem).toHaveClass('breadcrumbs__item--active')
expect(breadcrumbItem).toContainHTML('<span />')
expect(breadcrumbItem).not.toContainHTML('<a />')
expect(dropdownIcon).not.toBeInTheDocument()
})

it('should be able to set url permalink via prop `href`', () => {
const screen = render({
components: { BreadcrumbItem },
template : `
<BreadcrumbItem href="/home">
Home
</BreadcrumbItem>
`,
})

const breadcrumbItem = screen.getByTestId('breadcrumbs-item')
const text = screen.queryByText('Home')

expect(breadcrumbItem).toContainHTML('a')
expect(breadcrumbItem).not.toContainHTML('<span />')
expect(text).toBeInTheDocument()
})
95 changes: 95 additions & 0 deletions src/components/breadcrumbs/BreadcrumbItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<li
data-testid="breadcrumbs-item"
class="breadcrumbs__item"
:class="classNames">
<component
:is="tagName"
:href="permalink">
<slot />
</component>
<IconChevron
v-if="!active"
data-testid="breadcrumbs-icon"
class="breadcrumbs__item__icon" />
</li>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue-demi'
import IconChevron from '@carbon/icons-vue/lib/chevron--right/16'
import { TagVariant } from '.'
export default defineComponent({
components: { IconChevron },
props : {
href: {
type : String,
default: '#',
},
active: {
type : Boolean,
default: false,
},
},
setup (props) {
const classNames = computed(() => {
const result: string[] = ['']
if (props.active)
result.push('breadcrumbs__item--active')
return result
})
const tagName = computed(() => {
let tag: TagVariant = 'a'
if (props.active)
tag = 'span'
return tag
})
const permalink = computed(() => {
if (props.active)
return
return props.href
})
return {
classNames, tagName, permalink,
}
},
})
</script>

<style lang="postcss">
.breadcrumbs {
&__item {
@apply inline-flex text-sm items-center;
&:last-child {
& > .breadcrumbs__item__icon {
@apply hidden;
}
}
&:not(:last-child) {
& > .breadcrumbs__item__icon {
@apply inline-flex ml-3;
}
}
& > a {
@apply text-subtle cursor-pointer underline decoration-solid hover:no-underline;
}
& > span {
@apply font-bold cursor-default;
}
}
}
</style>
45 changes: 45 additions & 0 deletions src/components/breadcrumbs/BreadcrumbItemDropdown.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { render } from '@testing-library/vue'
import BreadcrumbItemDropdown from './BreadcrumbItemDropdown.vue'

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

const breadcrumbDropdown = screen.queryByTestId('breadcrumbs-dropdown')
const breadcrumbIcon = screen.queryByTestId('breadcrumbs-icon')

expect(breadcrumbDropdown).toBeInTheDocument()
expect(breadcrumbDropdown).toHaveClass('breadcrumbs__item--dropdown')
expect(breadcrumbIcon).toBeInTheDocument()
})

it('should be able to set active via prop `active`', () => {
const screen = render({
components: { BreadcrumbItemDropdown },
template : `
<BreadcrumbItemDropdown active />
`,
})

const breadcrumbDropdown = screen.queryByTestId('breadcrumbs-dropdown')

expect(breadcrumbDropdown).toBeInTheDocument()
expect(breadcrumbDropdown).toHaveClass('breadcrumbs__item--active')
})

it('should be able to set dropdown activator via prop `text`', () => {
const screen = render({
components: { BreadcrumbItemDropdown },
template : `
<BreadcrumbItemDropdown text="Document" />
`,
})

const breadcrumbDropdown = screen.queryByTestId('breadcrumbs-dropdown')

expect(breadcrumbDropdown).toHaveTextContent('Document')
})
70 changes: 70 additions & 0 deletions src/components/breadcrumbs/BreadcrumbItemDropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<li
data-testid="breadcrumbs-dropdown"
class="breadcrumbs__item"
:class="classNames">
<Dropdown
:text="text"
placement="bottom-end"
size="xs">
<slot />
</Dropdown>
<IconChevron
v-if="!active"
data-testid="breadcrumbs-icon"
class="breadcrumbs__item__icon" />
</li>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue-demi'
import Dropdown from '../dropdown/Dropdown.vue'
import IconChevron from '@carbon/icons-vue/lib/chevron--right/16'
export default defineComponent({
components: { Dropdown, IconChevron },
props : {
text: {
type : String,
default: '',
},
active: {
type : Boolean,
default: false,
},
},
setup (props) {
const classNames = computed(() => {
const result: string[] = ['breadcrumbs__item--dropdown']
if (props.active)
result.push('breadcrumbs__item--active')
return result
})
return { classNames }
},
})
</script>

<style lang="postcss">
.breadcrumbs__item {
&&--dropdown {
.dropdown__activator {
@apply px-0 text-subtle bg-transparent border-transparent hover:shadow-none hover:border-transparent hover:bg-transparent focus:shadow-none focus:border-transparent focus:bg-transparent;
}
}
&&--active {
.dropdown__activator {
@apply text-default;
& > .dropdown__caret {
@apply text-subtle;
}
}
}
}
</style>
Loading

0 comments on commit 5a633c8

Please sign in to comment.