vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.65k stars 33.67k forks source link

Establish a standard way to document component and its props #7186

Open octref opened 6 years ago

octref commented 6 years ago

What problem does this feature solve?

https://github.com/vuejs/vetur/issues/276

Currently, Vetur offers auto-completion & hover info for custom components defined in ElementUI, OnsenUI and Bootstrap-Vue. However, hand-maintaining such json files seem to be a lot of work. Also not co-locating the doc and the component definition can make updating component challenging.

Helper-json repos at:

This feature makes it possible to write the doc in the SFC / js component file, and auto-generate a helper json that can be used for enhancing editing experience or auto-generating API / doc website.

What does the proposed API look like?

Two more optional attributes on the default export:

export default {
  name: 'v-card',
  description: 'A card component',
  props: ['width', 'height'],
  propsDescription: [
    'width of the rendered card component',
    'height of the rendered card component'
  ]
}

I was thinking maybe using a custom block for it, but then that only applies to SFC, not js components. jsdoc might be another option. Other ideas welcome.

Another idea is similar to the typings in package.json, have a vueTypings for component libraries. It'll point to the generated helper-json file and editors could pick it up to enhance editing experience.

/cc

@Leopoldthecoder for ElementUI @masahirotanaka for OnsenUI @pi0 for Bootstrap-Vue @rstoenescu for Quasar @johnleider for Vuetify

Would you be interested in using this feature in the Vue component libraries that you are maintaining? Would you be interested in helping spec'ing a format for the generated json file and the editing experiences that should be enabled by using that file?

mesqueeb commented 4 years ago

@elevatebart thanks so much !! This is what I was looking for. There are so many links to competing projects here, that all looked very complex! But I must have missed this one. ;)

rchl commented 4 years ago

I'm in favor of web-types and I've created a feature request in Vetur to consider it (https://github.com/vuejs/vetur/issues/2090).

Some comments about the competing JSDoc-based solution: a) the JSDoc comments would have to be stripped on publishing the component as otherwise, the comments would add to component size. So how would a language server (like Vetur) then read that information when all of that would be stripped? b) if the idea is to parse the JSDoc and include parsed form of it separately on releasing, then those could be as well just transformed into web-types right? Why invent another format?

I'm not sure I fully understand the idea of JSDoc-based solution so excuse me if I completely missed the point.

elevatebart commented 4 years ago

@rchl good feedback.

You did not miss the point at all.

Questions

Keep in mind we are talking about 2 very different subjects here that are often confused.

  1. How documentation is written? In extenso, how the author of a component writes the docs for his component. Options mentioned above are:

    • JSDoc
    • A separate JSON file
    • a generated TOML object in an additional block
    • additional members added to props like suggested above
  2. How this documentation is consumed? id-est, what files are necessary for Vetur and WebStorm or any editor to understand the library the user has imported in his project. Options mentioned above are:

    • WebTypes
    • Vetur typings

Architecture

One file format does not have to take care of both. One does not have to read the components themselves directly. When we publish a library we could have a build step generating any format we want.

Choices - Authoring

On the choice of formats to author documentation, there are a couple of consideration that will orient your choice:

export default {
  props: {
    color:{
      type: String,
      required: true,
      docs: { 
        description: "use this prop to color your button",
        examples: "`blue`, `grey`",
        deprecated: true
      }
    }
  }
}

Choices - Usage

Choosing web-types as a standard for the Vue LSP: @octref was saying above that web-types were more complete therefore more complex than Vetur types format, making web-types a little slower to parse and to maintain.

@znck and @octref are working on a TypeScript plugin for vue 3 that will leverage the Language Server Protocol.

I am with you on that last point, I can't wait to know more.

piotrtomiak commented 4 years ago

It looks like the JSDoc approach of documenting components is more or less standarized with vue-docgen-api package present (thanks to styleguidist project), so I've just added basic support for generating web-types using it - https://www.npmjs.com/package/vue-docgen-web-types . If there are "api" packages available for other documentation options I'll be glad to add generators for them as well.

Here is a screenshot of documentation popup taking advantage of web-types generated from styleguidist example:

vue-styleguidist-web-types-test
mesqueeb commented 4 years ago

@piotrtomiak are these popups usable in VSCode as well?

piotrtomiak commented 4 years ago

