Code Monkey home page Code Monkey logo

selemondev / nuxt-ui-vue Goto Github PK

View Code? Open in Web Editor NEW
45.0 6.0 4.0 651 KB

:construction: WIP Fully styled and customizable components from Nuxt UI to Vue 3.

Home Page: https://www.npmjs.com/package/nuxt-ui-vue

License: MIT License

HTML 0.13% JavaScript 0.16% TypeScript 44.39% Vue 55.23% CSS 0.10%
nuxt tailwindcss-components-library ui-components vue-component-library vue-components vue3-typescript component-framework nuxt-components ui-framework vue3-component-library

nuxt-ui-vue's Introduction

Nuxt-UI-Vue

Current Versions

With each release of nuxt-ui a parallel update will be applied to nuxt-ui-vue, ensuring that the library is up to date and providing you, as the developer, with a seamless experience.

Below are the current versions of both libraries:

nuxt-ui nuxt-ui-vue
v2.8.1 v1.0.1-beta.9

Features

  • ๐Ÿฆพ TypeScript Support - Built with TypeScript in mind and from the ground up.
  • ๐Ÿ”ฅ Icon - Use any icon from Iconify in your project from your favourite icon set.
  • ๐Ÿ› ๏ธ On Demand Import - Nuxt UI Vue comes with an intelligent resolver that automatically imports only used components.
  • โšก๏ธ Powerful Tools - Nuxt UI Vue is built on top of powerful tools such as TailwindCss, VueUse, Headless UI etc.
  • ๐ŸŽจ Themeable - Customize any component to match your brand and style.

Getting Started

Add Nuxt UI Vue to your project by running one of the following commands below:

# pnpm
pnpm add nuxt-ui-vue

# yarn
yarn add nuxt-ui-vue

# npm
npm install nuxt-ui-vue

And also add @tailwindcss/forms plugin by running the following command:

# pnpm
pnpm add -D @tailwindcss/forms

# yarn
yarn add --dev @tailwindcss/forms

# npm
npm install -D @tailwindcss/forms

Usage

  1. Register the @tailwindcss/forms plugin and add the Nuxt-UI-Vue theme file, the darkMode class and the tailwindCss colors configuration in your tailwind.config.cjs file as shown below:
import tailwindColors from './node_modules/tailwindcss/colors'

const colorSafeList = []

const deprecated = ['lightBlue', 'warmGray', 'trueGray', 'coolGray', 'blueGray']

