Calcite-components: Docs: Enhance auto-generated documentation content

Created on 1 Jun 2021  路  13Comments  路  Source: Esri/calcite-components

Description

To support https://github.com/ArcGIS/afd-calcite-documentation/issues/165, we need to improve / add to the auto-generated documentation per component. These improvements will also help fill out the readme files on GH.

There are some holes in the auto-generated documentation, mostly when the documentation is referencing a typed interface or content from a resource file. Some examples:

I'm sure more items will come up, feel free to add more examples here.

There's a lot of inconsistency around how we write the documentation for props - sometimes we indicate optionally in the definition, other times we just add it to the prop annotation. It will be easier for us to go through and address the voice / tone differences once the auto-generated documentation is visible.

2 - in development docs

All 13 comments

Related issue: #1097

@macandcheese when you have a moment, can you add in the docs-json data you're referring to here for clarity on each bullet point?

Sure, here are some current data shapes from that file. As long as the content is present in the file we can display it consistently in the docs site.

Events without detail example (pagination):

 "events": [
        {
          "event": "calcitePaginationChange",
          "detail": "CalcitePaginationDetail",
          "bubbles": true,
          "cancelable": true,
          "composed": true,
          "docs": "Emitted whenever the selected page changes.",
          "docsTags": []
        },
...
]

