From 5c7403e56f40b8fdce6e30127bf08005a0cd7bfb Mon Sep 17 00:00:00 2001
From: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
Date: Mon, 16 Aug 2021 13:55:12 -0500
Subject: [PATCH] UI/StatText Component (#12295)
* creates stattext component
* creates .scss file
* creates storybook
* fixes typo
* fixes readme
* adds changelog
* finishes tests
---
changelog/12295.txt | 3 +
ui/README.md | 27 ++++-
ui/app/styles/components/stat-text.scss | 101 ++++++++++++++++++
ui/app/styles/core.scss | 1 +
ui/app/styles/utils/_bulma_variables.scss | 7 +-
ui/lib/core/addon/components/stat-text.js | 21 ++++
.../addon/templates/components/stat-text.hbs | 7 ++
ui/lib/core/app/components/stat-text.js | 1 +
ui/lib/core/stories/stat-text.md | 26 +++++
ui/lib/core/stories/stat-text.stories.js | 28 +++++
.../integration/components/stat-text-test.js | 29 +++++
11 files changed, 247 insertions(+), 4 deletions(-)
create mode 100644 changelog/12295.txt
create mode 100644 ui/app/styles/components/stat-text.scss
create mode 100644 ui/lib/core/addon/components/stat-text.js
create mode 100644 ui/lib/core/addon/templates/components/stat-text.hbs
create mode 100644 ui/lib/core/app/components/stat-text.js
create mode 100644 ui/lib/core/stories/stat-text.md
create mode 100644 ui/lib/core/stories/stat-text.stories.js
create mode 100644 ui/tests/integration/components/stat-text-test.js
diff --git a/changelog/12295.txt b/changelog/12295.txt
new file mode 100644
index 000000000..144ad0f58
--- /dev/null
+++ b/changelog/12295.txt
@@ -0,0 +1,3 @@
+```release-note:feature
+ui: Creates new StatText component
+```
\ No newline at end of file
diff --git a/ui/README.md b/ui/README.md
index 050be9aca..7f9a1ad67 100644
--- a/ui/README.md
+++ b/ui/README.md
@@ -178,7 +178,32 @@ Note that placing a param inside brackets (e.g. `[closedLabel=More options]` ind
2. Generate a new story with `ember generate story [name-of-component]`
3. Inside the newly generated `stories` file, add at least one example of the component. If the component should be interactive, enable the [Storybook Knobs addon](https://github.com/storybooks/storybook/tree/master/addons/knobs).
-4. Generate the `notes` file for the component with `yarn gen-story-md [name-of-component] [name-of-engine-or-addon]` (e.g. `yarn gen-md alert-banner core`). This will generate markdown documentation of the component and place it at `vault/ui/stories/[name-of-component].md`. If your component is a template-only component, you will need to manually create the markdown file.
+4. Generate the `notes` file for the component with `yarn gen-story-md [name-of-component] [name-of-engine-or-addon]` (e.g. `yarn gen-md alert-banner core`). This will generate markdown documentation of the component and place it at `vault/ui/stories/[name-of-component].md`. If your component is a template-only component, you will need to manually create the markdown file. The markdown file will need to be imported in your `[component-name].stories.js` file (e.g. `import notes from './[name-of-component].md'`).
+5. The completed `[component-name].stories.js` file should look something like this (with knobs):
+````js
+import hbs from 'htmlbars-inline-precompile';
+import { storiesOf } from '@storybook/ember';
+import { text, withKnobs } from '@storybook/addon-knobs';
+import notes from './stat-text.md';
+
+storiesOf('MyComponent', module)
+ .addParameters({ options: { showPanel: true } })
+ .addDecorator(withKnobs())
+ .add(
+ `MyComponent`,
+ () => ({
+ template: hbs`
+
My Component
+
+ `,
+ context: {
+ param: text('param', 'My parameter'),
+ anotherParam: boolean('anotherParam', true)
+ },
+ }),
+ { notes }
+ );
+````
See the [Storybook Docs](https://storybook.js.org/docs/basics/introduction/) for more information on writing stories.
diff --git a/ui/app/styles/components/stat-text.scss b/ui/app/styles/components/stat-text.scss
new file mode 100644
index 000000000..814d8a87b
--- /dev/null
+++ b/ui/app/styles/components/stat-text.scss
@@ -0,0 +1,101 @@
+.stat-text-container {
+ line-height: normal;
+
+ &.l,
+ &.m {
+ .stat-label {
+ font-size: $size-5;
+ font-weight: $font-weight-semibold;
+ line-height: inherit;
+ }
+ .stat-text {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-700;
+ line-height: inherit;
+ }
+ .stat-value {
+ font-size: $size-3;
+ font-weight: $font-weight-normal;
+ margin-top: $spacing-s;
+ }
+ }
+
+ &.s {
+ .stat-label {
+ font-size: $size-5;
+ font-weight: $font-weight-semibold;
+ line-height: inherit;
+ }
+ .stat-text {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-700;
+ line-height: inherit;
+ }
+ .stat-value {
+ font-size: $size-5;
+ font-weight: $font-weight-normal;
+ margin-top: $spacing-s;
+ }
+ }
+
+ &.l-no-subText {
+ .stat-label {
+ font-size: $size-5;
+ font-weight: $font-weight-semibold;
+ line-height: inherit;
+ }
+ .stat-text {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-700;
+ line-height: inherit;
+ }
+ .stat-value {
+ font-size: $size-3;
+ font-weight: $font-weight-normal;
+ margin-top: $spacing-xxs;
+ }
+ }
+
+ &.m-no-subText {
+ .stat-label {
+ font-size: $size-8;
+ font-weight: $font-weight-bold;
+ line-height: inherit;
+ }
+ .stat-text {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-700;
+ line-height: inherit;
+ }
+ .stat-value {
+ font-size: $size-5;
+ font-weight: $font-weight-normal;
+ margin-top: $spacing-xxs;
+ }
+ }
+
+ &.s-no-subText {
+ .stat-label {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-500;
+ line-height: inherit;
+ }
+ .stat-text {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-700;
+ line-height: inherit;
+ }
+ .stat-value {
+ font-size: $size-8;
+ font-weight: $font-weight-normal;
+ color: $ui-gray-800;
+ line-height: inherit;
+ }
+ }
+}
diff --git a/ui/app/styles/core.scss b/ui/app/styles/core.scss
index a2d5b1aba..cc4400750 100644
--- a/ui/app/styles/core.scss
+++ b/ui/app/styles/core.scss
@@ -101,6 +101,7 @@
@import './components/shamir-progress';
@import './components/sidebar';
@import './components/splash-page';
+@import './components/stat-text';
@import './components/status-menu';
@import './components/tabs';
@import './components/text-file';
diff --git a/ui/app/styles/utils/_bulma_variables.scss b/ui/app/styles/utils/_bulma_variables.scss
index bc20bb541..ff5aa2ca5 100644
--- a/ui/app/styles/utils/_bulma_variables.scss
+++ b/ui/app/styles/utils/_bulma_variables.scss
@@ -28,9 +28,10 @@ $family-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto'
$family-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
$family-primary: $family-sans;
$body-size: 14px;
-$size-3: (24/14) + 0rem;
-$size-7: (13/14) + 0rem;
-$size-8: (12/14) + 0rem;
+$size-3: (24/14) + 0rem; // ~1.714rem
+$size-5: 1.25rem;
+$size-7: (13/14) + 0rem; // ~.929rem
+$size-8: (12/14) + 0rem; // ~.857rem
$size-9: 0.75rem;
$size-10: 0.5rem;
$size-11: 0.25rem;
diff --git a/ui/lib/core/addon/components/stat-text.js b/ui/lib/core/addon/components/stat-text.js
new file mode 100644
index 000000000..e001c643b
--- /dev/null
+++ b/ui/lib/core/addon/components/stat-text.js
@@ -0,0 +1,21 @@
+/**
+ * @module StatText
+ * StatText components are used to display a label and associated value beneath, with the option to include a description.
+ *
+ * @example
+ * ```js
+ *
+ * ```
+ * @param {string} label=null - The label for the statistic
+ * @param {string} value=null - Value passed in, usually a number or statistic
+ * @param {string} size=null - Sizing changes whether or not there is subtext. If there is subtext 's' and 'l' are valid sizes. If no subtext, then 'm' is also acceptable.
+ * @param {string} [subText] - SubText is optional and will display below the label
+ */
+
+import Component from '@glimmer/component';
+import layout from '../templates/components/stat-text';
+import { setComponentTemplate } from '@ember/component';
+
+class StatTextComponent extends Component {}
+
+export default setComponentTemplate(layout, StatTextComponent);
diff --git a/ui/lib/core/addon/templates/components/stat-text.hbs b/ui/lib/core/addon/templates/components/stat-text.hbs
new file mode 100644
index 000000000..9d4bb916d
--- /dev/null
+++ b/ui/lib/core/addon/templates/components/stat-text.hbs
@@ -0,0 +1,7 @@
+
+
{{@label}}
+ {{#if @subText}}
+
{{@subText}}
+ {{/if}}
+
{{@value}}
+
diff --git a/ui/lib/core/app/components/stat-text.js b/ui/lib/core/app/components/stat-text.js
new file mode 100644
index 000000000..a15c6b560
--- /dev/null
+++ b/ui/lib/core/app/components/stat-text.js
@@ -0,0 +1 @@
+export { default } from 'core/components/stat-text';
diff --git a/ui/lib/core/stories/stat-text.md b/ui/lib/core/stories/stat-text.md
new file mode 100644
index 000000000..d156bfe83
--- /dev/null
+++ b/ui/lib/core/stories/stat-text.md
@@ -0,0 +1,26 @@
+
+
+## StatText
+StatText components are used to display a label and associated value beneath, with the option to include a description.
+
+**Params**
+
+| Param | Type | Default | Description |
+| --- | --- | --- | --- |
+| label | string
| null
| The label for the statistic |
+| value | string
| null
| Value passed in, usually a number or statistic |
+| size | string
| null
| Sizing changes whether or not there is subtext. If there is subtext 's' and 'l' are valid sizes. If no subtext, then 'm' is also acceptable. |
+| [subText] | string
| | SubText is optional and will display below the label |
+
+**Example**
+
+```js
+
+```
+
+**See**
+
+- [Uses of StatText](https://github.com/hashicorp/vault/search?l=Handlebars&q=StatText+OR+stat-text)
+- [StatText Source Code](https://github.com/hashicorp/vault/blob/master/ui/lib/core/addon/components/stat-text.js)
+
+---
diff --git a/ui/lib/core/stories/stat-text.stories.js b/ui/lib/core/stories/stat-text.stories.js
new file mode 100644
index 000000000..3217838b4
--- /dev/null
+++ b/ui/lib/core/stories/stat-text.stories.js
@@ -0,0 +1,28 @@
+import hbs from 'htmlbars-inline-precompile';
+import { storiesOf } from '@storybook/ember';
+import { text, withKnobs } from '@storybook/addon-knobs';
+import notes from './stat-text.md';
+
+storiesOf('StatText', module)
+ .addParameters({ options: { showPanel: true } })
+ .addDecorator(withKnobs())
+ .add(
+ `StatText`,
+ () => ({
+ template: hbs`
+ StatText Component
+
+ `,
+ context: {
+ label: text('label', 'Active Clients'),
+ value: text('value', '4,198'),
+ size: text('size', 'l'),
+ subText: text('subText', 'These are your active clients'),
+ },
+ }),
+ { notes }
+ );
diff --git a/ui/tests/integration/components/stat-text-test.js b/ui/tests/integration/components/stat-text-test.js
new file mode 100644
index 000000000..2c1f2bf61
--- /dev/null
+++ b/ui/tests/integration/components/stat-text-test.js
@@ -0,0 +1,29 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | StatText', function(hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function(assert) {
+ await render(hbs``);
+
+ assert.dom('[data-test-stat-text-container]').exists('renders element');
+ });
+
+ test('it renders passed in attributes', async function(assert) {
+ this.set('label', 'A Label');
+ this.set('value', '9,999');
+ this.set('size', 'l');
+ this.set('subText', 'This is my description');
+
+ await render(
+ hbs``
+ );
+
+ assert.dom('.stat-label').hasText(this.label, 'renders label');
+ assert.dom('.stat-text').hasText(this.subText, 'renders subtext');
+ assert.dom('.stat-value').hasText(this.value, 'renders value');
+ });
+});