Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI/StatText Component #12295

Merged
merged 17 commits into from Aug 16, 2021
Merged
3 changes: 3 additions & 0 deletions changelog/12295.txt
@@ -0,0 +1,3 @@
```release-note:feature
ui: Creates new StatText component
```
27 changes: 26 additions & 1 deletion ui/README.md
Expand Up @@ -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`
<h5 class="title is-5">My Component</h5>
<MyComponent @param={{param}} @anotherParam={{anotherParam}} />
`,
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.

Expand Down
119 changes: 119 additions & 0 deletions ui/app/styles/components/stat-text.scss
@@ -0,0 +1,119 @@
.stat-text-container {
line-height: normal;

&.l {
.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;
}
}
// medium styling is the same as large
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
&.m {
.stat-label {
font-size: $size-5;
font-weight: $font-weight-semibold;
line-height: inherit;
}
.stat-text {
Monkeychip marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}
}
1 change: 1 addition & 0 deletions ui/app/styles/core.scss
Expand Up @@ -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';
Expand Down
7 changes: 4 additions & 3 deletions ui/app/styles/utils/_bulma_variables.scss
Expand Up @@ -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
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
$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;
Expand Down
21 changes: 21 additions & 0 deletions ui/lib/core/addon/components/stat-text.js
@@ -0,0 +1,21 @@
/**
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
* @module StatText
* StatText components are used to display a label and associated value beneath, with the option to include a description.
*
* @example
* ```js
* <StatText @label="Active Clients" @stat="4,198" @size="l" @subText="These are the active client counts"/>
* ```
* @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);
7 changes: 7 additions & 0 deletions ui/lib/core/addon/templates/components/stat-text.hbs
@@ -0,0 +1,7 @@
<div class={{concat "stat-text-container " @size (unless @subText "-no-subText")}} data-test-stat-text-container>
<div class="stat-label">{{@label}}</div>
{{#if @subText}}
<div class="stat-text">{{@subText}}</div>
{{/if}}
<div class="stat-value">{{@value}}</div>
</div>
1 change: 1 addition & 0 deletions ui/lib/core/app/components/stat-text.js
@@ -0,0 +1 @@
export { default } from 'core/components/stat-text';
26 changes: 26 additions & 0 deletions ui/lib/core/stories/stat-text.md
@@ -0,0 +1,26 @@
<!--THIS FILE IS AUTO GENERATED. This file is generated from JSDoc comments in lib/core/addon/components/stat-text.js. To make changes, first edit that file and run "yarn gen-story-md stat-text" to re-generate the content.-->

## 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 | <code>string</code> | <code>null</code> | The label for the statistic |
| value | <code>string</code> | <code>null</code> | Value passed in, usually a number or statistic |
| size | <code>string</code> | <code>null</code> | 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] | <code>string</code> | | SubText is optional and will display below the label |

**Example**

```js
<StatText @label="Active Clients" @stat="4,198" @size="l" @subText="These are the active client counts"/>
```

**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)

---
28 changes: 28 additions & 0 deletions 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`
<h5 class="title is-5">StatText Component</h5>
<StatText
@label={{label}}
@value={{value}}
@size={{size}}
@subText={{subText}} />
`,
context: {
label: text('label', 'Active Clients'),
value: text('value', '4,198'),
size: text('size', 'l'),
subText: text('subText', 'These are your active clients'),
},
}),
{ notes }
);
29 changes: 29 additions & 0 deletions 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`<StatText />`);

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`<StatText @label={{this.label}} @size={{this.size}} @value={{this.value}} @subText={{this.subText}}/>`
);

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');
});
});