Props without default values (TEXT.nextLabel):

 "props": [
...
        {
          "name": "textLabelNext",
          "type": "string",
          "mutable": false,
          "attr": "text-label-next",
          "reflectToAttr": false,
          "docs": "title of the next button",
          "docsTags": [],
          "default": "TEXT.nextLabel",
          "values": [
            {
              "type": "string"
            }
          ],
          "optional": false,
          "required": false
        },

For the tree example - it's just formatted differently than other acceptable values (scale vs selection mode here)

 "props": [
...
        {
          "name": "scale",
          "type": "\"m\" | \"s\"",
          "mutable": true,
          "attr": "scale",
          "reflectToAttr": true,
          "docs": "Specify the scale of the tree, defaults to m",
          "docsTags": [],
          "default": "\"m\"",
          "values": [
            {
              "value": "m",
              "type": "string"
            },
            {
              "value": "s",
              "type": "string"
            }
          ],
          "optional": false,
          "required": false
        },
        {
          "name": "selectionMode",
          "type": "TreeSelectionMode.Ancestors | TreeSelectionMode.Children | TreeSelectionMode.Multi | TreeSelectionMode.MultiChildren | TreeSelectionMode.Single",
          "mutable": true,
          "attr": "selection-mode",
          "reflectToAttr": true,
          "docs": "Customize how tree selection works (single, multi, children, multi-children)",
          "docsTags": [],
          "default": "TreeSelectionMode.Single",
          "values": [
            {
              "type": "TreeSelectionMode.Ancestors"
            },
            {
              "type": "TreeSelectionMode.Children"
            },
            {
              "type": "TreeSelectionMode.Multi"
            },
            {
              "type": "TreeSelectionMode.MultiChildren"
            },
            {
              "type": "TreeSelectionMode.Single"
            }
          ],
...

Self-assigning this one for our upcoming developer docs update.

To-do:

  • [ ] ~replace "private" Custom JSDocs Tag with "internal" to exclude that property from prop tables/docs-json. Ex in calcite-tile.tsx:~ Update: the @private tag seems to be necessary so we can just filter these out in developer docs
  /**
   * The focused state of the tile.
   * @private
   */
  @Prop({ reflect: true }) focused = false;

~(per this comment)~

  • [ ] ~add jsdoc tags for the component's theming CSS variables. Ex in calcite-tile.scss:~
    Update: I'm documenting only the component-specific CSS Custom Properties (like --calcite-notice-width), not the components' usage of the global theming vars.
/**
  * @prop --calcite-ui-border-2: calcite-tile's box-shadow color when embed is false
  * @prop --calcite-ui-brand: calcite-tile's :hover and :active box-shadow color, when embed is false
  */

Will add the following data to docs-json:

      "styles": [
        {
          "name": "--calcite-ui-border-2",
          "annotation": "prop",
          "docs": "calcite-tile's box-shadow color when embed is false"
        },
        {
          "name": "--calcite-ui-brand",
          "annotation": "prop",
          "docs": "calcite-tile's :hover and :active box-shadow color, when embed is false"
        }
      ],

For the event details content, Franco helped clarify that due to this Stencil issue:
https://github.com/ionic-team/stencil/issues/2747

The only way he knows of to get the event detail's content would be inline doc'ing in the .tsx file like this (instead of the interface name):

  @Event() calcitePaginationChange: EventEmitter<{
    start: number;
    total: number;
    num: number;
  }>;

He's opening a support ticket with Stencil to see if there's a workaround. The issue applies to the following events (we can probably just hard-code these for now since there are only 12 unique interfaces):

18 results - 12 files

src/components/calcite-date-picker/calcite-date-picker.tsx:
  140:   @Event() calciteDatePickerChange: EventEmitter<Date>;
  145:   @Event() calciteDatePickerRangeChange: EventEmitter<DateRangeChange>;

src/components/calcite-date-picker-month-header/calcite-date-picker-month-header.tsx:
  86:   @Event() calciteDatePickerSelect: EventEmitter<Date>;

src/components/calcite-dropdown-group/calcite-dropdown-group.tsx:
  58:   @Event() calciteDropdownGroupRegister: EventEmitter<GroupRegistration>;

src/components/calcite-dropdown-item/calcite-dropdown-item.tsx:
  66:   @Event() calciteDropdownItemKeyEvent: EventEmitter<ItemKeyboardEvent>;
  69:   @Event() calciteDropdownItemRegister: EventEmitter<ItemRegistration>;

src/components/calcite-input-date-picker/calcite-input-date-picker.tsx:
  149:   @Event() calciteDatePickerChange: EventEmitter<Date>;
  154:   @Event() calciteDatePickerRangeChange: EventEmitter<DateRangeChange>;

src/components/calcite-label/calcite-label.tsx:
  57:   @Event() calciteLabelFocus: EventEmitter<FocusRequest>;

src/components/calcite-pagination/calcite-pagination.tsx:
  70:   @Event() calcitePaginationUpdate: EventEmitter<CalcitePaginationDetail>;

src/components/calcite-tab-nav/calcite-tab-nav.tsx:
  262:   @Event() calciteTabChange: EventEmitter<TabChangeEventDetail>;

src/components/calcite-tab-title/calcite-tab-title.tsx:
  241:   @Event() calciteTabsActivate: EventEmitter<TabChangeEventDetail>;
  256:   @Event() calciteTabTitleRegister: EventEmitter<TabID>;

src/components/calcite-time-picker/calcite-time-picker.tsx:
  165:   @Event() calciteTimePickerBlur: EventEmitter<Time>;
  170:   @Event() calciteTimePickerChange: EventEmitter<Time>;
  175:   @Event() calciteTimePickerFocus: EventEmitter<Time>;

src/components/calcite-tree/calcite-tree.tsx:
  252:   @Event() calciteTreeSelect: EventEmitter<TreeSelectDetail>;

src/components/calcite-tree-item/calcite-tree-item.tsx:
  341:   @Event() calciteTreeItemSelect: EventEmitter<TreeItemSelectDetail>;

(Additionally, type annotations are ignored when imported from a .ts file - so adding doc there won't help us.)

@macandcheese Couple notes for the "Values" column of the Properties table on docs site:

  • when a component's prop is optional (or when !prop.default), we should show undefined (default) (ie., mimic the way it appears on Storybook)
  • when a component's prop type is an interface name, include a case in the switch to check for typeof "string", and just display it (ie., Date)
  • Due to JSDoc limitations, prop default values are only documented if it's a simple value (a string, a number, a boolean or null). This means AFAIK, we'll have to manually document object values like TEXT.loading. (And JSDoc annotations seem to be ignored when imported from a .ts file anyhow.)

For the Events table, due to the Stencil bug I linked to in previous comment, we'll have to manually document event details that are a named interface as well (if we want to show the object's contents).

Thanks for the updates. This sounds reasonable - although not sure best course on manually adding interface details. Maybe we can infer a url and link to an associates file or worst case, the component in some way on GH?

@macandcheese After more analysis, I found that we can use the @see JSDoc tag with a markdown link that leads to the interface definition on GitHub master branch:

/**
 * Fires when a specific tab is activated.
 * @see [TabChangeEventDetail](https://github.com/Esri/calcite-components/blob/master/src/components/calcite-tab/interfaces.ts#L1)
 */
@Event() calciteTabsActivate: EventEmitter<TabChangeEventDetail>;

Which generates this typing info in components.d.ts:

/**
  * Fires when a specific tab is activated.
  * @see  [TabChangeEventDetail](https://github.com/Esri/calcite-components/blob/master/src/components/calcite-tab/interfaces.ts#L1)
 */
"onCalciteTabsActivate"?: (event: CustomEvent<TabChangeEventDetail>) => void;

and produces this data in docs-json:

"events": [
  {
    "event": "calciteTabsActivate",
    "detail": "TabChangeEventDetail",
    "bubbles": true,
    "cancelable": true,
    "composed": true,
    "docs": "Fires when a specific tab is activated.",
    "docsTags": [
      {
        "text": " [TabChangeEventDetail](https://github.com/Esri/calcite-components/blob/master/src/components/calcite-tab/interfaces.ts#L1)",
        "name": "see"
      }
    ]
  }
],

That said, since we can't use a relative link leading to the interface definition (ie., we'd have to point to a branch in the link) I'm not sure how useful it is. Might be more problem than it's worth.

Tangential note: we should also show a "private" chip or something for props if they have a docsTag with name = "private" .

For the link, we could replace master with the current version of calcite components. That way at least the interface could be viewed. Later we could scrape that link for content and the child item that contained that interface.

For private, should we show it at all on dev docs ?

For the link, we could replace master with the current version of calcite components.

You mean replace the text on docs site right? (Where does the cc version come from?)

For private, should we show it at all on dev docs ?

I'm not sure! Storybook shows them but doesn't delineate them as private right now. (Which is why I thought it could be a nice addition.)

One example is the hovered property on calcite-checkbox: https://esri.github.io/calcite-components/?path=/docs/components-controls-checkbox--simple

        {
          "name": "hovered",
          "type": "boolean",
          "mutable": true,
          "attr": "hovered",
          "reflectToAttr": true,
          "docs": "The hovered state of the checkbox.",
          "docsTags": [
            {
              "name": "private"
            }
          ],
          "default": "false",
          "values": [
            {
              "type": "boolean"
            }
          ],
          "optional": false,
          "required": false
        },

The CSS vars portion of this issue has been installed.

@macandcheese how should I proceed on this one? Yesterday I pushed the test branch I used for analyzing the docs-json, visible here: https://github.com/Esri/calcite-components/compare/caripizza/2241-auto-generated-docs-json-as-markdown

If you run npm run build on this branch, it will a) update component readmes (existing behavior) and b). generate a docs-json.md markdown file that contains normalized docs-json data. (It's using the docs-custom output target in its analysis. I needed a visual to help me understand the differences between how items get doc'ed.)

In order to finish this one (and due to the doc limitations I already mentioned), I see the following action-items. Can you think of others?

  • [ ] filter out private properties from docs-json (docs site, if we want we can show in future)
  • [ ] doc the interface definition links with @see for event details content (cc)
  • [ ] doc props' default values that are variables with their value (cc)

I think those todos are accurate, can you add them to the open issue in the afd repo for auto generating content? Then we can decide what to show and how to display it.

Is there an expected beta release this will land in so we can consume it via npm in that project?

The next beta release will have the CSS props portion (beta.59, I'm guessing release on next Tuesday cc @julio8a).

However considering we just determined scope of the final action items, I need more time to finish the remaining doc to-dos. I need to gather the full list of affected props/events/methods, add the docs, and then test that they're properly updated via the build script. That means I don't think those docs will land until the new pr is approved, merged into master, and the subsequent next version is deployed. (So we can use that next version to test the data, or just wait for the subsequent beta release after, ie., 60).

Yes, we should do a release on Tuesday so that Adam can get started with what did make it out. CC'ing @jcfranco

Let's regroup on what's left after this release and review the possible timeframe for them.

Was this page helpful?
0 / 5 - 0 ratings