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

Integrate Nuxt Icon #9

Merged
merged 1 commit into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,12 @@
### Nuxt Modules

- [Vuetify Nuxt Module](https://github.com/userquin/vuetify-nuxt-module) - Zero-config Nuxt Module for Vuetify
- [VueUse](https://github.com/vueuse/vueuse) - collection of useful composition APIs
- [Pinia](https://github.com/vuejs/pinia) - intuitive, type-safe, light and flexible Store for Vue
- [DevTools](https://github.com/nuxt/devtools) - unleash Nuxt Developer Experience
- [VueUse](https://github.com/vueuse/vueuse) - Collection of useful composition APIs
- [Pinia](https://github.com/vuejs/pinia) - Intuitive, type-safe, light and flexible Store for Vue
- [Nuxt Icon](https://github.com/nuxt/icon) - Icon module for Nuxt with 200,000+ ready to use icons from Iconify
- [Nuxt ECharts](https://github.com/kingyue737/nuxt-echarts) - Nuxt module for Apache ECharts™
- [Nuxt Auth Utils](https://github.com/Atinux/nuxt-auth-utils) - Minimalist Authentication module for Nuxt

### Plugins

- [`rollup-plugin-regexp`](https://github.com/kingyue737/rollup-plugin-regexp) - auto replace [`@mdi/font`](https://github.com/Templarian/MaterialDesign-Webfont) with [`@mdi/js`](https://github.com/Templarian/MaterialDesign-JS) in `<VIcon>`, reduce bundle size

### Coding Style

- [Prettier](https://prettier.io/), single quotes, no semi
Expand All @@ -91,11 +88,10 @@
- [pnpm](https://pnpm.js.org/) - Fast, disk space efficient package manager
- [Netlify](https://www.netlify.com/) - zero-config deployment
- [VS Code Extensions](./.vscode/extensions.json)
- [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - TypeScript support inside Vue SFCs
- [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - TypeScript support inside Vue SFCs
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Find and fix problems in your code
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Code formatter
- [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)
- [Material Design Icons Intellisense](https://marketplace.visualstudio.com/items?itemName=lukas-tr.materialdesignicons-intellisense)

## Try it now!

Expand Down
3 changes: 1 addition & 2 deletions assets/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ html {
}
}

.v-icon svg {
fill: currentColor;
.v-icon .iconify {
width: 100%;
height: 100%;
}
1 change: 1 addition & 0 deletions augmentation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ declare module '#app' {
declare module '#auth-utils' {
interface User {
login: string
avatar_url: string
}
}

Expand Down
2 changes: 1 addition & 1 deletion components/App/AppBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const { loggedIn, clear, user } = useUserSession()
<v-btn icon v-bind="mergeProps(menu, tooltip)" class="ml-1">
<v-icon v-if="!loggedIn" icon="mdi-account-circle" size="36" />
<v-avatar v-else color="primary" size="36">
<v-img :src="`https://github.com/${user!.login}.png`" />
<v-img :src="user?.avatar_url" />
</v-avatar>
</v-btn>
</template>
Expand Down
96 changes: 50 additions & 46 deletions components/App/AppNotification.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,58 @@ function toggleAll() {
:rounded="0"
@click="toggleAll"
/>
<teleport to="body">
<v-card
elevation="6"
width="400"
class="d-flex flex-column notification-card"
:class="{ 'notification-card--open': showAll }"
>
<v-toolbar flat density="compact">
<v-toolbar-title
class="font-weight-light text-body-1"
:text="notifications.length ? 'Notification' : 'No New Notifications'"
/>
<v-btn
v-tooltip="{ text: 'Clear All Notifications' }"
size="small"
icon="mdi-bell-remove"
@click="emptyNotifications"
/>
<v-btn
v-tooltip="{ text: 'Hide Notifications' }"
class="mr-0"
size="small"
icon="$expand"
@click="toggleAll"
/>
</v-toolbar>
<v-slide-y-reverse-transition
tag="div"
class="d-flex flex-column notification-box"
group
hide-on-leave
<ClientOnly>
<teleport to="body">
<v-card
elevation="6"
width="400"
class="d-flex flex-column notification-card"
:class="{ 'notification-card--open': showAll }"
>
<div
v-for="notification in notificationsShown"
:key="notification.id"
class="notification-item-wrapper"
>
<AppNotificationItem
v-model="notification.show"
:notification="notification"
:timeout="timeout"
class="notification-item"
@close="deleteNotification(notification.id)"
<v-toolbar flat density="compact">
<v-toolbar-title
class="font-weight-light text-body-1"
:text="
notifications.length ? 'Notification' : 'No New Notifications'
"
/>
<v-btn
v-tooltip="{ text: 'Clear All Notifications' }"
size="small"
icon="mdi-bell-remove"
@click="emptyNotifications"
/>
</div>
</v-slide-y-reverse-transition>
</v-card>
</teleport>
<v-btn
v-tooltip="{ text: 'Hide Notifications' }"
class="mr-0"
size="small"
icon="$expand"
@click="toggleAll"
/>
</v-toolbar>
<v-slide-y-reverse-transition
tag="div"
class="d-flex flex-column notification-box"
group
hide-on-leave
>
<div
v-for="notification in notificationsShown"
:key="notification.id"
class="notification-item-wrapper"
>
<AppNotificationItem
v-model="notification.show"
:notification="notification"
:timeout="timeout"
class="notification-item"
@close="deleteNotification(notification.id)"
/>
</div>
</v-slide-y-reverse-transition>
</v-card>
</teleport>
</ClientOnly>
</template>

<style scoped>
Expand Down
43 changes: 14 additions & 29 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
import regexpPlugin from 'rollup-plugin-regexp'
import * as mdicons from '@mdi/js'

const mdi: Record<string, string> = {}
Object.keys(mdicons).forEach((key) => {
const value = (mdicons as Record<string, string>)[key]
mdi[
key
.replace(/([A-Z])/g, '-$1')
.toLowerCase()
.replace(/([0-9]+)/g, '-$1')
] = value
})

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
Expand All @@ -21,6 +7,7 @@ export default defineNuxtConfig({
'vuetify-nuxt-module',
'nuxt-auth-utils',
'nuxt-echarts',
'@nuxt/icon',
'@nuxt/eslint',
'@nuxt/test-utils/module',
],
Expand All @@ -39,6 +26,19 @@ export default defineNuxtConfig({
},
},
},
icon: {
mode: 'svg',
clientBundle: {
// scan all components in the project and include icons
// scan: true,
},
customCollections: [
{
prefix: 'custom',
dir: './assets/icons',
},
],
},
echarts: {
charts: ['LineChart', 'BarChart', 'PieChart', 'RadarChart'],
renderer: 'svg',
Expand All @@ -54,21 +54,6 @@ export default defineNuxtConfig({
],
},
vite: {
plugins: [
regexpPlugin({
exclude: ['node_modules/**'],
find: /\b(?<![/\w])(mdi-[\w-]+)\b(?!\.)/,
replace: (match: string) => {
if (mdi[match]) {
return mdi[match]
} else {
console.warn('[plugin-regexp] No matched svg icon for ' + match)
return match
}
},
sourcemap: false,
}),
],
build: { sourcemap: false },
},
runtimeConfig: {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
"format": "prettier . --write"
},
"devDependencies": {
"@mdi/js": "^7.4.47",
"@iconify-json/mdi": "^1.1.68",
"@nuxt/eslint": "^0.5.3",
"@nuxt/icon": "^1.5.0",
"@nuxt/test-utils": "^3.14.1",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.9.1",
Expand All @@ -24,7 +25,6 @@
"nuxt-echarts": "^0.2.2",
"playwright-core": "^1.46.1",
"prettier": "^3.3.3",
"rollup-plugin-regexp": "^5.0.1",
"vitest": "^2.0.5",
"vue-tsc": "^2.0.29",
"vuetify-nuxt-module": "^0.17.1"
Expand Down
37 changes: 14 additions & 23 deletions plugins/vuetify.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
import { type IconSet, type IconProps } from 'vuetify'
import type { IconProps } from 'vuetify'
import { Icon } from '#components'
import type { VDataTable } from 'vuetify/components'
import { useStorage } from '@vueuse/core'
export type DataTableHeaders = VDataTable['$props']['headers']

function filename(path: string) {
return path
.split(/(\\|\/)/g)
.pop()!
.replace(/\.[^/.]+$/, '')
}
import { aliases } from 'vuetify/iconsets/mdi'

const svgIcons = Object.fromEntries(
Object.entries(
import.meta.glob('~/assets/icons/*.svg', {
eager: true,
query: '?raw',
import: 'default',
}),
).map(([k, v]) => [filename(k), v]),
)
const custom: IconSet = {
component: (props: IconProps) =>
h(props.tag, { innerHTML: svgIcons[props.icon as string] }),
}
export type DataTableHeaders = VDataTable['$props']['headers']

export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('vuetify:configuration', ({ vuetifyOptions }) => {
vuetifyOptions.icons!.sets!['custom'] = custom
vuetifyOptions.icons = {
defaultSet: 'nuxtIcon',
sets: {
nuxtIcon: {
component: ({ icon, tag, ...rest }: IconProps) =>
h(tag, rest, [h(Icon, { name: aliases[icon as string] ?? icon })]),
},
},
aliases,
}
const primary = useStorage('theme-primary', '#1697f6').value
vuetifyOptions.theme = {
themes: {
Expand Down
Loading