diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31bf7db9..8970fe1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ This repository is structured as follows: ``` apps └── www - ├── src + ├── src │ └── content └── registry ├── default @@ -32,12 +32,12 @@ packages └── cli ``` -| Path | Description | -| --------------------- | ---------------------------------------- | -| `apps/www/app` | The Next.js application for the website. | -| `apps/www/content` | The content for the website. | -| `apps/www/registry` | The registry for the components. | -| `packages/cli` | The `shadcn-vue` package. | +| Path | Description | +| ----------------------------| -------------------------------------------| +| `apps/www/.vitepress` | The Vitepress application for the website. | +| `apps/www/src/content` | The content for the website. | +| `apps/www/src/lib/registry` | The registry for the components. | +| `packages/cli` | The `shadcn-vue` package. | ## Development @@ -79,22 +79,24 @@ The documentation for this project is located in the `www` workspace. You can ru pnpm dev ``` -Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/content/docs` directory. +Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/src/content` directory. ## Components -We use a registry system for developing components. You can find the source code for the components under `apps/www/registry`. The components are organized by styles. +We use a registry system for developing components. You can find the source code for the components under `apps/www/src/lib/registry`. The components are organized by styles. ```bash apps └── www - └── registry - ├── default - │ ├── example - │ └── ui - └── new-york - ├── example - └── ui + └── src + └── lib + └── registry + ├── default + │ ├── example + │ └── ui + └── new-york + ├── example + └── ui ``` When adding or modifying components, please ensure that: @@ -130,13 +132,10 @@ the following categories: e.g. `feat(components): add new prop to the avatar component` - If you are interested in the detailed specification you can visit https://www.conventionalcommits.org/ or check out the [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines). - - ## Requests for new components If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out. @@ -155,4 +154,4 @@ Tests are written using [Vitest](https://vitest.dev). You can run all the tests pnpm test ``` -Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests. \ No newline at end of file +Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests. diff --git a/apps/www/.vitepress/theme/config/docs.ts b/apps/www/.vitepress/theme/config/docs.ts index ea8631df..31187fdc 100644 --- a/apps/www/.vitepress/theme/config/docs.ts +++ b/apps/www/.vitepress/theme/config/docs.ts @@ -98,6 +98,12 @@ export const docsConfig: DocsConfig = { href: '/docs/about', items: [], }, + { + title: 'Contribution', + href: '/docs/contribution', + items: [], + label: 'New', + }, ], }, { diff --git a/apps/www/src/assets/diagrams.drawio b/apps/www/src/assets/diagrams.drawio new file mode 100644 index 00000000..0801ae38 --- /dev/null +++ b/apps/www/src/assets/diagrams.drawio @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/src/content/docs/contribution.md b/apps/www/src/content/docs/contribution.md new file mode 100644 index 00000000..1ca556a2 --- /dev/null +++ b/apps/www/src/content/docs/contribution.md @@ -0,0 +1,341 @@ +--- +title: Contribution +description: Learn on how to contribute to shadcn/vue. +--- +## Introduction + +Thanks for your interest in contributing to shadcn-vue.com. We're happy to have you here. + +Please take a moment to review this document before submitting your first pull request. We also strongly recommend that you check for open issues and pull requests to see if someone else is working on something similar. + +If you need any help, feel free to reach out to the core team on [Discord](https://chat.radix-vue.com/). + +This guide provides detailed information to help new contributors. + +## About this repository + +This repository is a monorepo. + +- We use [pnpm](https://pnpm.io) and [`workspaces`](https://pnpm.io/workspaces) for development. + +## Project Structure + +The GitHub repository consists of the several folders. here's a quick view. + + + +1. **packages** - +Contains source code for supporting `nuxt` as a module and the `cli` to add new components. + +2. **apps/www** - +The main folder that holds the source code for the website and every `shadcn/vue` component. This folder contains important sub-folders and is a subproject with its own `package.json`. + +3. **.vitepress** - +Contains the configuration and source code for `vitepress` and the `shadcn/vue` website. + +4. **src** - +Hosts the main source code for every `shadcn/vue` component or demo and their documentation on the website. + +5. **\_\_registry\_\_** - +Holds the registry file generated by `scripts/build-registry.ts` to serve components for the `cli`. This folder's content is auto-generated and should not be edited manually. + +6. **scripts** - +Contains various helper scripts, such as `build-registry.ts`, which automatically generates the `__registry__` folder. + +7. **content** - +This folder holds all the documentation for the `/docs` route. Each component has one `.md` file documenting the installation and usage of the component. + +8. **examples** - +Holds all examples not part of `/docs`, like the [main page](/). + +9. **lib/registry** - +The main folder hosts the source code for different styles of every component. This is likely the main folder you'll be changing. + +We support two different styles for every component in `shadcn/vue`: + +1. Default +2. New York + +Every component added to the repository must support both versions, including the main source code and associated demos. + +When adding or modifying components, please ensure that: + +1. You make the changes for every style. +2. You update the documentation. +3. You run `pnpm build:registry` to update the registry. + +## Development + +Start by cloning the repository: + +```bash +git clone git@github.com:radix-vue/shadcn-vue.git +``` + +### Install dependencies + +```bash +pnpm install +``` + +### Run a workspace + +You can use the `pnpm --filter=[WORKSPACE]` command to start the development process for a workspace or some of the shortcut command that we have setup. + +#### Examples + +1. To run the `shadcn-vue.com` website: + +``` +pnpm dev +``` + +2. To run the `shadcn-vue` cli package: + +``` +pnpm dev:cli +``` + +## Documentation + +The documentation for this project is located in the `www` workspace. You can run the documentation locally by running the following command: + +```bash +pnpm dev +``` + +Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/src/content` directory. + +## CLI + +The `shadcn-vue` package is a CLI for adding components to your project. You can find the documentation for the CLI [here](https://shadcn-vue.com/docs/cli). + +Any changes to the CLI should be made in the `packages/cli` directory. If you can, it would be great if you could add tests for your changes. + +## Testing + +Tests are written using [Vitest](https://vitest.dev). You can run all the tests from the root of the repository. + +```bash +pnpm test +``` + +Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests. + +## Commit Convention + +Before you create a Pull Request, please check whether your commits comply with +the commit conventions used in this repository. + +When you create a commit we kindly ask you to follow the convention +`category(scope or module): message` in your commit message while using one of +the following categories: + +- `feat / feature`: all changes that introduce completely new code or new + features +- `fix`: changes that fix a bug (ideally you will additionally reference an + issue if present) +- `refactor`: any code related change that is not a fix nor a feature +- `docs`: changing existing or creating new documentation (i.e. README, docs for + usage of a lib or cli usage) +- `build`: all changes regarding the build of the software, changes to + dependencies or the addition of new dependencies +- `test`: all changes regarding tests (adding new tests or changing existing + ones) +- `ci`: all changes regarding the configuration of continuous integration (i.e. + github actions, ci system) +- `chore`: all changes to the repository that do not fit into any of the above + categories + + e.g. `feat(components): add new prop to the avatar component` + +If you are interested in the detailed specification you can visit [Conventional Commits](https://www.conventionalcommits.org/). + +## SFC - Single File Components + +Multiple components are integrated into one file in `shadcn/ui` - the React version of `shadcn` - while Vue only supports one component per file, hence the name Single File Component (SFC). In such cases, you need to create separate files for each component part and then export them all in an `index.ts` file. + +See the [`Accordion`](https://github.com/radix-vue/shadcn-vue/tree/v0.10.2/apps/www/src/lib/registry/default/ui/accordion) source code as an example. + +## Wrapping Radix-Vue Components + +[Radix-Vue](https://www.radix-vue.com) hosts many low-level UI components that are used to build reusable components. +There are many cases that you need to wrap `Radix-Vue` components. + +### Props & Events +All of the `Radix-Vue` compoennts expose their prop and emit types. We need to forward any props/events that are coming from outside to the `Radix-Vue` component. + +To do so, we have a helper function named [`useForwardPropsEmits`](https://www.radix-vue.com/utilities/use-forward-props-emits.html) that combines props and events that must be binded to the child radix component. + +To be more clear, the function `useForwardPropsEmits` takes in props and an optional emit function, and returns a +computed object that combines the parsed props and emits as props. + +Here's an example from `Accordian` root component. + +```vue + + + +``` + +As you can see, `AccordionRootEmits` and `AccordionRootProps` types are imported from radix, combined with `useForwardPropsEmits` and then are binded using `v-bind` syntaxt. + +### CSS Classes +There are cases when we want to accept `class` as a prop in our `shadcn/vue` component and then combine it with a default tailwind class on our `radix-vue` component via `cn` utility function. + +In these cases, we can not use `v-bind`, because this would lead in [double class binding](https://github.com/radix-vue/shadcn-vue/pull/241). + +Take a look at `DrawerDescription.vue`. + +```vue + + + +``` + +As you can see, we have created a computed property named `delegatedProps` to remove `class` from props, and only then bind +the returned value to our radix component (`DrawerDescription` in this case). + +As for our class, we first declared it as type of `HtmlHTMLAttributes['class']` and used `cn` to merge tailwind classes from `class` prop and our own classes. + +This pattern only needs to be applied when the `cn` utility is required. For instances where there are no default Tailwind classes that need to be merged with user-provided classes, this pattern is not necessary. A good example of this is the `SelectValue.vue` component. + +```vue + + + +``` + +### Boolean Props +When you are building a wrapper for a component, in some cases you want to ignore Vue [Props Boolean Casting](https://vuejs.org/guide/components/props.html#boolean-casting). +You can either set default value as undefined for all the boolean field, or you can use [`useForwardProps`](https://www.radix-vue.com/utilities/use-forward-props.html) composable. + +Take a look at `AccordionItem.vue` + +```vue + + + +``` + +Since `AccordionItemProps` type has atleast one boolean property, we need to use `useForwardProps` on the entire props object. + +Note that `useForwardPropsEmits` use `useForwardProps` under the hood. + +### Component as Root +Whenever your root component is a `Component` Primitive from vue, it's easier to use [`Primitive`](https://www.radix-vue.com/utilities/primitive.html) instead. + +Let's take a look at `Button.vue` + +```vue + + + +``` + +You'll need to extend `PrimitiveProps` in your props to support `Primitive` component. In most cases you would also need a default value for [`as`](https://www.radix-vue.com/utilities/primitive.html#changing-as-value) property. + +## Debugging +Here are some tools and techniques that can help you debug more effectively while contributing to `shadcn/vue` or developing your own projects. + +### Install Vue Dev Tools +To easily inspect component props, attributes, events, and more, you can leverage the [`Vue DevTools`](https://devtools.vuejs.org/) extension for browsers. This extension provides a user-friendly interface for debugging Vue components and can improve your development experience. + +### Enable Custom Formmaters +Vue wraps values stored in a `ref` in a way that, when logged, results in a nested object and requires manual inspection to access the value stored in the ref. + +You can enable Custom Formatters in your browser to automate this process. + +- [Firefox](https://firefox-source-docs.mozilla.org/devtools-user/custom_formatters/index.html) +- Chrome, Edge, Brave and other Chromium based [browsers](https://www.google.com/search?q=how+to+enable+custom++formatter+chrome) diff --git a/apps/www/src/lib/registry/default/ui/button/Button.vue b/apps/www/src/lib/registry/default/ui/button/Button.vue index a7641026..5cfd668a 100644 --- a/apps/www/src/lib/registry/default/ui/button/Button.vue +++ b/apps/www/src/lib/registry/default/ui/button/Button.vue @@ -7,7 +7,6 @@ import { cn } from '@/lib/utils' interface Props extends PrimitiveProps { variant?: ButtonVariants['variant'] size?: ButtonVariants['size'] - as?: string class?: HTMLAttributes['class'] } diff --git a/apps/www/src/lib/registry/new-york/ui/button/Button.vue b/apps/www/src/lib/registry/new-york/ui/button/Button.vue index a7641026..5cfd668a 100644 --- a/apps/www/src/lib/registry/new-york/ui/button/Button.vue +++ b/apps/www/src/lib/registry/new-york/ui/button/Button.vue @@ -7,7 +7,6 @@ import { cn } from '@/lib/utils' interface Props extends PrimitiveProps { variant?: ButtonVariants['variant'] size?: ButtonVariants['size'] - as?: string class?: HTMLAttributes['class'] } diff --git a/apps/www/src/public/diagrams/structure-dark.svg b/apps/www/src/public/diagrams/structure-dark.svg new file mode 100644 index 00000000..07ef91e0 --- /dev/null +++ b/apps/www/src/public/diagrams/structure-dark.svg @@ -0,0 +1,3 @@ + + +
Shadcn/Vue
Shadcn/Vue
Packages
Packages
Apps/www
Apps/www
Module
Module
CLI
CLI
Registry
Registry
.vitepress
.vitepress
Scripts
Scripts
Src
Src
Content
Content
Examples
Examples
Lib/Registry
Lib/Registry
Default
Default
New York
New York
1
1
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
2
2
\ No newline at end of file diff --git a/apps/www/src/public/diagrams/structure-light.svg b/apps/www/src/public/diagrams/structure-light.svg new file mode 100644 index 00000000..756f5b50 --- /dev/null +++ b/apps/www/src/public/diagrams/structure-light.svg @@ -0,0 +1,3 @@ + + +
Shadcn/Vue
Shadcn/Vue
Packages
Packages
Apps/www
Apps/www
Module
Module
CLI
CLI
Registry
Registry
.vitepress
.vitepress
Scripts
Scripts
Src
Src
Content
Content
Examples
Examples
Lib/Registry
Lib/Registry
Default
Default
New York
New York
1
1
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
2
2
\ No newline at end of file diff --git a/apps/www/src/public/registry/styles/default/breadcrumb.json b/apps/www/src/public/registry/styles/default/breadcrumb.json index b902af70..d9baa9cd 100644 --- a/apps/www/src/public/registry/styles/default/breadcrumb.json +++ b/apps/www/src/public/registry/styles/default/breadcrumb.json @@ -19,7 +19,7 @@ }, { "name": "BreadcrumbLink.vue", - "content": "\n\n\n" + "content": "\n\n\n" }, { "name": "BreadcrumbList.vue", diff --git a/apps/www/src/public/registry/styles/default/button.json b/apps/www/src/public/registry/styles/default/button.json index 4a5fac91..8d960a1d 100644 --- a/apps/www/src/public/registry/styles/default/button.json +++ b/apps/www/src/public/registry/styles/default/button.json @@ -7,7 +7,7 @@ "files": [ { "name": "Button.vue", - "content": "\n\n\n" + "content": "\n\n\n" }, { "name": "index.ts", @@ -15,4 +15,4 @@ } ], "type": "components:ui" -} \ No newline at end of file +} diff --git a/apps/www/src/public/registry/styles/new-york/breadcrumb.json b/apps/www/src/public/registry/styles/new-york/breadcrumb.json index 5529cc9e..094ff22e 100644 --- a/apps/www/src/public/registry/styles/new-york/breadcrumb.json +++ b/apps/www/src/public/registry/styles/new-york/breadcrumb.json @@ -19,7 +19,7 @@ }, { "name": "BreadcrumbLink.vue", - "content": "\n\n\n" + "content": "\n\n\n" }, { "name": "BreadcrumbList.vue", diff --git a/apps/www/src/public/registry/styles/new-york/button.json b/apps/www/src/public/registry/styles/new-york/button.json index 28daef14..09a735fd 100644 --- a/apps/www/src/public/registry/styles/new-york/button.json +++ b/apps/www/src/public/registry/styles/new-york/button.json @@ -7,7 +7,7 @@ "files": [ { "name": "Button.vue", - "content": "\n\n\n" + "content": "\n\n\n" }, { "name": "index.ts", @@ -15,4 +15,4 @@ } ], "type": "components:ui" -} \ No newline at end of file +}