for (const colorName in tailwindColors) {
  if (deprecated.includes(colorName))
    continue

  const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]

  const pallette = tailwindColors[colorName]

  if (typeof pallette === 'object') {
    shades.forEach((shade) => {
      if (shade in pallette) {
        colorSafeList.push(`text-${colorName}-${shade}`),
        colorSafeList.push(`accent-${colorName}-${shade}`),
        colorSafeList.push(`bg-${colorName}-${shade}`),
        colorSafeList.push(`hover:enabled:bg-${colorName}-${shade}`),
        colorSafeList.push(`focus:bg-${colorName}-${shade}`),
        colorSafeList.push(`ring-${colorName}-${shade}`),
        colorSafeList.push(`focus:ring-${colorName}-${shade}`),
        colorSafeList.push(`border-${colorName}-${shade}`)
      }
    })
  }
}
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}', 'node_modules/nuxt-ui-vue/dist/theme/*.{js,jsx,ts,tsx,vue}'],
  darkMode: 'class',
  safelist: colorSafeList,
  theme: {
    extend: {
      colors: tailwindColors
    },
  },
  plugins: [require('@tailwindcss/forms')],
}

Since TailwindCss doesn't support dynamic class names, you need to configure the tailwind.config.cjs file as shown above. You can read more about safelisting tailwindcss classes here

Component registration

With Nuxt UI Vue, you have the flexibility to register components precisely as you wish:

Import All Components

To import all the components provided by Nuxt UI Vue, add Nuxt UI Vue in your main entry file as shown below:

With Nuxt-UI-Vue, you have the flexibility to register components precisely as you wish:

import { createApp } from 'vue'
import './style.css'
import nuxtLabsTheme from 'nuxt-ui-vue/dist/theme/nuxtlabsTheme'

import install from 'nuxt-ui-vue'
import App from './App.vue'

const app = createApp(App)
app.use(install, nuxtLabsTheme)
app.mount('#app')

By doing this, you are importing all the components that are provided by Nuxt-UI-Vue and in your final bundle all the components including the ones you didn't use will be bundled. Use this method of component registration if you are confident that you will use all the components.

Individual Components with Tree Shaking

Probably you might not want to globally register all the components but instead only import the components that you need. You can achieve this by doing the following:

  1. Import the createUI option as well as the components you need as shown below:
import { createApp } from 'vue'
import './style.css'
import nuxtLabsTheme from 'nuxt-ui-vue/dist/theme/nuxtlabsTheme'

import { UButton, UDropdown, createUI } from 'nuxt-ui-vue'

import App from './App.vue'

const app = createApp(App)

const UI = createUI({
  prefix: 'T',
  components: [UDropdown, UButton],
})

app.use(UI, nuxtLabsTheme)

app.mount('#app')
  1. Now you can use the component as shown below:
<script setup lang='ts'>
const items = [
  [{
    label: 'Profile',
    avatar: {
      src: 'https://avatars.githubusercontent.com/u/739984?v=4'
    }
  }], [{
    label: 'Edit',
    icon: 'heroicons:pencil-square-20-solid',
    shortcuts: ['E'],
    click: () => {
      // eslint-disable-next-line no-console
      console.log('Edit')
    }
  }, {
    label: 'Duplicate',
    icon: 'heroicons:document-duplicate-20-solid',
    shortcuts: ['D'],
    disabled: true
  }], [{
    label: 'Archive',
    icon: 'heroicons:archive-box-20-solid'
  }, {
    label: 'Move',
    icon: 'heroicons:arrow-right-circle-20-solid'
  }], [{
    label: 'Delete',
    icon: 'heroicons:trash-20-solid',
    shortcuts: ['โŒ˜', 'D']
  }]
]
</script>

<template>
  <div class="grid place-items-center w-full min-h-screen">
    <div>
      <TDropdown :items="items" :popper="{ placement: 'bottom-start' }">
        <TButton color="white" label="Options" trailing-icon="heroicons:chevron-down-20-solid" />
      </TDropdown>
    </div>
  </div>
</template>

The prefix option is only available for individual component imports.

Auto Imports with Tree Shaking

Nuxt-UI-Vue comes with an intelligent resolver that automatically imports only used components.

This is made possible by leveraging a tool known as unplugin-vue-components which lets you auto import components on demand thus omitting import statements and still get the benefits of tree shaking.

To achieve this you need to do the following:

  1. Install the unplugin-vue-components package by running one of the following commands:
#pnpm
pnpm add -D unplugin-vue-components

#yarn
yarn add -D unplugin-vue-components

#npm
npm i -D unplugin-vue-components
  1. Head over to your main.ts or main.js file and set registerComponents to false as shown below:
import { createApp } from 'vue'
import './style.css'
import nuxtLabsTheme from 'nuxt-ui-vue/dist/theme/nuxtlabsTheme'

import { createUI } from 'nuxt-ui-vue'

import App from './App.vue'

const app = createApp(App)

const UI = createUI({
  registerComponents: false,
})

app.use(UI, nuxtLabsTheme)

app.mount('#app')
  1. Head over to your vite.config.ts or vite.config.js file and add the following:
// other imports
import { NuxtUIVueComponentResolver } from 'nuxt-ui-vue'
import Components from 'unplugin-vue-components/vite'

export default defineConfig({
  plugins: [
    // other plugins
    Components({
      resolvers: [
        NuxtUIVueComponentResolver()
      ]
    })
  ],
})
  1. Now you can simply use any component that you want and it will be auto imported on demand โœจ
<script setup lang='ts'>
const items = [
  [{
    label: 'Profile',
    avatar: {
      src: 'https://avatars.githubusercontent.com/u/739984?v=4'
    }
  }], [{
    label: 'Edit',
    icon: 'heroicons:pencil-square-20-solid',
    shortcuts: ['E'],
    click: () => {
      // eslint-disable-next-line no-console
      console.log('Edit')
    }
  }, {
    label: 'Duplicate',
    icon: 'heroicons:document-duplicate-20-solid',
    shortcuts: ['D'],
    disabled: true
  }], [{
    label: 'Archive',
    icon: 'heroicons:archive-box-20-solid'
  }, {
    label: 'Move',
    icon: 'heroicons:arrow-right-circle-20-solid'
  }], [{
    label: 'Delete',
    icon: 'heroicons:trash-20-solid',
    shortcuts: ['โŒ˜', 'D']
  }]
]
</script>

<template>
  <div class="grid place-items-center w-full min-h-screen">
    <div>
      <UDropdown :items="items" :popper="{ placement: 'bottom-start' }">
        <UButton color="green" label="Options" trailing-icon="heroicons:chevron-down-20-solid" />
      </UDropdown>
    </div>
  </div>
</template>

Component Customizations

In regards to customization, Nuxt UI Vue offers two ways of customizing your components. The first way is through the variants property and the second way is by creating your own theme file.

Here is an example of customizing a UButton component through the variants property:

<template>
  <div>
    <UButton
      :variants="{
        'my-variant': {
          rounded: 'rounded-full',
        },
      }" :variant="['my-variant']" color="red" label="Button"
    />
  </div>
</template>

By default, the default roundedness of the UButton component is rounded-md. However, we have customized its appearance by using the variants property to change its roundedness and then we used the variant prop to pass our variant which is my-variant ( you can name it whatever you want) to the variant array and now the UButton component will be rendered with a fully rounded appearance (rounded-full).

You can customize each component this way using the component's preset which can be found here

For any component that uses the variant prop such as the UButton, UBadge, UInput, UTextarea, USelect, etc, use the intent prop instead as shown below:

<template>
    <div>
        <UButton intent="soft" color="red" label="Button" />
    </div>
</template>
<template>
  <div>
    <UBadge color="red" intent="solid" label="Badge" />
  </div>
</template>

The Notifications component comes with a position prop to enable you to specify the position of the Notifications component. To get started with it, you need to import the injectToast() function and the UNotifications component in your App.vue file as shown below:

<!-- app.vue file -->
<script setup lang="ts">
import { injectToast } from 'nuxt-ui-vue'

injectToast()
</script>

<template>
  <div>
    <Hello />
    <UNotifications position="top-right" />
  </div>
</template>

By default, the position of the component is set to bottom-right.

Then in your other component, for example, Hello.vue component, you can do the following:

<!-- Hello.vue component -->

<script setup lang="ts">
import { useToast } from 'nuxt-ui-vue'

const toast = useToast()
</script>

<template>
  <UButton
    label="Show toast" @click="toast.add({
      title: 'Update downloaded.',
      description: 'It will be installed on restart. Restart now?',
      icon: 'octicon:desktop-download-24',
    })"
  />
</template>

๐Ÿฅณ Well done, you can now go ahead and build your web application with ease.

Contributions

Contributions are welcome and encouraged! If you have any ideas or suggestions for new features, or if you encounter any bugs or issues, please open an issue or submit a pull request on the GitHub repository.

Developers interested in contributing should read the Code of Conduct and the Contributing Guide.

Credits

License

MIT License ยฉ 2023 Selemondev

nuxt-ui-vue's People

Contributors

angelhdzmultimedia avatar cuiyajie avatar selemondev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nuxt-ui-vue's Issues

Questions about your workflow and plan for the future

Really cool ! Thanks a lot for all this work !

I use nuxt in many projects, and a build web extension with https://github.com/antfu/vitesse-webext
I plan to rewrite some projects with nuxtlabs/ui, and the web extension. Your repo is just what I need :)

I want to know about your workflow.
How do you follow the nuxtlabs/ui developement ? Do you watch every new commit on nuxtlabs/ui, or have you automatized some stuffs ? Do you plan to match exactly the same architecture and component ? And of course, will you follow all update made in nuxtlabs/ui ?

Thanks again.

Custom Iconset by iconfiy

I notice that nuxt-ui-vue use iconify to support icon. That is good framework. Now I want to add my own icon collection, then use them in nuxt-ui-vue.

import { addCollection } from '@iconify/vue'
addCollection({
    prefix: 's24',
    icons: tranIcons,
    width: 24,
    height: 24
  }, 'b3d')

for example

toast.add({  title: '1234',  timeout: 0, icon: '@b3d:s24:cross-filled' })

I find that loadIcon throw error in UIcon component. Any example can show how to use custom iconset?

Recommend use Symbol as globalVariant key

Is your feature request related to a problem? Please describe.

I notice that 'config' was used as global variants inject key. That will make user confused when same key is used in own project.

Describe the solution you'd like

I think we should use Symbol('nuxt-config') as the key and export it for user

Migration issues from nuxt-ui to nuxt-ui-vue

Here is my first attempt in trying to replace @nuxthq/ui with nuxt-ui-vue in my nuxt app.

Here is a online demo of the original nuxt ui repo - https://pg-nuxtui.netlify.app/, github - https://github.com/pinegrow/pg-nuxtui

Reproduction with nuxt-ui-vue:
https://github.com/TechAkayy/pg-nuxtui-vue

Few issues:

  1. I had to comment-out UAvatar component in my HeroSection.vue as I was getting some Image is not defined error.
  2. I had my own safelisting logic already, and used it in place of nuxtlabs/ui module's ui > safelistColors options. But for some reason, my palette colors are getting ignored.
  3. Nuxtlabs/ui uses the iconify's unocss format with the i- prefix. I installed @unocss/nuxt and other packages, but the icons are not getting working.

Thank you for this great effort. Will play it with it more.

Many transitions not work well

For example,

const notificationTransitions = {
  enter: variant.value.transitionEnterActiveClass,
  enterFrom: variant.value.transitionEnterFromClass,
  enterTo: variant.value.transitionEnterToClass,
  leave: variant.value.transitionLeaveActiveClass,
  leaveFrom: variant.value.transitionLeaveFromClass,
  leaveTo: variant.value.transitionLeaveToClass,
}

should be:

const notificationTransitions = {
  enterClass: variant.value.transitionEnterActiveClass,
  enterFromClass: variant.value.transitionEnterFromClass,
  enterToClass: variant.value.transitionEnterToClass,
  leaveClass: variant.value.transitionLeaveActiveClass,
  leaveFromClass: variant.value.transitionLeaveFromClass,
  leaveToClass: variant.value.transitionLeaveToClass,
}

you should check the component Transition is from '@headlessui/vue' or 'vue'

rename package

Rename nuxtlabs-ui-vue to nuxt-ui-vue so as to make the naming consistent across the repository to avoid confusion. This change will affect the project's name, package's name and documentation.

remove `lodash-es` as a runtime dependency

Describe the bug

As stated by @danielroe in the official nuxt ui lib's repo issue #642: "Looking at performance, I'd recommend removing the runtime lodash-es dependency. A lot of the utilities can be replaced with core JS, and I think also make it easier to reason about."

image validation error

Describe the bug
A clear and concise description of what the bug is.

When using image URLs from different providers, the image validation fails and displays a warning error in the console.

changing some props in custom theme has no effect

Describe the bug

I'm trying to implement my own theme following the documentation. However, there are certain parameters that are not being considered, such as UButton "size," "color", "intent" etc.

But when i change UButton "rounded" for example, it works...

To Reproduce

// main
...
import nuxtLabsTheme from './customTheme'

import { createUI } from 'nuxt-ui-vue'

import App from './App.vue'

const app = createApp(App)

const UI = createUI({
  registerComponents: false,
})

app.use(UI, nuxtLabsTheme)

...
// customTheme
export default {
 ...
 UButton: {
    base : {
     ....
       default : {
         ...
         color: "red" <------------------------
       }
    }
 }

Expected behavior
the default color of a button must be red, or i still have a green button

Button variants not getting applied

Describe the bug
Assigning a variant to a Button does not do anything.

To Reproduce
Steps to reproduce the behavior:

  1. Assign variant outline (or ghost/soft/link) to UButton component
    • e.g. <UButton variant="outline">Button</UButton> in any .vue template
  2. See that no outline variant has been applied

Expected behavior
When assigning variant="outline" to the Button component, I'm expecting to see the Button have the outlined style shown in NuxtUI docs.

Screenshots
image
image

Additional context
Version: nuxt-ui-vue ^0.0.9

nuxtlabsTheme resolve error when use vite build

I refer nuxtlabasTheme like import nuxtLabsTheme from 'nuxt-ui-vue/dist/theme/nuxtlabsTheme. but github ci builder will throw error

[vite]: Rollup failed to resolve import "nuxt-ui-vue/dist/theme/nuxtlabsTheme" from "/home/runner/work/b3d-frontend/b3d-frontend/web/src/ui/theme.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
error during build:

I build this well in local, but github ci builder always throw error through tried other vite config.

I found same case here: vitejs/vite#7312

So, can we change the export style of nuxtlabsTheme like export { default as nuxtlabsTheme } from '@/theme/nuxtlabsTheme' in index.ts? or same question have you met? how to solve it?

Thanks a lot. Best wishes to you.

Form

The Form component is used to validate form data using schema libraries such as Yup, Zod, Joi, Valibot or your own validation logic. It should work seamlessly with the FormGroup component to automatically display error messages around form elements.

The Form component requires the validate and state props for form validation.

  • state - A reactive object that holds the current state of the form.
  • validate - A function that takes the form's state as input and returns an array of FormError objects with the following fields:
  • message - The error message to display.
  • path - The path to the form element matching the name.

Npm package name

As it's very early days, would be great to have the npm package sync with the name as nuxt-ui-vue.

It's not taken yet on npm, and would be easy for new users to install easily, when the name sync with the npm package name.

The reason why nuxtlabs/ui didn't change their package name is probably because they existed long before it was made open-source - more details here.. nuxt/ui#538 (comment)

But, there might be a reason for your to keep it as *labs, if you want to retain the coupling with the upstream. But, naming a package as nuxtlabs might raise the assumption that it's one of nuxtlabs project, no harm there, but it's just cleaner to be simpler.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.