@jack-henry/jh-elements 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +26 -0
  3. package/README.md +13 -0
  4. package/components/badge/badge.js +73 -0
  5. package/components/button/button.js +953 -0
  6. package/components/card/card.js +343 -0
  7. package/components/checkbox/checkbox.js +601 -0
  8. package/components/checkbox-group/checkbox-group.js +241 -0
  9. package/components/divider/divider.js +91 -0
  10. package/components/icon/icon.js +96 -0
  11. package/components/input/input.js +1247 -0
  12. package/components/input-email/input-email.js +18 -0
  13. package/components/input-password/input-password.js +153 -0
  14. package/components/input-search/input-search.js +41 -0
  15. package/components/input-telephone/input-telephone.js +18 -0
  16. package/components/input-textarea/input-textarea.js +379 -0
  17. package/components/input-url/input-url.js +31 -0
  18. package/components/list-group/list-group.js +103 -0
  19. package/components/list-item/list-item.js +350 -0
  20. package/components/menu/menu.js +60 -0
  21. package/components/notification/notification.js +327 -0
  22. package/components/progress/progress.js +417 -0
  23. package/components/radio/radio.js +422 -0
  24. package/components/radio-group/radio-group.js +400 -0
  25. package/components/switch/switch.js +315 -0
  26. package/components/table/table.js +367 -0
  27. package/components/table-data-cell/table-data-cell.js +107 -0
  28. package/components/table-header-cell/table-header-cell.js +321 -0
  29. package/components/table-row/table-row.js +52 -0
  30. package/components/tag/tag.js +422 -0
  31. package/components/tag-group/tag-group.js +57 -0
  32. package/components/toast/toast.js +172 -0
  33. package/components/toast-controller/toast-controller.js +122 -0
  34. package/components/tooltip/tooltip.js +498 -0
  35. package/custom-elements.json +6892 -0
  36. package/index.d.ts +69 -0
  37. package/jsconfig.json +9 -0
  38. package/package.json +52 -0
  39. package/utils/themeProvider.js +32 -0
