diff --git a/ui/.gitignore b/ui/.gitignore
index 99318284a7..639f011c1d 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -15,6 +15,7 @@
/testem.log
/yarn-error.log
package-lock.json
+/docs/components/*
# ember-try
/.node_modules.ember-try/
diff --git a/ui/app/components/app-footer.hbs b/ui/app/components/app-footer.hbs
index 477807626a..00bbee1848 100644
--- a/ui/app/components/app-footer.hbs
+++ b/ui/app/components/app-footer.hbs
@@ -28,4 +28,16 @@
Documentation
+
+ {{#if this.isDevelopment}}
+
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/app/components/z-docfy-filter.hbs b/ui/app/components/z-docfy-filter.hbs
new file mode 100644
index 0000000000..a1a5b88351
--- /dev/null
+++ b/ui/app/components/z-docfy-filter.hbs
@@ -0,0 +1,19 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+
+
+
+ {{#each this.componentList as |component|}}
+
+ {{component.title}}
+
+ {{/each}}
+
\ No newline at end of file
diff --git a/ui/app/components/z-docfy-filter.js b/ui/app/components/z-docfy-filter.js
new file mode 100644
index 0000000000..ac26690960
--- /dev/null
+++ b/ui/app/components/z-docfy-filter.js
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Component from '@glimmer/component';
+import { action } from '@ember/object';
+import { tracked } from '@glimmer/tracking';
+
+// DEVELOPMENT ONLY COMPONENT used for filtering docfy components
+export default class ZDocfyFilter extends Component {
+ @tracked filterValue;
+
+ @action
+ filterComponents({ target }) {
+ this.filterValue = target.value;
+ }
+
+ get componentList() {
+ return this.filterValue
+ ? this.args.components.filter((c) => c.title.toLowerCase().includes(this.filterValue.toLowerCase()))
+ : this.args.components;
+ }
+}
diff --git a/ui/app/router.js b/ui/app/router.js
index 879f17542c..00fd70ba55 100644
--- a/ui/app/router.js
+++ b/ui/app/router.js
@@ -5,7 +5,7 @@
import EmberRouter from '@ember/routing/router';
import config from 'vault/config/environment';
-
+import { addDocfyRoutes } from '@docfy/ember';
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
@@ -217,4 +217,7 @@ Router.map(function () {
});
this.route('not-found', { path: '/*path' });
});
+ if (config.environment !== 'production') {
+ addDocfyRoutes(this);
+ }
});
diff --git a/ui/app/styles/app.scss b/ui/app/styles/app.scss
index 56a186eb08..0166e062ad 100644
--- a/ui/app/styles/app.scss
+++ b/ui/app/styles/app.scss
@@ -8,11 +8,14 @@
@import 'ember-power-select';
@import '@hashicorp/design-system-components';
@import './core';
+@import './docs';
@mixin font-face($name) {
@font-face {
font-family: $name;
- src: url('/ui/fonts/#{$name}.woff2') format('woff2'), url('/ui/fonts/#{$name}.woff') format('woff');
+ src:
+ url('/ui/fonts/#{$name}.woff2') format('woff2'),
+ url('/ui/fonts/#{$name}.woff') format('woff');
}
}
diff --git a/ui/app/styles/docs.scss b/ui/app/styles/docs.scss
new file mode 100644
index 0000000000..0ccb3aecfc
--- /dev/null
+++ b/ui/app/styles/docs.scss
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+.docs-collapse-toggle {
+ .hds-button {
+ color: var(--token-side-nav-color-foreground-primary);
+ background: var(--token-side-nav-color-surface-primary);
+ border-color: transparent;
+ border-radius: var(--token-side-nav-body-list-item-border-radius);
+ &:hover {
+ background: var(--token-side-nav-color-surface-interactive-hover);
+ border-color: transparent;
+ }
+ }
+}
+
+#docfy-content {
+ font-size: 16px;
+ font-family: var(--token-typography-display-300-font-family);
+ margin-left: 1.5rem;
+ margin-right: 2rem;
+ margin-top: 1.5rem;
+ max-width: 90%;
+
+ h1,
+ h2,
+ h3 {
+ border-bottom: 1px solid $grey-light;
+ padding-bottom: 0.5rem;
+ }
+
+ h1 {
+ margin-bottom: 1.15rem;
+ font-size: var(--token-typography-display-500-font-size);
+ line-height: var(--token-typography-display-500-line-height);
+ }
+
+ h2 {
+ padding-top: 1rem;
+ font-size: var(--token-typography-display-400-font-size);
+ line-height: var(--token-typography-display-400-line-height);
+ }
+
+ ul {
+ list-style: disc;
+ li {
+ margin-top: 1rem;
+ }
+ }
+
+ ul,
+ ol {
+ padding-left: $spacing-16;
+ padding-bottom: $spacing-16;
+ }
+
+ pre,
+ code {
+ background-color: $ui-gray-100;
+ }
+
+ blockquote {
+ margin-left: 1rem;
+ padding: 0.5rem;
+ background: $ui-gray-010;
+ border-radius: 6px;
+ }
+
+ code {
+ font-size: var(--token-typography-body-300-font-size);
+ font-family: var(--token-typography-font-stack-code);
+ }
+
+ pre code {
+ overflow-x: scroll;
+ max-width: 700px;
+ white-space: pre-line;
+ }
+
+ pre,
+ table {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ padding: 1rem;
+ text-align: left;
+ border-radius: 6px;
+ }
+
+ table {
+ border: none;
+ border-collapse: collapse;
+ td {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ code {
+ background: none;
+ }
+ }
+ tr {
+ border-bottom: 1px solid $grey-light;
+ }
+ }
+
+ .docfy-demo {
+ border: 1px solid $grey-lightest;
+ border-radius: 6px;
+ padding: 1rem;
+ overflow: scroll;
+
+ .docfy-demo__example {
+ & pre,
+ code {
+ background: none;
+ margin: 0;
+ padding: 0;
+ }
+ }
+ }
+}
diff --git a/ui/app/templates/docs.hbs b/ui/app/templates/docs.hbs
new file mode 100644
index 0000000000..27b4f56a80
--- /dev/null
+++ b/ui/app/templates/docs.hbs
@@ -0,0 +1,79 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+~}}
+
+
+
+
+ {{#let docs.children as |directories|}}
+ {{#let docs.pages as |pages|}}
+
+ <:header>
+
+ <:logo>
+
+
+ <:actions>
+
+
+
+
+ <:body>
+
+
+
+ Home
+
+
+ How to docfy
+
+
+
+ Components
+
+
+ {{! FILTER + COMPONENT LIST }}
+
+
+
+
+ Contributing docs
+
+ {{! Top level files in docs/ directory }}
+ {{#each pages as |page|}}
+ {{#let (concat "docs." (if page.relativeUrl page.relativeUrl "index")) as |url|}}
+
+ {{page.title}}
+
+ {{/let}}
+ {{/each}}
+
+ {{! Sub directories within docs/ (aside from 'components') }}
+ {{#each directories as |subDirectory|}}
+ {{#if (not-eq subDirectory.name "components")}}
+
+ {{capitalize subDirectory.label}}
+
+
+ {{#each subDirectory.pages as |page|}}
+ {{#let (concat "docs." (if page.relativeUrl page.relativeUrl "index")) as |url|}}
+
+ {{page.title}}
+
+ {{/let}}
+ {{/each}}
+ {{/if}}
+ {{/each}}
+
+
+
+ {{/let}}
+ {{/let}}
+
+
+
+
+ {{outlet}}
+
+
\ No newline at end of file
diff --git a/ui/docs/components.md b/ui/docs/building-components.md
similarity index 51%
rename from ui/docs/components.md
rename to ui/docs/building-components.md
index b38aeafa42..033b0832c0 100644
--- a/ui/docs/components.md
+++ b/ui/docs/building-components.md
@@ -1,8 +1,12 @@
-# Writing and consuming components
+# Building and consuming components
+
+- [Page components for every route](#page-components-for-every-route)
+- [Conditional rendering](#conditional-rendering)
+- [Reusable components](#reusable-components)
Components can range from small, highly reusable "atoms" to large units with lots of business logic specific to one workflow or action. In any scenario, these are things to keep in mind while developing components for the Vault UI.
-Please note that these guidelines are aspirational and you will see instances of antipatterns in the codebase. Many of these should be updated as we move forward. As with any ruleset, sometimes it is appropriate to break the rule.
+Please note that these guidelines are aspirational and you will see instances of anti-patterns in the codebase. Many of these should be updated as we move forward. As with any rule set, sometimes it is appropriate to break the rule.
## Page components for every route
@@ -24,38 +28,13 @@ Generally, we want the burden of deciding whether a component should render to l
## Reusable components
-When developing components, make sure to:
+- Consider yielding something instead of passing a new arg
+- Less is more! Adding lots of rendering logic means the component is likely doing too much
-- Add splattributes to the top level, eg:
-
- ```hbs
-
Stuff!
- ```
-
-- Consider passing splattributes or yielding something instead of passing a new arg
-
- ❌ **Instead of:** passing a new arg that controls a style
-
- ```
-
- ```
-
- ✅ **Prefer:** passing a class or helper that controls a style
-
- ```
-
- ```
-
-- Minimize the number of args that must be passed
-
- ❌ **Instead of:** Passing in separate args that are both required for icon to render
-
- ```
-
- ```
-
- ✅ **Prefer:** One arg that is rendered if present
-
- ```
-
- ```
+| 💡 Tips for reusability | Example |
+| ----------------------------------------------------------------- | -------------------------------------------------------------------------- |
+| ✅ Add splattributes to the top level |
`
Something!
`
|
+| ✅ Pass a class or helper that controls a style |
``
|
+| ❌ Don't pass a new arg that controls a style |
``
|
+| ✅ Minimize args passed, pass one arg that is rendered if present |
``
|
+| ❌ Don't pass separate args required for icon to render |
``
|
diff --git a/ui/docs/how-to-docfy.md b/ui/docs/how-to-docfy.md
new file mode 100644
index 0000000000..644cfed706
--- /dev/null
+++ b/ui/docs/how-to-docfy.md
@@ -0,0 +1,99 @@
+---
+title: How to docfy
+order: 1
+---
+
+# How to docfy
+
+http://localhost:4200/ui/docs (navigate to directly or click the present icon in the bottom right of the app footer).
+
+## `docs/` markdown files
+
+Side nav links correspond to the file + directory structure within the `docs/` directory. These top-level markdown files **can** be edited directly and any updates should be saved and pushed to main. (Component docs are generated by the `yarn docs` command, see below.)
+
+## generating component docs
+
+The `docs/components` directory is where _generated_ markdown files for components live after running `yarn docs`. **Do not edit component markdown files directly**. Instead, update markdown by making changes to the `jsdoc` and then re-running the generate command. The `docs/components/*` files are included in `.gitignore` so they are not pushed to main. `jsdoc-to-markdown` errors log in the console.
+
+```
+yarn docfy-md
+```
+
+> _Note: the above command takes three args, if passing the full filepath for a component then the second arg is unnecessary_
+
+| Command | Description |
+| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
+| `yarn docs` | generate markdown file for every\* component in the `addon/core` directory |
+| `yarn docfy-md some-component-name` | generate markdown file for specific component |
+| `yarn docfy-md read-more core` | generate markdown for `read-more` component in the `core` addon |
+| `yarn docfy-md pki-test null ./lib/pki/addon/components/pki-key-usage.ts` | optional third arg is the full component filepath (first arg will become markdown file name) |
+| `rm -f ./docs/components/*` | cleanup and delete generated component markdown files |
+
+> _\*replication and `shamir/*` components are skipped as these are not reused and should eventually be moved outside the `addon/core` directory_
+
+## Writing documentation for a component
+
+Component docs are generated by the script `yarn docs`. Accurate `jsdoc` syntax is important so `jsdoc-to-markdown` properly generates the markdown file for that component. **Do not edit component markdown files directly**.
+
+| jsdoc examples | | |
+| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
+| form-field (`@description` example) | [github ](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/form-field.js) | [vscode ](../lib/core/addon/components/form-field.js) |
+| confirmation-modal | [github ](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/confirmation-modal.js) | [vscode ](../lib/core/addon/components/confirmation-modal.js) |
+| certificate-card | [github ](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/certificate-card.js) | [vscode ](../lib/core/addon/components/certificate-card.js) |
+| alert-inline (`@deprecated` example) | [github](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/alert-inline.js) | [vscode ](../lib/core/addon/components/alert-inline.js) |
+| secret-list-header (code snippet only\*) | [github](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/secret-list-header.js) | [vscode ](../lib/core/addon/components/secret-list-header.js) |
+
+> _\*renders a template code snippet and not instantiated component because it relies on too many args that cannot be set up for component instance_
+
+### Syntax tips
+
+Docfy renders an actual instance of the component beneath `@example` as a sample. Make sure the component uses proper hbs syntax and all args are on a single line.
+
+> - Check the generated markdown file for syntax errors or typos. To update the markdown, first edit the jsdoc then re-run the generator. _Do not edit component markdown files directly_
+> - Param types: `object`, `string`, `function`, `array`
+> - Do not include `null` for empty default values
+> - Wrap optional params in brackets `[]`
+> - To include a codeblock in your module's description use `@description`
+
+```
+❌ multi-line jsdoc will not render a component example
+* @example
+*
+```
+
+```
+✅ this will render
+* @example
+*
+```
+
+**Template**
+
+```
+/**
+ * @module ComponentName
+ * @description
+ * Description of the component
+ *
+ * @example
+ *
+ *
+ * @param {object} paramName - description
+ * @param {array} requiredParam=foo - foo is the default value here
+ * @param {function} [optionalParamName] - An optional parameter is wrapped in brackets
+ * @param {string} [param="some default value"] - An optional parameter with a default value
+ */
+```
+
+> ### Config
+>
+> - [docfy-md.js](../scripts/docfy-md.js): script that generates component markdown and passes options to `jsdoc2md` command
+> - [generate-docs.sh](../scripts/docfy-md.js): batch command that iterates over desired javascript and typescript file in the `core` addon engine
+> - [jsdoc2md.json](../jsdoc2md.json): `jsdoc-to-markdown` config file, necessary so typescript files can be passed to `docfy-md` script
+
+### More info
+
+- [Building and consuming components](./building-components.md)
diff --git a/ui/docs/index.md b/ui/docs/index.md
new file mode 100644
index 0000000000..44bc4ac433
--- /dev/null
+++ b/ui/docs/index.md
@@ -0,0 +1,21 @@
+---
+title: Index
+---
+
+# Welcome to our docs!
+
+These views are generated by files in the `docs/` directory.
+
+
+
+- [How to docfy](./how-to-docfy.md)
+- [Client pagination](./client-pagination.md)
+- [Building and consuming components](./building-components.md)
+- [CSS styling](./css.md)
+- [Ember Engines](./ember-engines.md)
+- [Fetch secrets engine config decorator](./fetch-secrets-engine-config.md)
+- [Forms](./forms.md)
+- [Model validations](./model-validations.md)
+- [Models](./models.md)
+- [Routing](./routing.md)
+- [Serializers and Adapters](./serializers-adapters.md)
diff --git a/ui/jsdoc2md.json b/ui/jsdoc2md.json
new file mode 100644
index 0000000000..2254967c08
--- /dev/null
+++ b/ui/jsdoc2md.json
@@ -0,0 +1,18 @@
+{
+ "source": {
+ "includePattern": ".+\\.(js|ts)(doc|x)?$",
+ "excludePattern": ".+\\.(test|spec).(js|ts)"
+ },
+ "plugins": ["plugins/markdown", "node_modules/jsdoc-babel"],
+ "babel": {
+ "extensions": ["ts", "tsx", "js"],
+ "ignore": ["**/*.(test|spec).ts"],
+ "babelrc": false,
+ "presets": [["@babel/preset-env", { "targets": { "node": true } }], "@babel/preset-typescript"],
+ "plugins": [
+ "@babel/proposal-class-properties",
+ "@babel/proposal-object-rest-spread",
+ ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }]
+ ]
+ }
+}
diff --git a/ui/lib/core/addon/components/alert-inline.js b/ui/lib/core/addon/components/alert-inline.js
index 8a25a6fc28..6ca7bb1204 100644
--- a/ui/lib/core/addon/components/alert-inline.js
+++ b/ui/lib/core/addon/components/alert-inline.js
@@ -10,18 +10,22 @@ import { tracked } from '@glimmer/tracking';
import { assert } from '@ember/debug';
/**
+ * @deprecated
* @module AlertInline
- * * Use Hds::Alert @type="compact" for displaying alert messages.
* This component renders a compact Hds::Alert that displays a loading icon if the
- * @message arg changes and then re-renders the updated @message text.
+ * `@message` arg changes and then re-renders the updated `@message` text.
* (Example: submitting a form and displaying the number of errors because on re-submit the number may change)
*
* @example
- * ```
*
- * ```
*
- * @deprecated {string} type - color getter maps type to the Hds::Alert @color
+ * * use Hds::Alert @type="compact" for displaying alert messages instead
+ *
+ * Error
+ * Something is not right
+ *
+ *
+ * @param {string} type - color getter maps type to the Hds::Alert @color
* @param {string} color - Styles alert color and icon, can be one of: critical, warning, success, highlight, neutral
* @param {string} message - The message to display within the alert.
*/
diff --git a/ui/lib/core/addon/components/autocomplete-input.js b/ui/lib/core/addon/components/autocomplete-input.js
index 3171894d84..394fbc7aa0 100644
--- a/ui/lib/core/addon/components/autocomplete-input.js
+++ b/ui/lib/core/addon/components/autocomplete-input.js
@@ -11,20 +11,18 @@ import { action } from '@ember/object';
* AutocompleteInput components are used as standard string inputs or optionally select options to append to input value
*
* @example
- * ```js
- *
- * ```
- * @callback inputChangeCallback
+ *
+ *
* @param {string} value - input value
- * @param {inputChangeCallback} onChange - fires when input value changes to mutate value param by caller
+ * @param {function} onChange - fires when input value changes to mutate value param by caller
* @param {string} [optionsTrigger] - display options dropdown when trigger character is input
- * @param {Object[]} [options] - array of { label, value } objects where label is displayed in options dropdown and value is appended to input value
+ * @param {array} [options] - array of `{ label, value }` objects where label is displayed in options dropdown and value is appended to input value
* @param {string} [label] - label to display above input
* @param {string} [subText] - text to display below label
* @param {string} [placeholder] - input placeholder
*/
-export default class AutocompleteInput extends Component {
+export default class AutocompleteInputComponent extends Component {
dropdownAPI;
inputElement;
diff --git a/ui/lib/core/addon/components/certificate-card.js b/ui/lib/core/addon/components/certificate-card.js
index f7dd8ff4bd..994b593906 100644
--- a/ui/lib/core/addon/components/certificate-card.js
+++ b/ui/lib/core/addon/components/certificate-card.js
@@ -8,14 +8,13 @@ import Component from '@glimmer/component';
/**
* @module CertificateCard
* The CertificateCard component receives data and optionally receives a boolean declaring if that data is meant to be in PEM
- * Format. It renders using the . To the left there is a certificate icon. In the center there is a label
+ * Format. It renders using the Hds::Card::Container. To the left there is a certificate icon. In the center there is a label
* which says which format (PEM or DER) the data is in. Below the label is the truncated data. To the right there is a copy
* button to copy the data.
*
* @example
- * ```js
- *
- * ```
+ *
+ *
* @param {string} data - the data to be displayed in the component (usually in PEM or DER format)
* @param {boolean} [isPem] - optional argument for if the data is required to be in PEM format (and should thus have the PEM Format label)
*/
diff --git a/ui/lib/core/addon/components/checkbox-grid.ts b/ui/lib/core/addon/components/checkbox-grid.ts
index 3083cb425a..8f25a6959c 100644
--- a/ui/lib/core/addon/components/checkbox-grid.ts
+++ b/ui/lib/core/addon/components/checkbox-grid.ts
@@ -22,18 +22,12 @@ interface Field {
/**
* @module CheckboxGrid
- * CheckboxGrid components are used to allow users to select any
- * number of predetermined options, aligned in a 3-column grid.
+ * @description
+ * CheckboxGrid components are used to allow users to select any number of predetermined options, aligned in a 3-column grid.
+ *
*
* @example
- * ```js
- *
- * ```
+ *
*/
export default class CheckboxGrid extends Component {
diff --git a/ui/lib/core/addon/components/chevron.js b/ui/lib/core/addon/components/chevron.js
index 2cfa6d996c..17c20db82b 100644
--- a/ui/lib/core/addon/components/chevron.js
+++ b/ui/lib/core/addon/components/chevron.js
@@ -1,25 +1,24 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
import Component from '@glimmer/component';
import { assert } from '@ember/debug';
const DIRECTIONS = ['right', 'left', 'up', 'down'];
/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: BUSL-1.1
- */
-
-/**
+ * @deprecated
* @module Chevron
- * `Chevron` components render `Icon` with one of the `chevron-` glyphs.
+ * * Use HDS icons instead
+ * Chevron components render Icon with one of the "chevron-" glyphs.
*
* @example
- * ```js
*
- * ```
*
- * @param [direction="right"] {String} - the direction the chevron icon points. Accepted values are
- * "right", "down", "left", "up".
- * @param [isButton=false] {String} - if true, adjusts the CSS classes to push the icon closer to the right of a button.
+ * @param {string} [direction="right"] - the direction the chevron icon points. Accepted values are "right", "down", "left", "up".
+ * @param {string} [isButton=false] - if true, adjusts the CSS classes to push the icon closer to the right of a button.
*
*/
diff --git a/ui/lib/core/addon/components/choose-pgp-key-form.js b/ui/lib/core/addon/components/choose-pgp-key-form.js
index 982a070b81..7b1a3e0415 100644
--- a/ui/lib/core/addon/components/choose-pgp-key-form.js
+++ b/ui/lib/core/addon/components/choose-pgp-key-form.js
@@ -15,9 +15,8 @@ const pgpKeyFileDefault = () => ({ value: '' });
* an interface for the user to upload or paste a PGP key for use
*
* @example
- * ```js
- *
- * ```
+ *
+ *
* @param {function} onCancel - required - This function will be triggered when the modal intends to be closed
* @param {function} onSubmit - required - When the PGP key is confirmed, it will call this method with the pgpKey value as the only param
* @param {string} buttonText - Button text for onSubmit. Defaults to "Continue with key"
diff --git a/ui/lib/core/addon/components/confirm-action.js b/ui/lib/core/addon/components/confirm-action.js
index 2f19552d40..fdfcb5d126 100644
--- a/ui/lib/core/addon/components/confirm-action.js
+++ b/ui/lib/core/addon/components/confirm-action.js
@@ -12,39 +12,21 @@ import { tracked } from '@glimmer/tracking';
* @module ConfirmAction
* ConfirmAction is a button that opens a modal containing a confirmation message with confirm or cancel action.
* Splattributes are spread to the button element to apply styling directly without adding extra args.
- *
+ *
*
* @example
-// in dropdown
-
-
- // in toolbar
-
- * ```
+ *
+ *
*
* @param {Function} onConfirmAction - The action to take upon confirming.
- * @param {String} [confirmTitle=Are you sure?] - The title to display in the confirmation modal.
- * @param {String} [confirmMessage=You will not be able to recover it later.] - The message to display when confirming.
+ * @param {String} [confirmTitle="Are you sure?"] - The title to display in the confirmation modal.
+ * @param {String} [confirmMessage="You will not be able to recover it later."] - The message to display when confirming.
* @param {Boolean} isInDropdown - If true styles for dropdowns, button color is 'critical', and renders inside `
` elements via ` component to present a critical (red) type-to-confirm modal
+ * ConfirmationModal components wrap the Hds::Modal component to present a critical (red) type-to-confirm modal
* which require the user to type something to confirm the action.
* They are used for extremely destructive actions that require extra consideration before confirming.
*
* @example
- * ```js
- *
- * ```
+ * button is not part of component and is just to help demo functionality
+ *
+ *
+ *
* @param {function} onConfirm - onConfirm is the action that happens when user clicks onConfirm after filling in the confirmation block
* @param {function} onClose - specify what to do when user attempts to close modal
* @param {boolean} isActive - Controls whether the modal is "active" eg. visible or not.
* @param {string} title - Title of the modal
* @param {string} [confirmText=Yes] - The confirmation text that the user must type before continuing
- * @param {string} [toConfirmMsg] - Finishes the sentence "Type to confirm ", default is an empty string (ex. 'secret deletion')
+ * @param {string} [toConfirmMsg] - Finishes the sentence "Type `` to confirm ``", default is an empty string (ex. 'secret deletion')
* @param {string} [buttonText=Confirm] - Button text on the confirm button
*/
diff --git a/ui/lib/core/addon/components/doc-link.js b/ui/lib/core/addon/components/doc-link.js
index b0ea6ddf62..e28dbd03f5 100644
--- a/ui/lib/core/addon/components/doc-link.js
+++ b/ui/lib/core/addon/components/doc-link.js
@@ -6,15 +6,17 @@
import ExternalLink from './external-link';
/**
+ * @deprecated
* @module DocLink
- * `DocLink` components are used to render anchor links to relevant Vault documentation at developer.hashicorp.com.
+ * DocLink components are used to render anchor links to relevant Vault documentation at developer.hashicorp.com.
*
* @example
- * ```js
- Learn about KV v2
- * ```
+ * Learn about KV v2
*
- * @param {string} path="/" - The path to documentation on developer.hashicorp.com that the component should link to.
+ * * Use HDS link components instead with "doc-link" helper for path prefix
+ *
+ *
+ * @param {string} path=/ - The path to documentation on developer.hashicorp.com that the component should link to.
*
*/
export default class DocLinkComponent extends ExternalLink {
diff --git a/ui/lib/core/addon/components/download-button.js b/ui/lib/core/addon/components/download-button.js
index feb8ad7593..5d248b7545 100644
--- a/ui/lib/core/addon/components/download-button.js
+++ b/ui/lib/core/addon/components/download-button.js
@@ -12,32 +12,23 @@ import { tracked } from '@glimmer/tracking';
import { assert } from '@ember/debug';
/**
* @module DownloadButton
- * DownloadButton wraps an to perform a download action.
- * * NOTE: when using in an engine, remember to add the 'download' service to its dependencies (in /engine.js) and map to it in /app.js
- * [ember-docs](https://ember-engines.com/docs/services)
+ * DownloadButton wraps an Hds::Button to perform a download action. [Docs for HDS args](https://helios.hashicorp.design/components/button?tab=code)
+ * * **NOTE**: when using in an engine, remember to add the 'download' service to its dependencies (in /engine.js) and map to it in /app.js
+ * [Ember Engines Services](https://ember-engines.com/docs/services)
+ *
* @example
- * ```js
- *
- * ```
+ *
+ *
* @param {string} [filename] - name of file that prefixes the ISO timestamp generated at download
* @param {string} [data] - data to download
* @param {function} [fetchData] - function that fetches data and returns download content
- * @param {string} [extension='txt'] - file extension, the download service uses this to determine the mimetype
+ * @param {string} [extension=txt] - file extension, the download service uses this to determine the mimetype
* @param {boolean} [stringify=false] - argument to stringify the data before passing to the File constructor
* @param {callback} [onSuccess] - callback from parent to invoke if download is successful
* @param {boolean} [hideIcon=false] - renders the 'download' icon by default, pass true to hide (ex: when download button appears in a dropdown)
- * * HDS ARGS https://helios.hashicorp.design/components/button?tab=code
- * @param {string} [text="Download"] - button text, defaults to 'Download'
+ * @param {string} [text=Download] - button text, defaults to 'Download'
* @param {string} [color] - HDS default is primary, but there are four color options: primary, secondary, tertiary, and critical.
- * @param {string} [iconPosition="leading"] - icon position, 'leading' (HDS default) or 'trailing'
+ * @param {string} [iconPosition=leading] - icon position, 'leading' (HDS default) or 'trailing'
* @param {boolean} [isIconOnly] - button only renders an icon, no text
*/
diff --git a/ui/lib/core/addon/components/external-link.js b/ui/lib/core/addon/components/external-link.js
index 2eacb912b1..a95a73001e 100644
--- a/ui/lib/core/addon/components/external-link.js
+++ b/ui/lib/core/addon/components/external-link.js
@@ -6,16 +6,17 @@
import Component from '@glimmer/component';
/**
- * @module ExternalLinkComponent
- * `ExternalLink` components are used to render anchor links to non-cluster links. Automatically opens in a new tab with noopener noreferrer.
- * To link to developer.hashicorp.com, use DocLink .
+ * @deprecated
+ * @module ExternalLink
+ * ExternalLink components are used to render anchor links to non-cluster links. Automatically opens in a new tab with noopener noreferrer.
*
* @example
- * ```js
- Arbitrary Link
- * ```
+ * Arbitrary Link
*
- * @param {string} href="https://example.com/" - The full href with protocol
+ * * Use HDS links with @isHrefExternal={{true}} instead
+ * My link
+ *
+ * @param {string} href - The full href with protocol
* @param {boolean} [sameTab=false] - by default, these links open in new tab. To override, pass @sameTab={{true}}
*
*/
diff --git a/ui/lib/core/addon/components/form-field-groups-loop.js b/ui/lib/core/addon/components/form-field-groups-loop.js
index e5cc05f9c3..30eb09482f 100644
--- a/ui/lib/core/addon/components/form-field-groups-loop.js
+++ b/ui/lib/core/addon/components/form-field-groups-loop.js
@@ -10,16 +10,15 @@ import Component from '@glimmer/component';
* FormFieldGroupsLoop components loop through the "groups" set on a model and display them either as default or behind toggle components.
*
* @example
- * ```js
-
- * ```
+ *
+ *
* @param {class} model - The routes model class.
* @param {string} mode - "create" or "update" used to hide the name form field. TODO: not ideal, would prefer to disable it to follow new design patterns.
* @param {function} [modelValidations] - Passed through to formField.
* @param {boolean} [showHelpText] - Passed through to formField.
- * @param {string} [groupName="fieldGroups"] - option to override key on the model where groups are located
+ * @param {string} [groupName=fieldGroups] - option to override key on the model where groups are located
*/
-export default class FormFieldGroupsLoop extends Component {
+export default class FormFieldGroupsLoopComponent extends Component {
get fieldGroups() {
return this.args.groupName || 'fieldGroups';
}
diff --git a/ui/lib/core/addon/components/form-field-groups.js b/ui/lib/core/addon/components/form-field-groups.js
index d2cfe363f3..9a33341095 100644
--- a/ui/lib/core/addon/components/form-field-groups.js
+++ b/ui/lib/core/addon/components/form-field-groups.js
@@ -9,32 +9,17 @@ import { action } from '@ember/object';
/**
* @module FormFieldGroups
- * `FormFieldGroups` components are field groups associated with a particular model. They render individual `FormField` components.
+ * FormFieldGroups components are field groups associated with a particular model. They render individual FormField components.
*
* @example
- * ```js
- * {{if model.fieldGroups}}
- *
- * {{/if}}
+ *
*
- * ...
- *
- *
- * ```
- * @callback onChangeCallback
- * @callback onKeyUpCallback
* @param {Model} model- Model to be passed down to form-field component. If `fieldGroups` is present on the model then it will be iterated over and groups of `FormField` components will be rendered.
* @param {string} [renderGroup] - An allow list of groups to include in the render.
- * @param {onChangeCallback} [onChange] - Handler that will get set on the `FormField` component.
- * @param {onKeyUpCallback} [onKeyUp] - Handler that will set the value and trigger validation on input changes
- * @param {ModelValidations} [modelValidations] - Object containing validation message for each property
- * @param {string} [groupName='fieldGroups'] - attribute name where the field groups are
+ * @param {function} [onChange] - Handler that will get set on the `FormField` component.
+ * @param {function} [onKeyUp] - Handler that will set the value and trigger validation on input changes
+ * @param {object} [modelValidations] - Object containing validation message for each property
+ * @param {string} [groupName=fieldGroups] - attribute name where the field groups are
*/
export default class FormFieldGroupsComponent extends Component {
diff --git a/ui/lib/core/addon/components/form-field.js b/ui/lib/core/addon/components/form-field.js
index b9e61ef02b..a15d735f8a 100644
--- a/ui/lib/core/addon/components/form-field.js
+++ b/ui/lib/core/addon/components/form-field.js
@@ -15,38 +15,39 @@ import { removeFromArray } from 'vault/helpers/remove-from-array';
/**
* @module FormField
- * `FormField` components are field elements associated with a particular model.
+ * FormField components are field elements associated with a particular model.
+ * @description
+ * ```
+ * sample attr shape:
+ * attr = {
+ * name: "foo", // name of attribute -- used to populate various fields and pull value from model
+ * type: "boolean" // type of attribute value -- string, boolean, etc.
+ * options: {
+ * label: "To do task", // custom label to be shown, otherwise attr.name will be displayed
+ * defaultValue: "", // default value to display if model value is not present
+ * fieldValue: "toDo", // used for value lookup on model over attr.name
+ * editType: "boolean", type of field to use. List of editTypes:boolean, file, json, kv, optionalText, mountAccessor, password, radio, regex, searchSelect, stringArray, textarea, ttl, yield.
+ * helpText: "This will be in a tooltip",
+ * readOnly: true
+ * },
+ * }
+ * ```
*
* @example
- * ```js
* {{#each @model.fields as |attr|}}
- *
+ *
* {{/each}}
- * ```
- * example attr object:
- * attr = {
- * name: "foo", // name of attribute -- used to populate various fields and pull value from model
- * options: {
- * label: "Foo", // custom label to be shown, otherwise attr.name will be displayed
- * defaultValue: "", // default value to display if model value is not present
- * fieldValue: "bar", // used for value lookup on model over attr.name
- * editType: "ttl", type of field to use. List of editTypes:boolean, file, json, kv, optionalText, mountAccessor, password, radio, regex, searchSelect, stringArray, textarea, ttl, yield.
- * helpText: "This will be in a tooltip",
- * readOnly: true
- * },
- * type: "boolean" // type of attribute value -- string, boolean, etc.
- * }
+ *
+ *
* @param {Object} attr - usually derived from ember model `attributes` lookup, and all members of `attr.options` are optional
* @param {Model} model - Ember Data model that `attr` is defined on
* @param {boolean} [disabled=false] - whether the field is disabled
* @param {boolean} [showHelpText=true] - whether to show the tooltip with help text from OpenAPI
* @param {string} [subText] - text to be displayed below the label
* @param {string} [mode] - used when editType is 'kv'
- * @param {ModelValidations} [modelValidations] - Object of errors. If attr.name is in object and has error message display in AlertInline.
- * @callback onChangeCallback
- * @param {onChangeCallback} [onChange] - called whenever a value on the model changes via the component
- * @callback onKeyUpCallback
- * @param {onKeyUpCallback} [onKeyUp] - function passed through into MaskedInput to handle validation. It is also handled for certain form-field types here in the action handleKeyUp.
+ * @param {object} [modelValidations] - Object of errors. If attr.name is in object and has error message display in AlertInline.
+ * @param {function} [onChange] - called whenever a value on the model changes via the component
+ * @param {function} [onKeyUp] - function passed through into MaskedInput to handle validation. It is also handled for certain form-field types here in the action handleKeyUp.
*
*/
diff --git a/ui/lib/core/addon/components/form-save-buttons.js b/ui/lib/core/addon/components/form-save-buttons.js
index a5029c1f6d..10a1b3e061 100644
--- a/ui/lib/core/addon/components/form-save-buttons.js
+++ b/ui/lib/core/addon/components/form-save-buttons.js
@@ -11,19 +11,16 @@ import Component from '@glimmer/component';
* To show an overall inline error message, use the :error yielded block like shown below.
*
* @example
- * ```js
- *
+ *
* <:error>This is an error
*
- * ```
*
- * @param [saveButtonText="Save" {String}] - The text that will be rendered on the Save button.
- * @param [cancelButtonText="Cancel" {String}] - The text that will be rendered on the Cancel button.
- * @param [isSaving=false {Boolean}] - If the form is saving, this should be true. This will disable the save button and render a spinner on it;
- * @param [cancelLinkParams=[] {Array}] - An array of arguments used to construct a link to navigate back to when the Cancel button is clicked.
- * @param [onCancel=null {Function}] - If the form should call an action on cancel instead of route somewhere, the function can be passed using onCancel instead of passing an array to cancelLinkParams.
- * @param [includeBox=true {Boolean}] - By default we include padding around the form with underlines. Passing this value as false will remove that padding.
+ * @param {string} [saveButtonText=Save] - The text that will be rendered on the Save button.
+ * @param {string} [cancelButtonText=Cancel] - The text that will be rendered on the Cancel button.
+ * @param {boolean} [isSaving=false] - If the form is saving, this should be true. This will disable the save button and render a spinner on it;
+ * @param {array} [cancelLinkParams] - An array of arguments used to construct a link to navigate back to when the Cancel button is clicked.
+ * @param {function} [onCancel=null] - If the form should call an action on cancel instead of route somewhere, the function can be passed using onCancel instead of passing an array to cancelLinkParams.
+ * @param {boolean} [includeBox=true] - By default we include padding around the form with underlines. Passing this value as false will remove that padding.
*
*/
diff --git a/ui/lib/core/addon/components/icon.js b/ui/lib/core/addon/components/icon.js
index 3b86a40e75..f8c90cef47 100644
--- a/ui/lib/core/addon/components/icon.js
+++ b/ui/lib/core/addon/components/icon.js
@@ -16,15 +16,14 @@ const flightIconNames = flightIconMap.assets.map((asset) => asset.iconName).uniq
* Flight icon library at https://helios.hashicorp.design/icons/library
*
* @example
- * ```js
- *
- * ```
+ *
+ *
* @param {string} name - The name of the SVG to render inline. Required.
* @param {string} [size=16] - size for flight icon, can be 16 or 24
*
*/
-export default class Icon extends Component {
+export default class IconComponent extends Component {
constructor(owner, args) {
super(owner, args);
assert('Icon component size argument must be either "16" or "24"', ['16', '24'].includes(this.size));
diff --git a/ui/lib/core/addon/components/info-table-item-array.js b/ui/lib/core/addon/components/info-table-item-array.js
index b79afe102a..8957f67eed 100644
--- a/ui/lib/core/addon/components/info-table-item-array.js
+++ b/ui/lib/core/addon/components/info-table-item-array.js
@@ -17,23 +17,13 @@ import { action } from '@ember/object';
* return a wildcard count similar to what is done in the searchSelect component.
*
* @example
- * ```js
- *
*
- * @param {string} label - used to render lowercased display text for "View all