Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Breadcrumb): new component #506

Merged
merged 37 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ff9be01
feat(Breadcrumb): new component
Haythamasalama Aug 6, 2023
59c4888
up
Haythamasalama Aug 8, 2023
44c9b38
up
Haythamasalama Aug 8, 2023
46eec70
up
Haythamasalama Aug 8, 2023
0a19904
up
Haythamasalama Aug 11, 2023
2219f83
refactor: change to `item-tag`
Haythamasalama Aug 11, 2023
5c8f57d
refactor: make docs more clear
Haythamasalama Aug 11, 2023
2144f9d
refactor: remove `tag`
Haythamasalama Aug 11, 2023
0cfa53d
up
Haythamasalama Aug 18, 2023
ef74991
up
Haythamasalama Aug 22, 2023
3dac4b2
chore(deps): update devdependency unbuild to v2 (#565)
renovate[bot] Aug 28, 2023
9707eff
docs(ComponentCard): prevent `label` prop as select (#568)
eduayme Aug 28, 2023
e38bd46
docs: bump `@nuxthq/elements`
benjamincanac Sep 7, 2023
797c931
docs: bump `@nuxthq/elements`
benjamincanac Sep 8, 2023
8708c54
chore(deps): update all non-major dependencies (#612)
renovate[bot] Sep 9, 2023
a54c37c
docs: bump `@nuxthq/elements`
benjamincanac Sep 11, 2023
697bcdd
up
Haythamasalama Sep 14, 2023
8f2d46b
up
Haythamasalama Sep 14, 2023
8ba1c1a
up
Haythamasalama Sep 21, 2023
dfaef33
up
Haythamasalama Sep 21, 2023
ae5417e
up
Haythamasalama Sep 21, 2023
ad1606e
up
Haythamasalama Sep 21, 2023
20e5659
up
Haythamasalama Sep 21, 2023
f9b00d8
up
Haythamasalama Sep 21, 2023
0dab072
up
Haythamasalama Sep 21, 2023
9996125
up
Haythamasalama Sep 21, 2023
66c8140
Merge branch 'dev' into feat/breadcrumb-new-components
Haythamasalama Sep 21, 2023
043a8bc
Merge branch 'dev' into feat/breadcrumb-new-components
Haythamasalama Sep 28, 2023
cc03c52
Merge branch 'dev' into feat/breadcrumb-new-components
Haythamasalama Oct 5, 2023
9d892bf
Merge branch 'dev' into feat/breadcrumb-new-components
benjamincanac Nov 16, 2023
9da544f
up
benjamincanac Nov 16, 2023
257ac8a
up
benjamincanac Nov 16, 2023
daef2e1
up
benjamincanac Nov 16, 2023
bdf247e
up
benjamincanac Nov 16, 2023
f2bed1c
up
benjamincanac Nov 16, 2023
c15ddc5
up
benjamincanac Nov 16, 2023
fcc8a4e
up
benjamincanac Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/components/content/examples/BreadcrumbExampleBasic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script setup>
const links = [{
label: 'Home',
icon: 'i-heroicons-home',
to: '/'
}, {
label: 'Navigation',
icon: 'i-heroicons-square-3-stack-3d'
}, {
label: 'Breadcrumb',
icon: 'i-heroicons-link'
}]
</script>

<template>
<UBreadcrumb :links="links" />
</template>
20 changes: 20 additions & 0 deletions docs/components/content/examples/BreadcrumbExampleDefaultSlot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup>
const links = [{
label: 'Home',
to: '/'
}, {
label: 'Navigation'
}, {
label: 'Breadcrumb'
}]
</script>

<template>
<UBreadcrumb :links="links">
<template #default="{ link, isActive, index }">
<UBadge :color="isActive ? 'primary' : 'gray'" class="rounded-full">
{{ index + 1 }}. {{ link.label }}
</UBadge>
</template>
</UBreadcrumb>
</template>
21 changes: 21 additions & 0 deletions docs/components/content/examples/BreadcrumbExampleDividerSlot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup>
const links = [{
label: 'Home',
icon: 'i-heroicons-home',
to: '/'
}, {
label: 'Navigation',
icon: 'i-heroicons-square-3-stack-3d'
}, {
label: 'Breadcrumb',
icon: 'i-heroicons-link'
}]
</script>

<template>
<UBreadcrumb :links="links" :ui="{ ol: 'gap-x-3', li: 'gap-x-3' }">
<template #divider>
<span class="w-8 h-1 rounded-full bg-gray-300 dark:bg-gray-700" />
</template>
</UBreadcrumb>
</template>
25 changes: 25 additions & 0 deletions docs/components/content/examples/BreadcrumbExampleIconSlot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script setup>
const links = [{
label: 'Home',
to: '/'
}, {
label: 'Navigation'
}, {
label: 'Breadcrumb'
}]
</script>

<template>
<UBreadcrumb :links="links" :divider="null" :ui="{ ol: 'gap-x-3' }">
<template #icon="{ link, index, isActive }">
<UAvatar
:alt="(index + 1 ).toString()"
:ui="{
background: isActive ? 'bg-primary-500 dark:bg-primary-400' : undefined,
placeholder: isActive ? 'text-white dark:text-gray-900' : !!link.to ? 'group-hover:text-gray-700 dark:group-hover:text-gray-200' : ''
}"
size="xs"
/>
</template>
</UBreadcrumb>
</template>
16 changes: 16 additions & 0 deletions docs/content/1.getting-started/3.theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,13 +369,29 @@ export default defineAppConfig({
},
pagination: {
default: {
firstButton: {
icon: 'i-octicon-chevron-left-24'
},
prevButton: {
icon: 'i-octicon-arrow-left-24'
},
nextButton: {
icon: 'i-octicon-arrow-right-24'
},
lastButton: {
icon: 'i-octicon-chevron-right-24'
}
}
},
accordion: {
default: {
openIcon: 'i-octicon-chevron-down-24'
}
},
breadcrumb: {
default: {
divider: 'i-octicon-chevron-right-24'
}
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion docs/content/5.navigation/1.vertical-navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Pass an array to the `links` prop of the VerticalNavigation component. Each link

- `label` - The label of the link.
- `icon` - The icon of the link.
- `iconClass` - The class of the icon of the link.
- `iconClass` - The class of the icon link.
- `avatar` - The avatar of the link. You can pass all the props of the [Avatar](/elements/avatar) component.
- `badge` - A badge to display next to the label.
- `click` - The click handler of the link.
Expand Down
69 changes: 69 additions & 0 deletions docs/content/5.navigation/5.breadcrumb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Breadcrumb
description: A list of links that indicate the current page's location within a navigational hierarchy.
navigation:
badge: New
---

## Usage

Pass an array to the `links` prop of the Breadcrumb component. Each link can have the following properties:

- `label` - The label of the link.
- `icon` - The icon of the link.
- `iconClass` - The class of the icon link.

You can also pass any property from the [NuxtLink](https://nuxt.com/docs/api/components/nuxt-link#props) component such as `to`, `exact`, etc.

:component-example{component="breadcrumb-example-basic"}

::callout{icon="i-heroicons-light-bulb"}
A `span` will be rendered instead of a link when the `to` property is not defined.
::

## Divider

Use the `divider` prop to customize the divider between each link, it can be **an icon or a string**. You can change it globally in `ui.breadcrumb.default.divider`. Defaults to `i-heroicons-chevron-right-20-solid`.

You can set the prop to `null` to hide the divider. Additionally, you can customize it using the [`divider`](#divider-1) slot.

::component-card
---
baseProps:
links:
- label: Home
to: /
- label: Navigation
- label: Breadcrumb
props:
divider: '/'
---
::

## Slots

### `default`

Use the `#default` slot to customize the link label. You will have access to the `link`, `index` and `isActive` properties in the slot scope.

:component-example{component="breadcrumb-example-default-slot"}

### `icon`

Use the `#icon` slot to customize the link icon. You will have access to the `link`, `index` and `isActive` properties in the slot scope.

:component-example{component="breadcrumb-example-icon-slot"}

### `divider`

Use the `divider` slot to customize the divider of the Breadcrumb.

:component-example{component="breadcrumb-example-divider-slot"}

## Props

:component-props

## Config

:component-preset
84 changes: 84 additions & 0 deletions src/runtime/components/navigation/Breadcrumb.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<nav aria-label="Breadcrumb" :class="ui.wrapper" v-bind="attrs">
<ol :class="ui.ol">
<li v-for="(link, index) in links" :key="index" :class="ui.li">
<ULink
as="span"
:class="[ui.base, index === links.length - 1 ? ui.active : !!link.to ? ui.inactive : '']"
v-bind="omit(link, ['label', 'icon', 'iconClass'])"
:aria-current="index === links.length - 1 ? 'page' : undefined"
>
<slot name="icon" :link="link" :index="index" :is-active="index === links.length - 1">
<UIcon
v-if="link.icon"
:name="link.icon"
:class="[ui.icon.base, index === links.length - 1 ? ui.icon.active : !!link.to ? ui.icon.inactive : '', link.iconClass]"
/>
</slot>

<slot :link="link" :index="index" :is-active="index === links.length - 1">
{{ link.label }}
</slot>
</ULink>

<slot v-if="index < links.length - 1" name="divider">
<template v-if="divider">
<UIcon v-if="divider.startsWith('i-')" :name="divider" :class="ui.divider.base" role="presentation" />
<span v-else role="presentation">{{ divider }}</span>
</template>
</slot>
</li>
</ol>
</nav>
</template>

<script lang="ts">
import { defineComponent, toRef } from 'vue'
import type { PropType } from 'vue'
import UIcon from '../elements/Icon.vue'
import ULink from '../elements/Link.vue'
import { useUI } from '../../composables/useUI'
import { mergeConfig, omit } from '../../utils'
import type { BreadcrumbLink, Strategy } from '../../types'
// @ts-expect-error
import appConfig from '#build/app.config'
import { breadcrumb } from '#ui/ui.config'

const config = mergeConfig<typeof breadcrumb>(appConfig.ui.strategy, appConfig.ui.breadcrumb, breadcrumb)

export default defineComponent({
components: {
UIcon,
ULink
},
inheritAttrs: false,
props: {
links: {
type: Array as PropType<BreadcrumbLink[]>,
default: () => []
},
divider: {
type: String,
default: () => config.default.divider
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('breadcrumb', toRef(props, 'ui'), config, toRef(props, 'class'))

return {
// eslint-disable-next-line vue/no-dupe-keys
ui,
attrs,
omit
}
}
})
</script>
7 changes: 7 additions & 0 deletions src/runtime/types/breadcrumb.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Link } from './link'

export interface BreadcrumbLink extends Link {
label: string
icon?: string
iconClass?: string
}
1 change: 1 addition & 0 deletions src/runtime/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './accordion'
export * from './avatar'
export * from './badge'
export * from './breadcrumb'
export * from './button'
export * from './clipboard'
export * from './command-palette'
Expand Down
22 changes: 21 additions & 1 deletion src/runtime/ui.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ export const pagination = {
nextButton: {
color: 'white',
class: 'rtl:[&_span:last-child]:rotate-180',
icon: 'i-heroicons-chevron-right-20-solid '
icon: 'i-heroicons-chevron-right-20-solid'
}
}
}
Expand Down Expand Up @@ -1163,6 +1163,26 @@ export const tabs = {
}
}

export const breadcrumb = {
wrapper: 'relative',
ol: 'flex items-center gap-x-1.5',
li: 'flex items-center gap-x-1.5 text-gray-500 dark:text-gray-400 text-sm',
base: 'flex items-center gap-x-1.5 group font-semibold',
icon: {
base: 'flex-shrink-0 w-4 h-4',
active: '',
inactive: ''
},
divider: {
base: 'flex-shrink-0 w-5 h-5'
},
active: 'text-primary-500 dark:text-primary-400',
inactive: ' hover:text-gray-700 dark:hover:text-gray-200',
default: {
divider: 'i-heroicons-chevron-right-20-solid'
}
}

// Overlays

export const modal = {
Expand Down