Skip to content

Commit 4f50a23

Browse files
feat(helper-text): add pf-helper-text element (#2947)
* feat: create pf-helper-text element * style(helper-text): improved demo page for more accurate alignment with requirements * refactor(docs): improve pf-helper-text code, translate comments, align docs with pf-icon * docs(helper-text): add detailed documentation with examples and icon usage * feat(helper-text): implement pf-helper-text component and refactor demos * docs(helper-text): update demos * fix(helper-text): simplify * fix: attribution * test: add tests * docs: add demo * fix: revert other changes --------- Co-authored-by: Benny Powers - עם ישראל חי! <bennypowers@users.noreply.github.com> Co-authored-by: Benny Powers <web@bennypowers.com>
1 parent 280ef9b commit 4f50a23

File tree

12 files changed

+375
-0
lines changed

12 files changed

+375
-0
lines changed

elements/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"./pf-dropdown/pf-dropdown-item.js": "./pf-dropdown/pf-dropdown-item.js",
3333
"./pf-dropdown/pf-dropdown-menu.js": "./pf-dropdown/pf-dropdown-menu.js",
3434
"./pf-dropdown/pf-dropdown.js": "./pf-dropdown/pf-dropdown.js",
35+
"./pf-helper-text/pf-helper-text.js": "./pf-helper-text/pf-helper-text.js",
3536
"./pf-hint/pf-hint.js": "./pf-hint/pf-hint.js",
3637
"./pf-icon/pf-icon.js": "./pf-icon/pf-icon.js",
3738
"./pf-jazz-hands/pf-jazz-hands.js": "./pf-jazz-hands/pf-jazz-hands.js",
@@ -118,6 +119,7 @@
118119
"Ajinyka Shinde <sajinkya359@gmail.com>",
119120
"Avigail Chubara (https://github.com/chubara62372)",
120121
"Benny Powers <bennyp@redhat.com>",
122+
"Daly Betzalel (https://github.com/dali327519294)",
121123
"Daniel Faucette",
122124
"Diwanshi Pandey <diwanshipandey@gmail.com> (https://github.com/diwanshi)",
123125
"Gili Greenberger (https://github.com/Gili-Greenberger)",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<pf-helper-text>
2+
<ul>
3+
<li class="success">
4+
<pf-icon icon="check-circle"></pf-icon> Must be at least 14 characters
5+
</li>
6+
<li class="error">
7+
<pf-icon icon="exclamation-circle"></pf-icon> Cannot contain any variation of the word "redhat"
8+
</li>
9+
<li class="success">
10+
<pf-icon icon="check-circle"></pf-icon> Must include at least 3 of the following: lowercase letter, uppercase letters, numbers, symbols
11+
</li>
12+
</ul>
13+
</pf-helper-text>
14+
15+
<script type="module">
16+
import '@patternfly/elements/pf-helper-text/pf-helper-text.js';
17+
import '@patternfly/elements/pf-icon/pf-icon.js';
18+
</script>
19+
20+
<style>
21+
li {
22+
margin-block: 0.25rem;
23+
&.success {
24+
color: var(--pf-c-helper-text__item-text--m-success--Color, #1e4f18);
25+
}
26+
&.error {
27+
color: var(--pf-c-helper-text__item-text--m-error--Color, #a30000);
28+
}
29+
}
30+
</style>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<pf-helper-text icon="minus"
2+
variant="default">
3+
This is default helper text
4+
</pf-helper-text>
5+
6+
<pf-helper-text icon="minus"
7+
variant="indeterminate">
8+
This is indeterminate helper text
9+
</pf-helper-text>
10+
11+
<pf-helper-text icon="exclamation-triangle"
12+
variant="warning">
13+
This is warning helper text
14+
</pf-helper-text>
15+
16+
<pf-helper-text icon="check-circle"
17+
variant="success">
18+
This is success helper text
19+
</pf-helper-text>
20+
21+
<pf-helper-text icon="exclamation-circle"
22+
variant="error">
23+
This is error helper text
24+
</pf-helper-text>
25+
26+
<script type="module">
27+
import '@patternfly/elements/pf-helper-text/pf-helper-text.js';
28+
import '@patternfly/elements/pf-icon/pf-icon.js';
29+
</script>
30+
31+
<style>
32+
pf-helper-text {
33+
display: block;
34+
margin-block: 0.25rem;
35+
}
36+
37+
pf-icon {
38+
fill: currentColor;
39+
width: 1em;
40+
height: 1em;
41+
}
42+
</style>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<pf-helper-text variant="success">Success!</pf-helper-text>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<pf-helper-text variant="default">
2+
<ul>
3+
<li>This is default helper text</li>
4+
<li>This is another default helper text in the same block</li>
5+
<li>And this is more default text in the same block</li>
6+
</ul>
7+
</pf-helper-text>
8+
9+
<script type="module">
10+
import '@patternfly/elements/pf-helper-text/pf-helper-text.js';
11+
</script>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<pf-helper-text icon="minus" variant="default">
2+
This is default helper text
3+
</pf-helper-text>
4+
5+
<pf-helper-text icon="minus" variant="indeterminate">
6+
This is indeterminate helper text
7+
</pf-helper-text>
8+
9+
<pf-helper-text icon="exclamation-triangle" variant="warning">
10+
This is warning helper text
11+
</pf-helper-text>
12+
13+
<pf-helper-text icon="check-circle" variant="success">
14+
This is success helper text
15+
</pf-helper-text>
16+
17+
<pf-helper-text icon="exclamation-circle" variant="error">
18+
This is error helper text
19+
</pf-helper-text>
20+
21+
<script type="module">
22+
import '@patternfly/elements/pf-helper-text/pf-helper-text.js';
23+
import '@patternfly/elements/pf-icon/pf-icon.js';
24+
</script>
25+
26+
<style>
27+
pf-helper-text {
28+
display: block;
29+
margin-block: 0.25rem;
30+
}
31+
32+
pf-icon {
33+
fill: currentColor;
34+
width: 1em;
35+
height: 1em;
36+
}
37+
</style>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<pf-helper-text variant="default">This is default helper text</pf-helper-text>
2+
<pf-helper-text variant="indeterminate">This is indeterminate helper text</pf-helper-text>
3+
<pf-helper-text variant="warning">This is warning helper text</pf-helper-text>
4+
<pf-helper-text variant="success">This is success helper text</pf-helper-text>
5+
<pf-helper-text variant="error">This is error helper text</pf-helper-text>
6+
7+
<script type="module">
8+
import '@patternfly/elements/pf-helper-text/pf-helper-text.js';
9+
</script>
10+
11+
<style>
12+
pf-helper-text {
13+
display: block;
14+
margin-block: 0.25rem;
15+
}
16+
</style>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{% renderOverview %}
2+
<pf-helper-text></pf-helper-text>
3+
{% endrenderOverview %}
4+
5+
{% band header="Usage" %}{% endband %}
6+
7+
{% renderSlots %}{% endrenderSlots %}
8+
9+
{% renderAttributes %}{% endrenderAttributes %}
10+
11+
{% renderMethods %}{% endrenderMethods %}
12+
13+
{% renderEvents %}{% endrenderEvents %}
14+
15+
{% renderCssCustomProperties %}{% endrenderCssCustomProperties %}
16+
17+
{% renderCssParts %}{% endrenderCssParts %}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
:host {
2+
display: flex;
3+
align-items: center;
4+
gap: var(--pf-c-helper-text--Gap, 0.25rem);
5+
font-size: var(--pf-c-helper-text--FontSize, 0.875rem);
6+
color: var(--pf-c-helper-text__item-text--Color, #151515);
7+
line-height: 1.4;
8+
}
9+
10+
/* Color variants */
11+
:host([variant='indeterminate']) {
12+
color: var(--pf-c-helper-text__item-text--m-indeterminate--Color, #6a6e73);
13+
}
14+
15+
:host([variant='warning']) {
16+
color: var(--pf-c-helper-text__item-text--m-warning--Color, #795600);
17+
}
18+
19+
:host([variant='success']) {
20+
color: var(--pf-c-helper-text__item-text--m-success--Color, #1e4f18);
21+
}
22+
23+
:host([variant='error']) {
24+
color: var(--pf-c-helper-text__item-text--m-error--Color, #a30000);
25+
}
26+
27+
::slotted(ul) {
28+
margin: 0;
29+
padding: 0;
30+
list-style-type: none;
31+
}
32+
33+
pf-icon {
34+
fill: currentColor;
35+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { LitElement, html, type TemplateResult } from 'lit';
2+
import { customElement } from 'lit/decorators/custom-element.js';
3+
import { property } from 'lit/decorators/property.js';
4+
import { ifDefined } from 'lit/directives/if-defined.js';
5+
6+
import { SlotController } from '@patternfly/pfe-core/controllers/slot-controller.js';
7+
8+
import '@patternfly/elements/pf-icon/pf-icon.js';
9+
10+
import styles from './pf-helper-text.css';
11+
12+
/** Map of status to default icons (Font Awesome solid set). */
13+
const StatusIconMap = {
14+
success: 'check-circle',
15+
warning: 'exclamation-triangle',
16+
error: 'exclamation-circle',
17+
indeterminate: 'info-circle',
18+
};
19+
20+
/**
21+
* Displays contextual feedback for form fields with optional icon and status color.
22+
*
23+
* @slot icon - Optional custom icon to override the default icon.
24+
* @slot - Default slot for the helper text content.
25+
*
26+
* @fires icon-load - Fired when the icon successfully loads.
27+
* @fires icon-error - Fired if loading the icon fails.
28+
*
29+
* @csspart icon - The container for the icon.
30+
* @csspart text - The container for the text.
31+
*/
32+
@customElement('pf-helper-text')
33+
export class PfHelperText extends LitElement {
34+
public static readonly styles: CSSStyleSheet[] = [styles];
35+
36+
/**
37+
* Defines the helper text status and its corresponding color and icon.
38+
*/
39+
@property({ reflect: true }) variant:
40+
| 'default'
41+
| 'success'
42+
| 'warning'
43+
| 'error'
44+
| 'indeterminate' = 'default';
45+
46+
/**
47+
* Custom icon name to override the default icon.
48+
* Requires `<pf-icon>` to be imported.
49+
*/
50+
@property() icon?: string;
51+
52+
/**
53+
* Icon set for custom icons (e.g., 'fas', 'patternfly').
54+
*/
55+
@property({ attribute: 'icon-set' }) iconSet?: string;
56+
57+
#slots = new SlotController(this, 'icon', null);
58+
59+
/**
60+
* Determine the effective icon to display.
61+
*/
62+
private get _resolvedIcon(): string | undefined {
63+
if (this.icon) {
64+
return this.icon;
65+
}
66+
if (this.variant !== 'default') {
67+
return StatusIconMap[this.variant];
68+
}
69+
return undefined;
70+
}
71+
72+
protected render(): TemplateResult<1> {
73+
const iconName = this._resolvedIcon;
74+
const showIcon = !!this.icon || this.#slots.hasSlotted('icon');
75+
76+
return html`
77+
<span id="icon" ?hidden="${!showIcon}">
78+
<slot name="icon">
79+
<pf-icon icon="${iconName}"
80+
set="${ifDefined(this.iconSet)}"
81+
role="presentation"></pf-icon>
82+
</slot>
83+
</span>
84+
<span id="text" aria-live="polite">
85+
<slot></slot>
86+
</span>
87+
`;
88+
}
89+
}
90+
91+
declare global {
92+
interface HTMLElementTagNameMap {
93+
'pf-helper-text': PfHelperText;
94+
}
95+
}

0 commit comments

Comments
 (0)