@mesqueeb VSCode does not have support for "web-types.json", it uses a much more simplified format split into two files. As @rchl has mentioned above he has filed a feature request for Vetur to support web-types - vuejs/vetur#2090.

scscgit commented 3 years ago

Also don't forget that we need a way to access the documentation (in IDE/static analysis) even when using dynamic components, e.g.

<component :is="condition ? 'v-textarea' : 'v-text-field'" any-documented-prop />

which is currently very cumbersome to use (plus it's difficult to apply any form of defensive programming to ensure that we only use existing props). As an alternative we could implement our own wrapper that exposes the same props, but there's also no way to inherit an existing documentation, making integration with third party libraries very painful (and not forward compatible, lacking warnings).

elevatebart commented 3 years ago

@scscgit this is a valid point, dynamic component resolution should be working.

Are you still talking about adding documentation to the available props/events/slots? -> I do not see a proper way to display it in VSCode or WebStorm without being extremely confusing. TS tried to merge all the definitions and the errors you get are confusing, to say the least.

If you are talking about the validation of prop types in the IDE this is another story.

I believe that most of the time what you want to achieve here should be accomplished with a v-if unless you do not know the component you are going to get. I would let aside the dynamic analysis for runtime and focus, for the live documentation, on static components.

What do you think? Any good ideas on how to display all the possible props of all the possible components?

znck commented 3 years ago

For dynamic components, TS/VueDX would show intersection of props. It's not a good idea to use dynamic components with very different props, either use if/else or a render function.

scscgit commented 3 years ago

Yeah, the set of all possible (dynamic) components may not be known beforehand, but it'd be great if we could cover at least the scenarios when they are constants (and the best case would include inference of actual prop values if they utilize the same conditions as in :is) - and in the worst case, there's always an opportunity to introduce workarounds like some special comment above the <component> tag, in which we'd specify everything we expect (maybe with metadata to for example include/exclude props as required), describing the intention that also validates further refactoring.

As the if/else causes a huge duplication of code, especially when using children (and there's sadly no such thing as conditional props), the render function does indeed seem like the best alternative; it's just that it may obviously over-complicate the component (and sadly can't be done "inline" within an existing template). Well, it'd be way easier for us if we could use v-if on parents that share the same child.

I don't know the details of integration between VueDX and tools like Vetur, so if it already supports showing intersection of props, is there any DX-oriented guide for new users about the currently "best" options of setting up the project (possibly including further static/dynamic analysis, considering that Vue silently ignores so many problems even with eslint)? Searching for setup recommendations currently feels very random (including this lack of consensus on documentation, which especially hurts new library authors), and that's even if one starts on Nuxt.js, so maybe some hints could be back-integrated into official articles.

elevatebart commented 3 years ago

@scscgit it would probably be awesome indeed, but very complicated. In short, you would have to deduce the component used from the props passed in order to re-validate the prop types.

I believe @znck VueDX does this already.

I insist though. If you want your code to be readable by noobs and newcomers, you should avoid using <component>. If you already know the components you might want to use and they have exactly the same API, maybe make an intermediary component with a render function that does the mapping. If the 2 are completely different, then you should use a v-if, even if they have one thing (a slot) in common

scscgit commented 3 years ago

@elevatebart I agree that <component> doesn't increase readability for newcomers, but it does remove a code duplication, making the long-term maintenance way easier as you don't have to guess by using eyes to make a diff; and you face the same decision of using v-if even in the intermediary component (and it's difficult to document an intention if some aspects don't live in any single place). In any case, the key requirement here would be to be able to inherit (prop) documentation and types from the (proxied) components.

Still, it feels like overkill if every time you make a small change requiring changing component you risk having to create a new component, re-document all props and duplicate them (using v-if), plus make a new render function to insert the child.

travis5491811 commented 3 years ago

Is vue storybook basically the most developed option for users needing this on a per-project basis? Vue styleguidist looks ok but it doesn't seem like the documentation lives as close to the component as with storybook.

elevatebart commented 3 years ago

@travis5491811 I invite you to try styleguidist if the proximity of the docs is important to you.

The SFC model of styleguidist contains a docs block with all the needed examples.

<template functional>
    <!-- @prop {string} id name attribute of the button -->
    <button :name="props.id" style="background: pink;">
        <!-- @slot name of the button -->
        <slot />
    </button>
</template>

<docs>
Document your functional templates in docs blocks

```vue
<FunctionalButton id="test">
    In the docs block
</FunctionalButton>



[Example](https://github.com/vue-styleguidist/vue-styleguidist/blob/dev/examples/basic/src/components/Functional/FunctionalButton.vue)

[Documentation](https://vue-styleguidist.github.io/docs/Documenting.html#usage-examples-and-readme-files)
travis5491811 commented 3 years ago

Thanks for the link @elevatebart. Proximity is important but id also like the ability to easily test different states of my components or show (through code and interactivity) how they work with different props. I don't see how to do that with styleguidist.

However, assuming the following are my goals when documenting components:

  1. Ability to document component description, name, props, actions and event.
  2. Ability to document my style guide (typography, css classes, etc)
  3. Ability to display examples of my components in isolation for use when building the component and showcasing it to others.
  4. Ability to interact with my component for testing (example i want to see if i put a date range "from date" newer than "to date") (should i just be using my test suite for this kind of stuff)
  5. Have the documentation live as close to the component as possible so it's more likely to be updated when the component changes.
  6. Be as DRY as possible

Are you able to accomplish all those with styleguidist? From the docs and examples i can see you can do 1, 2, 3, 5, and 6. I don't see how you can do the rest. What is your workflow for automated testing?

travis5491811 commented 3 years ago

For anybody interested, there is a interesting video on this topic from Vue Mastery here Component Documentation Made Easy by Bart Ledoux | VueConf US 2020

elevatebart commented 3 years ago

Hey @travis5491811, I love it !! You just made my day. You linked my talk about storybook and styleguidist.

  1. SB & VSG use the same library (vue-docgen-api maintained by yours truly) to extract those descriptions. Even WebTypes generation from the WebStorm intelliJ ecosystem use the same lib.
  2. Check out the vue design system example, it shows how to do this quite simply on top of styleguidist. I took the liberty of updating the shell in the home repo of styleguidist since the main vueds is not maintained anymore by the original author. But @viljamis did an incredible job.
  3. These examples are the heart and soul of styleguidist and are meant to document each component with some proper live and editable use cases. I tried to write a simple documentation but any question would help me make it more useful.
  4. For real testing today my opinion is that you should extract the logic from the rendering of your components. This way, you can use node to test your logic and only have examples of the visual parts of your components that you can check at a glance. Cypress.io can help you at this point test and screenshot the components from your styleguide and compare it with previous screenshots or test properties visually.
  5. Component Workbench 101 and my philosophy forever with both Styleguidist and Storybook
  6. That is hard to achieve and can push you into doing some stuff that are impossible to understand. But overall I agree (and my team at cypress is working on solving it).
travis5491811 commented 3 years ago

Thanks @elevatebart for the feedback and I'm glad that video will reach more people.

I noticed the vue design system examples depend on react (first import)

Is the library mainly geared toward react users? Do teams have to know both react and vue to effectively used the systems or is that only if you need to use vue design system, or maybe it's just that the example is not fully for vue?

I am still trying to get styleguidist working with nuxt so i can play with it more in a real project.

lywufei commented 2 years ago

Hey @travis5491811, I love it !! You just made my day. You linked my talk about storybook and styleguidist.

  1. SB & VSG use the same library (vue-docgen-api maintained by yours truly) to extract those descriptions. Even WebTypes generation from the WebStorm intelliJ ecosystem use the same lib.
  2. Check out the vue design system example, it shows how to do this quite simply on top of styleguidist. I took the liberty of updating the shell in the home repo of styleguidist since the main vueds is not maintained anymore by the original author. But @viljamis did an incredible job.
  3. These examples are the heart and soul of styleguidist and are meant to document each component with some proper live and editable use cases. I tried to write a simple documentation but any question would help me make it more useful.
  4. For real testing today my opinion is that you should extract the logic from the rendering of your components. This way, you can use node to test your logic and only have examples of the visual parts of your components that you can check at a glance. Cypress.io can help you at this point test and screenshot the components from your styleguide and compare it with previous screenshots or test properties visually.
  5. Component Workbench 101 and my philosophy forever with both Styleguidist and Storybook
  6. That is hard to achieve and can push you into doing some stuff that are impossible to understand. But overall I agree (and my team at cypress is working on solving it).

very cool!