@kubex/zinc 1.1.81 → 1.1.82

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.
@@ -323,6 +323,22 @@ A complete example showing product content management with translations.
323
323
  </div>
324
324
  ```
325
325
 
326
+ ### Help Text
327
+
328
+ Use the `help-text` attribute to describe how the field should be filled in. It sits below the field and applies to
329
+ every language, so it is the place to explain a convention the translator needs to follow. For help text containing
330
+ HTML, use the `help-text` slot instead.
331
+
332
+ ```html:preview
333
+ <zn-translations
334
+ label="Confirmation headline"
335
+ help-text="Keep this under 60 characters so it does not wrap on mobile."></zn-translations>
336
+ <br />
337
+ <zn-translations label="Footer">
338
+ <div slot="help-text">Shown on <strong>every</strong> page of the checkout.</div>
339
+ </zn-translations>
340
+ ```
341
+
326
342
  ### Slash Menu Quick Insertions
327
343
 
328
344
  {% raw %}
@@ -360,6 +376,7 @@ way `Enter` otherwise would.
360
376
  | `name` | `string` | `''` | Form field name for submission |
361
377
  | `value` | `string` | `'{"en":""}'` | JSON string of translations |
362
378
  | `label` | `string` | `''` | Label displayed above the component |
379
+ | `help-text` | `string` | `''` | Text shown below the field, describing how to fill it in |
363
380
  | `disabled` | `boolean` | `false` | Disables editing of all translations |
364
381
  | `required` | `boolean` | `false` | Makes the field required for form validation |
365
382
  | `flush` | `boolean` | `false` | Removes padding for compact layout |
@@ -379,10 +396,11 @@ way `Enter` otherwise would.
379
396
 
380
397
  ## Slots
381
398
 
382
- | Slot | Description |
383
- |-----------|------------------------------------------------------------------|
384
- | `label` | Alternative to the `label` attribute for rich HTML content |
385
- | `expand` | Action button displayed in the navbar (e.g., translate button) |
399
+ | Slot | Description |
400
+ |-------------|------------------------------------------------------------------|
401
+ | `label` | Alternative to the `label` attribute for rich HTML content |
402
+ | `expand` | Action button displayed in the navbar (e.g., translate button) |
403
+ | `help-text` | Alternative to the `help-text` attribute for rich HTML content |
386
404
 
387
405
  ## Methods
388
406
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubex/zinc",
3
- "version": "1.1.81",
3
+ "version": "1.1.82",
4
4
  "description": "A collection of web components for building web applications based off of @shoelace-style/Shoelace",
5
5
  "keywords": [
6
6
  "web components",
@@ -33,11 +33,17 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
33
33
  };
34
34
 
35
35
  private readonly formControlController: FormControlController = new FormControlController(this);
36
- private readonly hasSlotController = new HasSlotController(this, 'label', 'expand');
36
+ private readonly hasSlotController = new HasSlotController(this, 'label', 'expand', 'help-text');
37
37
 
38
38
  @property() name = '';
39
39
  @property() value = '{"en":""}';
40
40
  @property() label: string = '';
41
+
42
+ /**
43
+ * Text shown below the field, describing how to fill it in. Applies to every language. If you need HTML, use the
44
+ * `help-text` slot instead.
45
+ */
46
+ @property({attribute: 'help-text'}) helpText: string = '';
41
47
  @property({type: Boolean, reflect: true}) disabled = false;
42
48
  @property({type: Boolean, reflect: true}) required = false;
43
49
  @property({type: Boolean, reflect: true}) flush = false;
@@ -356,6 +362,8 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
356
362
  const hasLabelSlot = this.hasSlotController.test('label');
357
363
  const hasLabel = this.label ? true : hasLabelSlot;
358
364
  const hasExpandSlot = this.hasSlotController.test('expand');
365
+ const hasHelpTextSlot = this.hasSlotController.test('help-text');
366
+ const hasHelpText = this.helpText ? true : hasHelpTextSlot;
359
367
  const hasMultipleLanguages = Object.keys(this.languages).length > 1;
360
368
  const showActions = !this.grouped && (hasMultipleLanguages || hasExpandSlot);
361
369
 
@@ -368,6 +376,7 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
368
376
  'form-control': true,
369
377
  'form-control--medium': true,
370
378
  'form-control--has-label': hasLabel,
379
+ 'form-control--has-help-text': hasHelpText,
371
380
  })}"
372
381
  @keydown="${this.handleKeyDown}">
373
382
  <div class="translations__header">
@@ -443,6 +452,12 @@ export default class ZnTranslations extends ZincElement implements ZincFormContr
443
452
  ></zn-inline-edit>
444
453
  `)}
445
454
  </div>
455
+
456
+ ${hasHelpText ? html`
457
+ <div part="form-control-help-text" class="form-control__help-text" aria-hidden="false">
458
+ <slot name="help-text">${this.helpText}</slot>
459
+ </div>
460
+ ` : nothing}
446
461
  </div>
447
462
  `;
448
463
  }
@@ -50,6 +50,48 @@ describe('<zn-translations>', () => {
50
50
  await expect(JSON.parse(el.value)).to.deep.equal({'en': 'Hello World'});
51
51
  });
52
52
 
53
+ describe('help text', () => {
54
+ function helpTextOf(el: ZnTranslations) {
55
+ return el.shadowRoot!.querySelector<HTMLElement>('[part="form-control-help-text"]');
56
+ }
57
+
58
+ it('is not rendered when unset', async () => {
59
+ const el = await fixture<ZnTranslations>(html`<zn-translations></zn-translations>`);
60
+ await el.updateComplete;
61
+
62
+ expect(helpTextOf(el)).to.not.exist;
63
+ });
64
+
65
+ it('renders the help-text attribute below the field', async () => {
66
+ const el = await fixture<ZnTranslations>(html`
67
+ <zn-translations help-text="Type / to insert a replacement"></zn-translations>`);
68
+ await el.updateComplete;
69
+
70
+ expect(helpTextOf(el)?.textContent?.trim()).to.equal('Type / to insert a replacement');
71
+ });
72
+
73
+ it('renders the help-text slot', async () => {
74
+ const el = await fixture<ZnTranslations>(html`
75
+ <zn-translations>
76
+ <div slot="help-text">Type <strong>/</strong> to insert</div>
77
+ </zn-translations>`);
78
+ await el.updateComplete;
79
+
80
+ expect(helpTextOf(el), 'a slotted help text should still render the wrapper').to.exist;
81
+ });
82
+
83
+ it('shows the same help text after switching language', async () => {
84
+ const el = await fixture<ZnTranslations>(html`
85
+ <zn-translations help-text="Type / to insert a replacement"></zn-translations>`);
86
+ el.languages = {'en': 'EN', 'fr': 'FR'};
87
+ el.values = {'en': '', 'fr': ''};
88
+ el.setActiveLanguage('fr');
89
+ await el.updateComplete;
90
+
91
+ expect(helpTextOf(el)?.textContent?.trim()).to.equal('Type / to insert a replacement');
92
+ });
93
+ });
94
+
53
95
  describe('slash menu', () => {
54
96
  /** Puts the active language's field into edit mode, the way clicking it does. */
55
97
  async function textareaOf(el: ZnTranslations) {