@@ -0,0 +1,953 @@
1
+ // SPDX-FileCopyrightText: 2025 Jack Henry
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { LitElement, css, html } from 'lit';
6
+ import { ifDefined } from 'lit/directives/if-defined.js';
7
+ import '../progress/progress.js';
8
+
9
+ /**
10
+ * @cssprop --jh-button-color-background-primary-enabled - The button container background-color when enabled and `appearance="primary"`. Defaults to `--jh-color-content-brand-enabled`.
11
+ * @cssprop --jh-button-color-border-primary-enabled - The button container border-color when enabled and `appearance="primary"`. Defaults to `transparent`.
12
+ * @cssprop --jh-button-color-background-primary-focus - The button container background-color when in focus and `appearance="primary"`. Defaults to `--jh-color-content-brand-hover`.
13
+ * @cssprop --jh-button-color-border-primary-focus - The button container border-color when in focus and `appearance="primary"`. Defaults to `transparent`.
14
+ * @cssprop --jh-button-color-background-primary-hover - The button container background-color when hovered and `appearance="primary"`. Defaults to `--jh-color-content-brand-hover`.
15
+ * @cssprop --jh-button-color-border-primary-hover - The button container border-color when hovered and `appearance="primary"`. Defaults to `transparent`.
16
+ * @cssprop --jh-button-color-background-primary-active - The button container background-color when active and `appearance="primary"`. Defaults to `--jh-color-content-brand-active`.
17
+ * @cssprop --jh-button-color-border-primary-active - The button container border-color when active and `appearance="primary"`. Defaults to `transparent`.
18
+ * @cssprop --jh-button-color-background-primary-disabled - The button container background-color when disabled and `appearance="primary"`. Defaults to `--jh-color-content-brand-enabled`.
19
+ * @cssprop --jh-button-color-border-primary-disabled - The button container border-color when disabled and `appearance="primary"`. Defaults to `transparent`.
20
+ * @cssprop --jh-button-color-background-primary-pending - The button container background-color when pending and `appearance="primary"`. Defaults to `--jh-color-content-brand-enabled`.
21
+ * @cssprop --jh-button-color-border-primary-pending - The button container border-color when pending and `appearance="primary"`. Defaults to `transparent`.
22
+ * @cssprop --jh-button-label-color-text-primary-enabled - The label text color when enabled and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-enabled`.
23
+ * @cssprop --jh-button-label-color-text-primary-focus - The label text color when in focus and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-hover`.
24
+ * @cssprop --jh-button-label-color-text-primary-hover - The label text color when hovered and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-hover`.
25
+ * @cssprop --jh-button-label-color-text-primary-active - The label text color when active and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-active`.
26
+ * @cssprop --jh-button-label-color-text-primary-disabled - The label text color when disabled and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-enabled`.
27
+ * @cssprop --jh-button-icon-color-fill-primary-enabled - The icon color when enabled and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-enabled`.
28
+ * @cssprop --jh-button-icon-color-fill-primary-focus - The icon color when in focus and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-hover`.
29
+ * @cssprop --jh-button-icon-color-fill-primary-hover - The icon color when hovered and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-hover`.
30
+ * @cssprop --jh-button-icon-color-fill-primary-active - The icon color when active and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-active`.
31
+ * @cssprop --jh-button-icon-color-fill-primary-disabled - The icon color when disabled and `appearance="primary"`. Defaults to `--jh-color-content-on-brand-enabled`.
32
+ * @cssprop --jh-button-progress-color-border-primary-pending - The progress indicator border-color when `appearance="primary"`. Defaults to `--jh-color-content-on-brand-enabled`.
33
+ * @cssprop --jh-button-color-background-secondary-enabled - The button container background-color when enabled and `appearance="secondary"`. Defaults to `transparent`.
34
+ * @cssprop --jh-button-color-border-secondary-enabled - The button container border-color when enabled and `appearance="secondary"`. Defaults to `--jh-border-action-color`.
35
+ * @cssprop --jh-button-color-background-secondary-focus - The button container background-color when in focus and `appearance="secondary"`. Defaults to `--jh-color-content-brand-hover`.
36
+ * @cssprop --jh-button-color-border-secondary-focus - The button container border-color when in focus and `appearance="secondary"`. Defaults to `--jh-color-content-brand-hover`.
37
+ * @cssprop --jh-button-color-background-secondary-hover - The button container background-color when hovered and `appearance="secondary"`. Defaults to `--jh-color-content-brand-hover`.
38
+ * @cssprop --jh-button-color-border-secondary-hover - The button container border-color when hovered and `appearance="secondary"`. Defaults to `--jh-color-content-brand-hover`.
39
+ * @cssprop --jh-button-color-background-secondary-active - The button container background-color when active and `appearance="secondary"`. Defaults to `--jh-color-content-brand-active`.
40
+ * @cssprop --jh-button-color-border-secondary-active - The button container border-color when active and `appearance="secondary"`. Defaults to `--jh-color-content-brand-active`.
41
+ * @cssprop --jh-button-color-background-secondary-disabled - The button container background-color when disabled and `appearance="secondary"`. Defaults to `transparent`.
42
+ * @cssprop --jh-button-color-border-secondary-disabled - The button container border-color when disabled and `appearance="secondary"`. Defaults to `--jh-border-action-color`.
43
+ * @cssprop --jh-button-color-background-secondary-pending - The button container background-color when pending and `appearance="secondary"`. Defaults to `transparent`.
44
+ * @cssprop --jh-button-color-border-secondary-pending - The button container border-color when pending and `appearance="secondary"`. Defaults to `--jh-border-action-color`.
45
+ * @cssprop --jh-button-label-color-text-secondary-enabled - The label text color when enabled and `appearance="secondary"`. Defaults to `--jh-color-content-brand-enabled`.
46
+ * @cssprop --jh-button-label-color-text-secondary-focus - The label text color when in focus and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-hover`.
47
+ * @cssprop --jh-button-label-color-text-secondary-hover - The label text color when hovered and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-hover`.
48
+ * @cssprop --jh-button-label-color-text-secondary-active - The label text color when active and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-active`.
49
+ * @cssprop --jh-button-label-color-text-secondary-disabled - The label text color when disabled and `appearance="secondary"`. Defaults to `--jh-color-content-brand-enabled`.
50
+ * @cssprop --jh-button-icon-color-fill-secondary-enabled - The icon color when enabled and `appearance="secondary"`. Defaults to `--jh-color-content-brand-enabled`.
51
+ * @cssprop --jh-button-icon-color-fill-secondary-focus - The icon color when in focus and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-hover`.
52
+ * @cssprop --jh-button-icon-color-fill-secondary-hover - The icon color when hovered and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-hover`.
53
+ * @cssprop --jh-button-icon-color-fill-secondary-active - The icon color when active and `appearance="secondary"`. Defaults to `--jh-color-content-on-brand-active`.
54
+ * @cssprop --jh-button-icon-color-fill-secondary-disabled - The icon color when disabled and `appearance="secondary"`. Defaults to `--jh-color-content-brand-enabled`.
55
+ * @cssprop --jh-button-progress-color-border-secondary-pending - The progress indicator border-color when `appearance="secondary"`. Defaults to `--jh-color-content-brand-enabled`.
56
+ * @cssprop --jh-button-color-background-tertiary-enabled - The button container background-color when enabled and `appearance="tertiary"`. Defaults to `transparent`.
57
+ * @cssprop --jh-button-color-border-tertiary-enabled - The button container border-color when enabled and `appearance="tertiary"`. Defaults to `transparent`.
58
+ * @cssprop --jh-button-color-background-tertiary-focus - The button container background-color when in focus and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-hover`.
59
+ * @cssprop --jh-button-color-border-tertiary-focus - The button container border-color when in focus and `appearance="tertiary"`. Defaults to `transparent`.
60
+ * @cssprop --jh-button-color-background-tertiary-hover - The button container background-color when hovered and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-hover`.
61
+ * @cssprop --jh-button-color-border-tertiary-hover - The button container border-color when hovered and `appearance="tertiary"`. Defaults to `transparent`.
62
+ * @cssprop --jh-button-color-background-tertiary-active - The button container background-color when active and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-active`.
63
+ * @cssprop --jh-button-color-border-tertiary-active - The button container border-color when active and `appearance="tertiary"`. Defaults to `transparent`.
64
+ * @cssprop --jh-button-color-background-tertiary-disabled - The button container background-color when disabled and `appearance="tertiary"`. Defaults to `transparent`.
65
+ * @cssprop --jh-button-color-border-tertiary-disabled - The button container border-color when disabled and `appearance="tertiary"`. Defaults to `transparent`.
66
+ * @cssprop --jh-button-color-background-tertiary-pending - The button container background-color when pending and `appearance="tertiary"`. Defaults to `transparent`.
67
+ * @cssprop --jh-button-color-border-tertiary-pending - The button container border-color when pending and `appearance="tertiary"`. Defaults to `transparent`.
68
+ * @cssprop --jh-button-label-color-text-tertiary-enabled - The label text color when enabled and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-enabled`.
69
+ * @cssprop --jh-button-label-color-text-tertiary-focus - The label text color when in focus and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-hover`.
70
+ * @cssprop --jh-button-label-color-text-tertiary-hover - The label text color when hovered and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-hover`.
71
+ * @cssprop --jh-button-label-color-text-tertiary-active - The label text color when active and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-active`.
72
+ * @cssprop --jh-button-label-color-text-tertiary-disabled - The label text color when disabled and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-enabled`.
73
+ * @cssprop --jh-button-icon-color-fill-tertiary-enabled - The icon color when enabled and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-enabled`.
74
+ * @cssprop --jh-button-icon-color-fill-tertiary-focus - The icon color when in focus and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-hover`.
75
+ * @cssprop --jh-button-icon-color-fill-tertiary-hover - The icon color when hovered and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-hover`.
76
+ * @cssprop --jh-button-icon-color-fill-tertiary-active - The icon color when active and `appearance="tertiary"`. Defaults to `--jh-color-content-on-brand-active`.
77
+ * @cssprop --jh-button-icon-color-fill-tertiary-disabled - The icon color when disabled and `appearance="tertiary"`. Defaults to `--jh-color-content-brand-enabled`.
78
+ * @cssprop --jh-button-progress-color-border-tertiary-pending - The progress indicator border-color when `appearance="tertiary"`. Defaults to `--jh-color-content-brand-enabled`.
79
+ * @cssprop --jh-button-color-background-danger-enabled - The button container background-color when enabled and `appearance="danger"`. Defaults to `--jh-color-content-negative-enabled`.
80
+ * @cssprop --jh-button-color-border-danger-enabled - The button container border-color when enabled and `appearance="danger"`. Defaults to `transparent`.
81
+ * @cssprop --jh-button-color-background-danger-focus - The button container background-color when in focus and `appearance="danger"`. Defaults to `--jh-color-content-negative-hover`.
82
+ * @cssprop --jh-button-color-border-danger-focus - The button container border-color when in focus and `appearance="danger"`. Defaults to `transparent`.
83
+ * @cssprop --jh-button-color-background-danger-hover - The button container background-color when hovered and `appearance="danger"`. Defaults to `--jh-color-content-negative-hover`.
84
+ * @cssprop --jh-button-color-border-danger-hover - The button container border-color when hovered and `appearance="danger"`. Defaults to `transparent`.
85
+ * @cssprop --jh-button-color-background-danger-active - The button container background-color when active and `appearance="danger"`. Defaults to `--jh-color-content-negative-active`.
86
+ * @cssprop --jh-button-color-border-danger-active - The button container border-color when active and `appearance="danger"`. Defaults to `transparent`.
87
+ * @cssprop --jh-button-color-background-danger-disabled - The button container background-color when disabled and `appearance="danger"`. Defaults to `--jh-color-content-negative-enabled`.
88
+ * @cssprop --jh-button-color-border-danger-disabled - The button container border-color when disabled and `appearance="danger"`. Defaults to `transparent`.
89
+ * @cssprop --jh-button-color-background-danger-pending - The button container background-color when pending and `appearance="danger"`. Defaults to `--jh-color-content-negative-enabled`.
90
+ * @cssprop --jh-button-color-border-danger-pending - The button container border-color when pending and `appearance="danger"`. Defaults to `transparent`.
91
+ * @cssprop --jh-button-label-color-text-danger-enabled - The label text color when enabled and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-enabled`.
92
+ * @cssprop --jh-button-label-color-text-danger-focus - The label text color when in focus and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-hover`.
93
+ * @cssprop --jh-button-label-color-text-danger-hover - The label text color when hovered and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-hover`.
94
+ * @cssprop --jh-button-label-color-text-danger-active - The label text color when active and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-active`.
95
+ * @cssprop --jh-button-label-color-text-danger-disabled - The label text color when disabled and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-enabled`.
96
+ * @cssprop --jh-button-icon-color-fill-danger-enabled - The icon color when enabled and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-enabled`.
97
+ * @cssprop --jh-button-icon-color-fill-danger-focus - The icon color when in focus and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-hover`.
98
+ * @cssprop --jh-button-icon-color-fill-danger-hover - The icon color when hovered and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-hover`.
99
+ * @cssprop --jh-button-icon-color-fill-danger-active - The icon color when active and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-active`.
100
+ * @cssprop --jh-button-icon-color-fill-danger-disabled - The icon color when disabled and `appearance="danger"`. Defaults to `--jh-color-content-on-negative-enabled`.
101
+ * @cssprop --jh-button-progress-color-border-danger-pending - The progress indicator border-color when `appearance="danger"`. Defaults to `--jh-color-content-on-negative-enabled`.
102
+ * @cssprop --jh-button-border-radius - The button container border-radius. Defaults to `--jh-border-radius-100`.
103
+ * @cssprop --jh-button-opacity-disabled - The button container opacity when disabled. Defaults to `--jh-opacity-disabled`.
104
+ * @cssprop --jh-button-color-focus - The button container outline when it receives keyboard focus. Defaults to `--jh-border-focus-color`.
105
+ * @cssprop --jh-button-size - The button width when no label is set, and the button height. Button width and height defaults to `--jh-dimension-1000` when `size="small"`, `--jh-dimension-1200` when `size="medium"`, and `--jh-dimension-1400` when `size="large"`.
106
+ *
107
+ * @slot jh-button-icon - Use to insert an icon.
108
+ * @customElement jh-button
109
+ */
110
+ export class JhButton extends LitElement {
111
+ /** @ignore */
112
+ static get formAssociated() {
113
+ return true;
114
+ }
115
+
116
+ /** @type {ElementInternals} */
117
+ #internals;
118
+
119
+ /** @type {?string} */
120
+ #value;
121
+
122
+ static get styles() {
123
+ return css`
124
+ :host {
125
+ display: inline-block;
126
+ touch-action: manipulation;
127
+ vertical-align: middle;
128
+ }
129
+ a {
130
+ text-decoration: none;
131
+ box-sizing: border-box;
132
+ }
133
+ button,
134
+ a {
135
+ border-radius: var(
136
+ --jh-button-border-radius,
137
+ var(--jh-border-radius-100)
138
+ );
139
+ font-family: var(--jh-font-body-medium-1-font-family);
140
+ font-weight: var(--jh-font-body-medium-1-font-weight);
141
+ font-size: var(--jh-font-body-medium-1-font-size);
142
+ line-height: var(--jh-font-body-medium-1-line-height);
143
+ border-width: var(--jh-border-action-width);
144
+ border-style: var(--jh-border-action-style);
145
+ border-color: var(--button-border-color);
146
+ padding: 0 var(--jh-dimension-400);
147
+ display: inline-flex;
148
+ justify-content: center;
149
+ align-items: center;
150
+ position: relative;
151
+ margin: 0;
152
+ cursor: pointer;
153
+ transition: background-color ease 0.2s;
154
+ }
155
+ .content-wrapper {
156
+ display: flex;
157
+ justify-content: center;
158
+ align-items: center;
159
+ }
160
+ button:focus,
161
+ a:focus {
162
+ outline: none;
163
+ }
164
+ button:focus-visible,
165
+ a:focus-visible {
166
+ outline-color: var(
167
+ --jh-button-color-focus,
168
+ var(--jh-border-focus-color)
169
+ );
170
+ outline-style: var(--jh-border-focus-style);
171
+ outline-width: var(--jh-border-focus-width);
172
+ outline-offset: 1px;
173
+ }
174
+ :host([pending]),
175
+ :host([accessible-disabled='true']),
176
+ :host([disabled]) button,
177
+ :host([disabled]) a {
178
+ cursor: default;
179
+ pointer-events: none;
180
+ }
181
+ /* Size styling ('medium' is default) */
182
+ :host([size='small']) button,
183
+ :host([size='small']) a {
184
+ height: var(--jh-button-size, var(--jh-dimension-1000));
185
+ }
186
+ :host([size='medium']) button,
187
+ :host([size='medium']) a {
188
+ height: var(--jh-button-size, var(--jh-dimension-1200));
189
+ }
190
+ :host([size='large']) button,
191
+ :host([size='large']) a {
192
+ height: var(--jh-button-size, var(--jh-dimension-1400));
193
+ }
194
+ /* appearance='primary' ('secondary' is default) */
195
+ :host([appearance='primary']) button,
196
+ :host([appearance='primary']) a {
197
+ background-color: var(
198
+ --jh-button-color-background-primary-enabled,
199
+ var(--jh-color-content-brand-enabled)
200
+ );
201
+ color: var(
202
+ --jh-button-label-color-text-primary-enabled,
203
+ var(--jh-color-content-on-brand-enabled)
204
+ );
205
+ --button-border-color: var(
206
+ --jh-button-color-border-primary-enabled,
207
+ transparent
208
+ );
209
+ --jh-icon-color-fill: var(
210
+ --jh-button-icon-color-fill-primary-enabled,
211
+ var(--jh-color-content-on-brand-enabled)
212
+ );
213
+ }
214
+ :host([appearance='primary']) button:focus-visible,
215
+ :host([appearance='primary']) a:focus-visible {
216
+ background-color: var(
217
+ --jh-button-color-background-primary-focus,
218
+ var(--jh-color-content-brand-hover)
219
+ );
220
+ color: var(
221
+ --jh-button-label-color-text-primary-focus,
222
+ var(--jh-color-content-on-brand-hover)
223
+ );
224
+ --button-border-color: var(
225
+ --jh-button-color-border-primary-focus,
226
+ transparent
227
+ );
228
+ --jh-icon-color-fill: var(
229
+ --jh-button-icon-color-fill-primary-focus,
230
+ var(--jh-color-content-on-brand-hover)
231
+ );
232
+ }
233
+ :host([appearance='primary']) button:hover,
234
+ :host([appearance='primary']) a:hover {
235
+ background-color: var(
236
+ --jh-button-color-background-primary-hover,
237
+ var(--jh-color-content-brand-hover)
238
+ );
239
+ color: var(
240
+ --jh-button-label-color-text-primary-hover,
241
+ var(--jh-color-content-on-brand-hover)
242
+ );
243
+ --button-border-color: var(
244
+ --jh-button-color-border-primary-hover,
245
+ transparent
246
+ );
247
+ --jh-icon-color-fill: var(
248
+ --jh-button-icon-color-fill-primary-hover,
249
+ var(--jh-color-content-on-brand-hover)
250
+ );
251
+ }
252
+ :host([appearance='primary']) button:active,
253
+ :host([appearance='primary']) a:active {
254
+ background-color: var(
255
+ --jh-button-color-background-primary-active,
256
+ var(--jh-color-content-brand-active)
257
+ );
258
+ color: var(
259
+ --jh-button-label-color-text-primary-active,
260
+ var(--jh-color-content-on-brand-active)
261
+ );
262
+ --button-border-color: var(
263
+ --jh-button-color-border-primary-active,
264
+ transparent
265
+ );
266
+ --jh-icon-color-fill: var(
267
+ --jh-button-icon-color-fill-primary-active,
268
+ var(--jh-color-content-on-brand-active)
269
+ );
270
+ }
271
+ :host([appearance='primary'][accessible-disabled='true'][pending]) button,
272
+ :host([appearance='primary']) button[aria-disabled='true'],
273
+ :host([appearance='primary']) a[aria-disabled='true'],
274
+ :host([appearance='primary'][disabled][pending]) button,
275
+ :host([appearance='primary']) button[disabled],
276
+ :host([appearance='primary']) a[disabled] {
277
+ background-color: var(
278
+ --jh-button-color-background-primary-disabled,
279
+ var(--jh-color-content-brand-enabled)
280
+ );
281
+ color: var(
282
+ --jh-button-label-color-text-primary-disabled,
283
+ var(--jh-color-content-on-brand-enabled)
284
+ );
285
+ --button-border-color: var(
286
+ --jh-button-color-border-primary-disabled,
287
+ transparent
288
+ );
289
+ --jh-icon-color-fill: var(
290
+ --jh-button-icon-color-fill-primary-disabled,
291
+ var(--jh-color-content-on-brand-enabled)
292
+ );
293
+ }
294
+ /* appearance='secondary' */
295
+ :host([appearance='secondary']) button,
296
+ :host([appearance='secondary']) a {
297
+ background-color: var(
298
+ --jh-button-color-background-secondary-enabled,
299
+ transparent
300
+ );
301
+ color: var(
302
+ --jh-button-label-color-text-secondary-enabled,
303
+ var(--jh-color-content-brand-enabled)
304
+ );
305
+ --button-border-color: var(
306
+ --jh-button-color-border-secondary-enabled,
307
+ var(--jh-border-action-color)
308
+ );
309
+ --jh-icon-color-fill: var(
310
+ --jh-button-icon-color-fill-secondary-enabled,
311
+ var(--jh-color-content-brand-enabled)
312
+ );
313
+ }
314
+ :host([appearance='secondary']) button:focus-visible,
315
+ :host([appearance='secondary']) a:focus-visible {
316
+ background-color: var(
317
+ --jh-button-color-background-secondary-focus,
318
+ var(--jh-color-content-brand-hover)
319
+ );
320
+ color: var(
321
+ --jh-button-label-color-text-secondary-focus,
322
+ var(--jh-color-content-on-brand-hover)
323
+ );
324
+ --button-border-color: var(
325
+ --jh-button-color-border-secondary-focus,
326
+ var(--jh-color-content-brand-hover)
327
+ );
328
+ --jh-icon-color-fill: var(
329
+ --jh-button-icon-color-fill-secondary-focus,
330
+ var(--jh-color-content-on-brand-hover)
331
+ );
332
+ }
333
+ :host([appearance='secondary']) button:hover,
334
+ :host([appearance='secondary']) a:hover {
335
+ background-color: var(
336
+ --jh-button-color-background-secondary-hover,
337
+ var(--jh-color-content-brand-hover)
338
+ );
339
+ color: var(
340
+ --jh-button-label-color-text-secondary-hover,
341
+ var(--jh-color-content-on-brand-hover)
342
+ );
343
+ --button-border-color: var(
344
+ --jh-button-color-border-secondary-hover,
345
+ var(--jh-color-content-brand-hover)
346
+ );
347
+ --jh-icon-color-fill: var(
348
+ --jh-button-icon-color-fill-secondary-hover,
349
+ var(--jh-color-content-on-brand-hover)
350
+ );
351
+ }
352
+ :host([appearance='secondary']) button:active,
353
+ :host([appearance='secondary']) a:active {
354
+ background-color: var(
355
+ --jh-button-color-background-secondary-active,
356
+ var(--jh-color-content-brand-active)
357
+ );
358
+ color: var(
359
+ --jh-button-label-color-text-secondary-active,
360
+ var(--jh-color-content-on-brand-active)
361
+ );
362
+ --button-border-color: var(
363
+ --jh-button-color-border-secondary-active,
364
+ var(--jh-color-content-brand-active)
365
+ );
366
+ --jh-icon-color-fill: var(
367
+ --jh-button-icon-color-fill-secondary-active,
368
+ var(--jh-color-content-on-brand-active)
369
+ );
370
+ }
371
+ :host([appearance='secondary'][accessible-disabled='true'][pending])
372
+ button,
373
+ :host([appearance='secondary']) button[aria-disabled='true'],
374
+ :host([appearance='secondary']) a[aria-disabled='true'],
375
+ :host([appearance='secondary'][disabled][pending]) button,
376
+ :host([appearance='secondary']) button[disabled],
377
+ :host([appearance='secondary']) a[disabled] {
378
+ background-color: var(
379
+ --jh-button-color-background-secondary-disabled,
380
+ transparent
381
+ );
382
+ color: var(
383
+ --jh-button-label-color-text-secondary-disabled,
384
+ var(--jh-color-content-brand-enabled)
385
+ );
386
+ --button-border-color: var(
387
+ --jh-button-color-border-secondary-disabled,
388
+ var(--jh-border-action-color)
389
+ );
390
+ --jh-icon-color-fill: var(
391
+ --jh-button-icon-color-fill-secondary-disabled,
392
+ var(--jh-color-content-brand-enabled)
393
+ );
394
+ }
395
+ /* appearance='tertiary' */
396
+ :host([appearance='tertiary']) button,
397
+ :host([appearance='tertiary']) a {
398
+ background-color: var(
399
+ --jh-button-color-background-tertiary-enabled,
400
+ transparent
401
+ );
402
+ color: var(
403
+ --jh-button-label-color-text-tertiary-enabled,
404
+ var(--jh-color-content-brand-enabled)
405
+ );
406
+ --button-border-color: var(
407
+ --jh-button-color-border-tertiary-enabled,
408
+ transparent
409
+ );
410
+ --jh-icon-color-fill: var(
411
+ --jh-button-icon-color-fill-tertiary-enabled,
412
+ var(--jh-color-content-brand-enabled)
413
+ );
414
+ }
415
+ :host([appearance='tertiary']) button:focus-visible,
416
+ :host([appearance='tertiary']) a:focus-visible {
417
+ background-color: var(
418
+ --jh-button-color-background-tertiary-focus,
419
+ var(--jh-color-content-brand-hover)
420
+ );
421
+ color: var(
422
+ --jh-button-label-color-text-tertiary-focus,
423
+ var(--jh-color-content-on-brand-hover)
424
+ );
425
+ --button-border-color: var(
426
+ --jh-button-color-border-tertiary-focus,
427
+ transparent
428
+ );
429
+ --jh-icon-color-fill: var(
430
+ --jh-button-icon-color-fill-tertiary-focus,
431
+ var(--jh-color-content-on-brand-hover)
432
+ );
433
+ }
434
+ :host([appearance='tertiary']) button:hover,
435
+ :host([appearance='tertiary']) a:hover {
436
+ background-color: var(
437
+ --jh-button-color-background-tertiary-hover,
438
+ var(--jh-color-content-brand-hover)
439
+ );
440
+ color: var(
441
+ --jh-button-label-color-text-tertiary-hover,
442
+ var(--jh-color-content-on-brand-hover)
443
+ );
444
+ --button-border-color: var(
445
+ --jh-button-color-border-tertiary-hover,
446
+ transparent
447
+ );
448
+ --jh-icon-color-fill: var(
449
+ --jh-button-icon-color-fill-tertiary-hover,
450
+ var(--jh-color-content-on-brand-hover)
451
+ );
452
+ }
453
+ :host([appearance='tertiary']) button:active,
454
+ :host([appearance='tertiary']) a:active {
455
+ background-color: var(
456
+ --jh-button-color-background-tertiary-active,
457
+ var(--jh-color-content-brand-active)
458
+ );
459
+ color: var(
460
+ --jh-button-label-color-text-tertiary-active,
461
+ var(--jh-color-content-on-brand-active)
462
+ );
463
+ --button-border-color: var(
464
+ --jh-button-color-border-tertiary-active,
465
+ transparent
466
+ );
467
+ --jh-icon-color-fill: var(
468
+ --jh-button-icon-color-fill-tertiary-active,
469
+ var(--jh-color-content-on-brand-active)
470
+ );
471
+ }
472
+ :host([appearance='tertiary'][accessible-disabled='true'][pending])
473
+ button,
474
+ :host([appearance='tertiary']) button[aria-disabled='true'],
475
+ :host([appearance='tertiary']) a[aria-disabled='true'],
476
+ :host([appearance='tertiary'][disabled][pending]) button,
477
+ :host([appearance='tertiary']) button[disabled],
478
+ :host([appearance='tertiary']) a[disabled] {
479
+ background-color: var(
480
+ --jh-button-color-background-tertiary-disabled,
481
+ transparent
482
+ );
483
+ color: var(
484
+ --jh-button-label-color-text-tertiary-disabled,
485
+ var(--jh-color-content-brand-enabled)
486
+ );
487
+ --button-border-color: var(
488
+ --jh-button-color-border-tertiary-disabled,
489
+ transparent
490
+ );
491
+ }
492
+ :host([appearance='tertiary']) button[aria-disabled='true'],
493
+ :host([appearance='tertiary']) a[aria-disabled='true'],
494
+ :host([appearance='tertiary']) button[disabled],
495
+ :host([appearance='tertiary']) a[disabled] {
496
+ --jh-icon-color-fill: var(
497
+ --jh-button-icon-color-fill-tertiary-disabled,
498
+ var(--jh-color-content-brand-enabled)
499
+ );
500
+ }
501
+ /* appearance='danger' */
502
+ :host([appearance='danger']) button,
503
+ :host([appearance='danger']) a {
504
+ background-color: var(
505
+ --jh-button-color-background-danger-enabled,
506
+ var(--jh-color-content-negative-enabled)
507
+ );
508
+ color: var(
509
+ --jh-button-label-color-text-danger-enabled,
510
+ var(--jh-color-content-on-negative-enabled)
511
+ );
512
+ --button-border-color: var(
513
+ --jh-button-color-border-danger-enabled,
514
+ transparent
515
+ );
516
+ --jh-icon-color-fill: var(
517
+ --jh-button-icon-color-fill-danger-enabled,
518
+ var(--jh-color-content-on-negative-enabled)
519
+ );
520
+ }
521
+ :host([appearance='danger']) button:focus-visible,
522
+ :host([appearance='danger']) a:focus-visible {
523
+ background-color: var(
524
+ --jh-button-color-background-danger-focus,
525
+ var(--jh-color-content-negative-hover)
526
+ );
527
+ color: var(
528
+ --jh-button-label-color-text-danger-focus,
529
+ var(--jh-color-content-on-negative-hover)
530
+ );
531
+ --button-border-color: var(
532
+ --jh-button-color-border-danger-focus,
533
+ transparent
534
+ );
535
+ --jh-icon-color-fill: var(
536
+ --jh-button-icon-color-fill-danger-focus,
537
+ var(--jh-color-content-on-negative-hover)
538
+ );
539
+ }
540
+ :host([appearance='danger']) button:hover,
541
+ :host([appearance='danger']) a:hover {
542
+ background-color: var(
543
+ --jh-button-color-background-danger-hover,
544
+ var(--jh-color-content-negative-hover)
545
+ );
546
+ color: var(
547
+ --jh-button-label-color-text-danger-hover,
548
+ var(--jh-color-content-on-negative-hover)
549
+ );
550
+ --button-border-color: var(
551
+ --jh-button-color-border-danger-hover,
552
+ transparent
553
+ );
554
+ --jh-icon-color-fill: var(
555
+ --jh-button-icon-color-fill-danger-hover,
556
+ var(--jh-color-content-on-negative-hover)
557
+ );
558
+ }
559
+ :host([appearance='danger']) button:active,
560
+ :host([appearance='danger']) a:active {
561
+ background-color: var(
562
+ --jh-button-color-background-danger-active,
563
+ var(--jh-color-content-negative-active)
564
+ );
565
+ color: var(
566
+ --jh-button-label-color-text-danger-active,
567
+ var(--jh-color-content-on-negative-active)
568
+ );
569
+ --button-border-color: var(
570
+ --jh-button-color-border-danger-active,
571
+ transparent
572
+ );
573
+ --jh-icon-color-fill: var(
574
+ --jh-button-icon-color-fill-danger-active,
575
+ var(--jh-color-content-on-negative-active)
576
+ );
577
+ }
578
+ :host([appearance='danger'][accessible-disabled='true'][pending]) button,
579
+ :host([appearance='danger']) button[aria-disabled='true'],
580
+ :host([appearance='danger']) a[aria-disabled='true'],
581
+ :host([appearance='danger'][disabled][pending]) button,
582
+ :host([appearance='danger']) button[disabled],
583
+ :host([appearance='danger']) a[disabled] {
584
+ background-color: var(
585
+ --jh-button-color-background-danger-disabled,
586
+ var(--jh-color-content-negative-enabled)
587
+ );
588
+ color: var(
589
+ --jh-button-label-color-text-danger-disabled,
590
+ var(--jh-color-content-on-negative-enabled)
591
+ );
592
+ --button-border-color: var(
593
+ --jh-button-color-border-danger-disabled,
594
+ transparent
595
+ );
596
+ --jh-icon-color-fill: var(
597
+ --jh-button-icon-color-fill-danger-disabled,
598
+ var(--jh-color-content-on-negative-enabled)
599
+ );
600
+ }
601
+ /* additional disabled/aria-disabled/pending styling */
602
+ :host([accessible-disabled='true'][pending]) button,
603
+ button[aria-disabled='true'],
604
+ a[aria-disabled='true'],
605
+ :host([disabled][pending]) button,
606
+ button[disabled],
607
+ a[disabled] {
608
+ opacity: var(--jh-button-opacity-disabled, var(--jh-opacity-disabled));
609
+ }
610
+ /* additional focus styling */
611
+ :host([accessible-disabled='true']) button:focus-visible,
612
+ :host([accessible-disabled='true']) a:focus-visible,
613
+ :host([pending]) button:focus-visible,
614
+ :host([pending]) a:focus-visible {
615
+ outline: none;
616
+ }
617
+ /* pending styling */
618
+ :host([pending]) button,
619
+ :host([pending]) a {
620
+ width: var(--populated-button-width);
621
+ }
622
+ :host([pending][appearance='primary']) button,
623
+ :host([pending][appearance='primary']) a {
624
+ background-color: var(
625
+ --jh-button-color-background-primary-pending,
626
+ var(--jh-color-content-brand-enabled)
627
+ );
628
+ --button-border-color: var(
629
+ --jh-button-color-border-primary-pending,
630
+ transparent
631
+ );
632
+ }
633
+ :host([pending][appearance='primary']) jh-progress {
634
+ --jh-progress-indicator-color: var(
635
+ --jh-button-progress-color-border-primary-pending,
636
+ var(--jh-color-content-on-brand-enabled)
637
+ );
638
+ }
639
+ :host([pending][appearance='secondary']) button,
640
+ :host([pending][appearance='secondary']) a {
641
+ background-color: var(
642
+ --jh-button-color-background-secondary-pending,
643
+ transparent
644
+ );
645
+ --button-border-color: var(
646
+ --jh-button-color-border-secondary-pending,
647
+ var(--jh-border-action-color)
648
+ );
649
+ }
650
+ :host([pending][appearance='secondary']) jh-progress {
651
+ --jh-progress-indicator-color: var(
652
+ --jh-button-progress-color-border-secondary-pending,
653
+ var(--jh-color-content-brand-enabled)
654
+ );
655
+ }
656
+ :host([pending][appearance='tertiary']) button,
657
+ :host([pending][appearance='tertiary']) a {
658
+ background-color: var(
659
+ --jh-button-color-background-tertiary-pending,
660
+ transparent
661
+ );
662
+ --button-border-color: var(
663
+ --jh-button-color-border-tertiary-pending,
664
+ transparent
665
+ );
666
+ }
667
+ :host([pending][appearance='tertiary']) jh-progress {
668
+ --jh-progress-indicator-color: var(
669
+ --jh-button-progress-color-border-tertiary-pending,
670
+ var(--jh-color-content-brand-enabled)
671
+ );
672
+ }
673
+ :host([pending][appearance='danger']) button,
674
+ :host([pending][appearance='danger']) a {
675
+ background-color: var(
676
+ --jh-button-color-background-danger-pending,
677
+ var(--jh-color-content-negative-enabled)
678
+ );
679
+ --button-border-color: var(
680
+ --jh-button-color-border-danger-pending,
681
+ transparent
682
+ );
683
+ }
684
+ :host([pending][appearance='danger']) jh-progress {
685
+ --jh-progress-indicator-color: var(
686
+ --jh-button-progress-color-border-danger-pending,
687
+ var(--jh-color-content-on-negative-enabled)
688
+ );
689
+ }
690
+ /* Icon-related Type option styling */
691
+ :host([icon-position='before'][label]) ::slotted(*) {
692
+ margin-right: var(--jh-dimension-200);
693
+ }
694
+ :host([icon-position='after'][label]) ::slotted(*) {
695
+ margin-left: var(--jh-dimension-200);
696
+ }
697
+ :host([icon-position='after']) .content-wrapper {
698
+ flex-direction: row-reverse;
699
+ }
700
+ /* Icon only styling */
701
+ :host(:not([label])[size='small']) button,
702
+ :host(:not([label])[size='small']) a {
703
+ width: var(--jh-button-size, var(--jh-dimension-1000));
704
+ }
705
+ :host(:not([label])[size='medium']) button,
706
+ :host(:not([label])[size='medium']) a {
707
+ width: var(--jh-button-size, var(--jh-dimension-1200));
708
+ }
709
+ :host(:not([label])[size='large']) button,
710
+ :host(:not([label])[size='large']) a {
711
+ width: var(--jh-button-size, var(--jh-dimension-1400));
712
+ }
713
+ :host(:not([label])) button,
714
+ :host(:not([label])) a {
715
+ padding: 0;
716
+ }
717
+ /* Block styling */
718
+ :host([block]) {
719
+ display: block;
720
+ text-align: center;
721
+ }
722
+ :host(:not([label])[block]) button,
723
+ :host(:not([label])[block]) a,
724
+ :host([block]) button,
725
+ :host([block]) a {
726
+ width: 100%;
727
+ }
728
+ `;
729
+ }
730
+
731
+ static get properties() {
732
+ return {
733
+ /** Sets an `aria-disabled` to signify to screen readers that the disabled button should remain perceivable while disabled. */
734
+ accessibleDisabled: {
735
+ type: String,
736
+ attribute: 'accessible-disabled',
737
+ reflect: true,
738
+ },
739
+ /** Sets an `aria-label` to assist screen reader users when no visible label is present. */
740
+ accessibleLabel: {
741
+ type: String,
742
+ attribute: 'accessible-label',
743
+ },
744
+ /** Determines the button color. */
745
+ appearance: {
746
+ type: String,
747
+ reflect: true,
748
+ },
749
+ /** Sets the button width to its parent container. */
750
+ block: {
751
+ type: Boolean,
752
+ },
753
+ /** Disables the button and prevents all user interactions. May cause button to be ignored by assistive technologies(AT). See `accessible-disabled` attribute if the button should remain perceivable to AT. */
754
+ disabled: {
755
+ type: Boolean,
756
+ reflect: true,
757
+ },
758
+ /** Sets the link's destination. */
759
+ href: {
760
+ type: String,
761
+ },
762
+ /** Sets location of icon in relation to the label. */
763
+ iconPosition: {
764
+ type: String,
765
+ attribute: 'icon-position',
766
+ reflect: true,
767
+ },
768
+ /** Displays a progress indicator. */
769
+ pending: {
770
+ type: Boolean,
771
+ reflect: true,
772
+ },
773
+ /** Describes the intent of the button.*/
774
+ label: {
775
+ type: String,
776
+ },
777
+ /** Sets the name of the button data when submitted in a form. */
778
+ name: {
779
+ type: String,
780
+ },
781
+ /** Sets the size of the button. */
782
+ size: {
783
+ type: String,
784
+ reflect: true,
785
+ },
786
+ /** Sets button `type='submit'`. Button defaults to `type='button'`. */
787
+ submit: {
788
+ type: Boolean,
789
+ },
790
+ /** Specifies where to display the linked URL set by the `href` property. */
791
+ target: {
792
+ type: String,
793
+ },
794
+ /** Sets the value of the button. */
795
+ value: {
796
+ type: String,
797
+ },
798
+ };
799
+ }
800
+
801
+ constructor() {
802
+ super();
803
+ /** @type {ElementInternals} */
804
+ this.#internals = this.attachInternals();
805
+ /** @type {ElementInternals} */
806
+ this.#internals.form;
807
+ /** @type {'true'|'false'} */
808
+ this.accessibleDisabled = null;
809
+ /** @type {?string} */
810
+ this.accessibleLabel = null;
811
+ /** @type {'primary'|'secondary'|'tertiary'|'danger'} */
812
+ this.appearance = 'secondary';
813
+ /** @type {boolean} */
814
+ this.block = false;
815
+ /** @type {boolean} */
816
+ this.disabled = false;
817
+ /** @type {?string} */
818
+ this.href = null;
819
+ /** @type {'before'|'after'} */
820
+ this.iconPosition = 'before';
821
+ /** @type {?boolean} */
822
+ this.pending = false;
823
+ /** @type {?string} */
824
+ this.label = null;
825
+ /** @type {?string} */
826
+ this.name = null;
827
+ /** @type {'small'|'medium'|'large'} */
828
+ this.size = 'medium';
829
+ /** @type {?boolean} */
830
+ this.submit = false;
831
+ /** @type {'_blank'|'_self'|'_parent'|'_top'} */
832
+ this.target = null;
833
+ /** @type {?string} */
834
+ this.value = null;
835
+
836
+ this.addEventListener('click', this.#onClick);
837
+ this.addEventListener('keydown', this.#handleKeydown);
838
+ }
839
+
840
+ /** @type {?string} */
841
+ get value() {
842
+ return this.#value;
843
+ }
844
+
845
+ set value(newValue) {
846
+ const oldValue = this.#value;
847
+ if (newValue !== oldValue) {
848
+ this.#value = newValue;
849
+ this.#internals.setFormValue(newValue);
850
+ }
851
+ this.requestUpdate('value', oldValue);
852
+ }
853
+
854
+ firstUpdated() {
855
+ this.#cacheButtonDimensions();
856
+ new ResizeObserver(this.#cacheButtonDimensions.bind(this)).observe(this);
857
+ }
858
+
859
+ #cacheButtonDimensions() {
860
+ const { width } = this.getBoundingClientRect();
861
+
862
+ this.style.setProperty('--populated-button-width', `${width}px`);
863
+ }
864
+
865
+ formDisabledCallback(disabled) {
866
+ this.disabled = disabled;
867
+ }
868
+
869
+ #onClick(event) {
870
+ //If I'm a submit button in a form and I'm not disabled submit the form
871
+ if (this.submit && this.#internals.form && !this.disabled) {
872
+ this.#internals.form.requestSubmit();
873
+ }
874
+ }
875
+
876
+ //disable button when accessible-disabled='true'
877
+ #handleKeydown(e) {
878
+ if (
879
+ (e.code === 'Space' || e.code === 'Enter') &&
880
+ (this.accessibleDisabled === 'true' || this.pending)
881
+ ) {
882
+ e.preventDefault();
883
+ }
884
+ }
885
+
886
+ #handleSlotChange() {
887
+ this.firstElementChild.setAttribute('aria-hidden', 'true');
888
+ this.firstElementChild.setAttribute('size', 'medium');
889
+ }
890
+
891
+ #renderButtonContent(pending, label) {
892
+ let buttonContent;
893
+ let buttonLabel;
894
+
895
+ if (label) {
896
+ buttonLabel = html`<span>${label}</span>`;
897
+ }
898
+
899
+ if (pending && !this.disabled) {
900
+ buttonContent = html`
901
+ <jh-progress type="circular" indeterminate></jh-progress>
902
+ `;
903
+ } else {
904
+ buttonContent = html`
905
+ <slot
906
+ name="jh-button-icon"
907
+ @slotchange=${this.#handleSlotChange}
908
+ ></slot>
909
+ ${buttonLabel}
910
+ `;
911
+ }
912
+
913
+ return html` <span class="content-wrapper">${buttonContent}</span> `;
914
+ }
915
+
916
+ render() {
917
+ const buttonContent = this.#renderButtonContent(this.pending, this.label);
918
+ let ariaDisabled;
919
+
920
+ if (this.accessibleDisabled !== 'false') {
921
+ ariaDisabled = this.accessibleDisabled;
922
+ }
923
+
924
+ if (this.href) {
925
+ return html`
926
+ <a
927
+ tabindex="0"
928
+ aria-disabled=${ifDefined(ariaDisabled)}
929
+ aria-label=${ifDefined(this.accessibleLabel)}
930
+ ?disabled=${this.disabled}
931
+ href=${ifDefined(!this.disabled ? this.href : null)}
932
+ target=${ifDefined(!this.disabled ? this.target : null)}
933
+ >
934
+ ${buttonContent}
935
+ </a>
936
+ `;
937
+ } else {
938
+ return html`
939
+ <button
940
+ tabindex="0"
941
+ aria-disabled=${ifDefined(ariaDisabled)}
942
+ aria-label=${ifDefined(this.accessibleLabel)}
943
+ ?disabled=${this.disabled}
944
+ type=${this.submit ? 'submit' : 'button'}
945
+ >
946
+ ${buttonContent}
947
+ </button>
948
+ `;
949
+ }
950
+ }
951
+ }
952
+
953
+ customElements.define('jh-button', JhButton);