lightning-base-components 1.22.2-alpha → 1.22.3-alpha

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 (137) hide show
  1. package/README.md +2 -0
  2. package/metadata/raptor.json +31 -2
  3. package/package.json +12 -1
  4. package/scopedImports/@salesforce-label-LightningRecordPicker.actionIconAlternativeText.js +1 -0
  5. package/src/lightning/ariaObserver/ariaObserver.js +1 -1
  6. package/src/lightning/baseCombobox/baseCombobox.html +1 -1
  7. package/src/lightning/baseCombobox/baseCombobox.js +1 -0
  8. package/src/lightning/baseCombobox/input-text.slds.css +6 -7
  9. package/src/lightning/baseComboboxItem/card.lbc.native.css +1 -0
  10. package/src/lightning/baseComboboxItem/inline.lbc.native.css +1 -0
  11. package/src/lightning/buttonIcon/button-icon.slds.css +5 -5
  12. package/src/lightning/buttonIconStateful/button-icon.slds.css +5 -5
  13. package/src/lightning/buttonMenu/button-icon.slds.css +5 -5
  14. package/src/lightning/calendar/calendar.slds.css +10 -13
  15. package/src/lightning/checkboxGroup/checkboxGroup.js +21 -10
  16. package/src/lightning/checkboxGroup/checkboxGroup.js-meta.xml +3 -0
  17. package/src/lightning/colorPickerCustom/input-text.slds.css +6 -7
  18. package/src/lightning/combobox/form-element.slds.css +1 -1
  19. package/src/lightning/datatable/__docs__/datatable.md +10 -5
  20. package/src/lightning/datatable/columnResizer.js +3 -2
  21. package/src/lightning/datatable/columnWidthManager.js +16 -10
  22. package/src/lightning/datatable/datatable.js +101 -38
  23. package/src/lightning/datatable/infiniteLoading.js +8 -20
  24. package/src/lightning/datatable/inlineEdit.js +11 -6
  25. package/src/lightning/datatable/keyboard.js +58 -55
  26. package/src/lightning/datatable/resizeObserver.js +10 -5
  27. package/src/lightning/datatable/rows.js +1 -2
  28. package/src/lightning/datatable/rowsInlining.js +5 -4
  29. package/src/lightning/datatable/state.js +1 -2
  30. package/src/lightning/datatable/templates/div/div.html +150 -43
  31. package/src/lightning/datatable/templates/div/div.lbc.synthetic.css +8 -7
  32. package/src/lightning/datatable/templates/table/table.html +153 -46
  33. package/src/lightning/datatable/utils.js +10 -4
  34. package/src/lightning/datatable/virtualization.js +6 -4
  35. package/src/lightning/datatable/wrapText.js +16 -15
  36. package/src/lightning/datepicker/form-element.slds.css +1 -1
  37. package/src/lightning/datepicker/input-text.slds.css +6 -7
  38. package/src/lightning/datetimepicker/form-element.slds.css +1 -1
  39. package/src/lightning/datetimepicker/input-text.slds.css +6 -7
  40. package/src/lightning/dualListbox/form-element.slds.css +1 -1
  41. package/src/lightning/groupedCombobox/form-element.slds.css +1 -1
  42. package/src/lightning/groupedCombobox/input-text.slds.css +6 -7
  43. package/src/lightning/helptext/button-icon.slds.css +5 -5
  44. package/src/lightning/helptext/form-element.slds.css +1 -1
  45. package/src/lightning/input/form-element.slds.css +1 -1
  46. package/src/lightning/input/input.html +0 -1
  47. package/src/lightning/inputAddress/form-element.slds.css +1 -1
  48. package/src/lightning/inputAddress/input-text.slds.css +6 -7
  49. package/src/lightning/inputLocation/form-element.slds.css +1 -1
  50. package/src/lightning/inputLocation/input-text.slds.css +6 -7
  51. package/src/lightning/inputName/form-element.slds.css +1 -1
  52. package/src/lightning/inputName/input-text.slds.css +6 -7
  53. package/src/lightning/lookupAddress/form-element.slds.css +1 -1
  54. package/src/lightning/modal/__docs__/modal.md +2 -0
  55. package/src/lightning/modalBase/modalBase.html +2 -0
  56. package/src/lightning/modalBase/modalBase.js +30 -31
  57. package/src/lightning/modalBody/modalBody.html +1 -0
  58. package/src/lightning/modalBody/modalBody.js +3 -0
  59. package/src/lightning/modalFooter/modalFooter.html +5 -1
  60. package/src/lightning/modalFooter/modalFooter.js +3 -0
  61. package/src/lightning/modalHeader/modalHeader.html +4 -1
  62. package/src/lightning/modalHeader/modalHeader.js +3 -0
  63. package/src/lightning/overlayManager/overlayManager.js +1 -1
  64. package/src/lightning/positionLibrary/elementProxy.js +13 -6
  65. package/src/lightning/positionLibrary/util.js +20 -2
  66. package/src/lightning/primitiveCellActions/primitiveCellActions.html +1 -0
  67. package/src/lightning/primitiveCellActions/primitiveCellActions.js +3 -5
  68. package/src/lightning/primitiveCellButton/primitiveCellButton.html +2 -0
  69. package/src/lightning/primitiveCellButton/primitiveCellButton.js +3 -5
  70. package/src/lightning/primitiveCellCheckbox/checkbox.html +3 -2
  71. package/src/lightning/primitiveCellCheckbox/primitiveCellCheckbox.js +6 -3
  72. package/src/lightning/primitiveCellCheckbox/radio.html +5 -4
  73. package/src/lightning/primitiveCellEditableButton/primitiveCellEditableButton.html +1 -1
  74. package/src/lightning/primitiveCellEditableButton/primitiveCellEditableButton.js +1 -1
  75. package/src/lightning/primitiveCellFactory/bareCustomCell.html +1 -0
  76. package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +1 -0
  77. package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +4 -6
  78. package/src/lightning/primitiveColorpickerButton/color-picker-button.slds.css +1 -1
  79. package/src/lightning/primitiveColumnSorter/primitiveColumnSorter.html +1 -0
  80. package/src/lightning/primitiveColumnSorter/primitiveColumnSorter.js +1 -1
  81. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +3 -1
  82. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +3 -3
  83. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.html +1 -0
  84. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +1 -3
  85. package/src/lightning/primitiveDatatableTooltip/primitiveDatatableTooltip.html +1 -0
  86. package/src/lightning/primitiveDatatableTooltip/primitiveDatatableTooltip.js +1 -1
  87. package/src/lightning/primitiveDatatableTooltipBubble/primitiveDatatableTooltipBubble.html +1 -1
  88. package/src/lightning/primitiveDatatableTooltipBubble/primitiveDatatableTooltipBubble.js +1 -1
  89. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.html +1 -0
  90. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +2 -4
  91. package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +8 -3
  92. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +43 -13
  93. package/src/lightning/primitiveHeaderFactory/selectableHeader.html +3 -2
  94. package/src/lightning/primitiveHeaderFactory/sortableHeader.html +8 -3
  95. package/src/lightning/primitiveHeaderFactory/sortingMenuHeader.html +1 -1
  96. package/src/lightning/primitiveIcon/primitiveIcon.css +0 -1
  97. package/src/lightning/primitiveInputCheckbox/form-element.slds.css +1 -1
  98. package/src/lightning/primitiveInputCheckboxButton/form-element.slds.css +1 -1
  99. package/src/lightning/primitiveInputColor/form-element.slds.css +1 -1
  100. package/src/lightning/primitiveInputColor/input-text.slds.css +6 -7
  101. package/src/lightning/primitiveInputFile/form-element.slds.css +1 -1
  102. package/src/lightning/primitiveInputSimple/form-element.slds.css +1 -1
  103. package/src/lightning/primitiveInputSimple/input-text.slds.css +6 -7
  104. package/src/lightning/primitiveInputToggle/form-element.slds.css +1 -1
  105. package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.html +4 -2
  106. package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.js +2 -2
  107. package/src/lightning/primitiveTreegridCellToggle/primitiveTreegridCellToggle.html +1 -1
  108. package/src/lightning/primitiveTreegridCellToggle/primitiveTreegridCellToggle.js +1 -1
  109. package/src/lightning/progressIndicator/progressIndicator.css +1 -1
  110. package/src/lightning/progressIndicator/progressIndicator.js +14 -6
  111. package/src/lightning/progressIndicator/progressIndicator.js-meta.xml +3 -0
  112. package/src/lightning/progressIndicator/progressIndicator.lbc.native.css +2 -0
  113. package/src/lightning/progressStep/__examples__/basic/basic.html +11 -0
  114. package/src/lightning/progressStep/__examples__/basic/basic.js +3 -0
  115. package/src/lightning/progressStep/__examples__/shaded/shaded.html +11 -0
  116. package/src/lightning/progressStep/__examples__/shaded/shaded.js +3 -0
  117. package/src/lightning/progressStep/base.html +2 -1
  118. package/src/lightning/progressStep/progressStep.css +1 -0
  119. package/src/lightning/progressStep/progressStep.js +40 -29
  120. package/src/lightning/progressStep/progressStep.js-meta.xml +3 -0
  121. package/src/lightning/progressStep/progressStep.lbc.native.css +3 -0
  122. package/src/lightning/prompt/form-element.slds.css +1 -1
  123. package/src/lightning/prompt/input-text.slds.css +6 -7
  124. package/src/lightning/radioGroup/form-element.slds.css +1 -1
  125. package/src/lightning/select/form-element.slds.css +1 -1
  126. package/src/lightning/select/select.slds.css +1 -1
  127. package/src/lightning/sldsCommon/sldsCommon.css +1 -1
  128. package/src/lightning/textarea/form-element.slds.css +1 -1
  129. package/src/lightning/tile/mediaTile.css +2 -0
  130. package/src/lightning/tile/standardTile.css +2 -1
  131. package/src/lightning/tile/tile.js +5 -2
  132. package/src/lightning/tile/tile.js-meta.xml +3 -0
  133. package/src/lightning/tile/tile.lbc.native.css +4 -0
  134. package/src/lightning/timepicker/form-element.slds.css +1 -1
  135. package/src/lightning/toast/button-icon.slds.css +5 -5
  136. package/src/lightning/primitiveIcon/primitiveIcon.lbc.synthetic.css +0 -9
  137. /package/src/lightning/tile/{standardTile.lbc.synthetic.css → tile.lbc.synthetic.css} +0 -0
@@ -246,7 +246,7 @@
246
246
  --sds-c-inputtext-text-color: var(--slds-c-inputtext-text-color);
247
247
  --sds-c-inputtext-font-size: var(
248
248
  --slds-c-inputtext-font-size,
249
- var(--slds-g-font-size-base)
249
+ var(--slds-g-font-scale-neg-2)
250
250
  );
251
251
  --sds-c-inputtext-text-color-placeholder: var(
252
252
  --slds-c-inputtext-text-color-placeholder,
@@ -264,7 +264,7 @@
264
264
 
265
265
  display: flex;
266
266
  flex-wrap: wrap;
267
- flex-direction: column;
267
+ align-items: center;
268
268
  }
269
269
  /**
270
270
  * Input Container
@@ -371,10 +371,6 @@
371
371
  --sds-c-inputtext-color-border: var(--slds-g-color-border-disabled-1);
372
372
  --sds-c-inputtext-text-color: var(--slds-g-color-on-disabled-2);
373
373
  }
374
- :host([data-render-mode="shadow"][disabled]) [part='input-text'] {
375
- --sds-c-inputtext-text-color-placeholder:
376
- var(--slds-g-color-on-disabled-2);
377
- }
378
374
  /**
379
375
  * Label
380
376
  *
@@ -388,7 +384,10 @@
388
384
  --slds-c-inputtext-label-color,
389
385
  var(--slds-g-color-on-surface-2)
390
386
  );
391
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
387
+ font-size: var(
388
+ --slds-c-inputtext-label-font-size,
389
+ var(--slds-g-font-scale-neg-3)
390
+ );
392
391
  margin-block-end: var(--slds-g-sizing-1);
393
392
 
394
393
  /* We inline flex to control the spacing between elements and not have to rely on whitespace characters */
@@ -553,19 +553,19 @@ Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
553
553
  --sds-c-button-color-border-disabled: var(--slds-g-color-border-disabled-1);
554
554
  }
555
555
  /* slds-icon interaction states */
556
- :host([data-render-mode="shadow"]) [part~='button-icon']:hover {
556
+ :host([data-render-mode="shadow"]) [part~='button-icon']:not(.slds-is-selected):hover {
557
557
  --slds-c-icon-color-foreground: var(
558
- --slds-c-buttonicon-color-foreground-hover,
558
+ --slds-c-buttonicon-color-foreground-hover,
559
559
  var(--slds-g-color-accent-3)
560
560
  );
561
561
  }
562
- :host([data-render-mode="shadow"]) [part~='button-icon']:focus {
562
+ :host([data-render-mode="shadow"]) [part~='button-icon']:not(.slds-is-selected):focus {
563
563
  --slds-c-icon-color-foreground: var(
564
564
  --slds-c-buttonicon-color-foreground-focus,
565
565
  var(--slds-g-color-accent-3)
566
566
  );
567
567
  }
568
- :host([data-render-mode="shadow"]) [part~='button-icon']:active {
568
+ :host([data-render-mode="shadow"]) [part~='button-icon']:not(.slds-is-selected):active {
569
569
  --slds-c-icon-color-foreground: var(
570
570
  --slds-c-buttonicon-color-foreground-active,
571
571
  var(--slds-g-color-accent-3)
@@ -643,7 +643,7 @@ Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
643
643
 
644
644
  /* Icon */
645
645
  --slds-c-buttonicon-color-foreground: var(--slds-g-color-neutral-base-100);
646
- --slds-c-buttonicon-color-foreground-hover: color-mix(in oklab, var(--slds-g-color-on-surface-inverse-1), transparent 25%);
646
+ --slds-c-buttonicon-color-foreground-hover: var(--slds-g-color-neutral-base-95);
647
647
  --slds-c-buttonicon-color-foreground-focus: var(--slds-g-color-neutral-base-95);
648
648
  --slds-c-buttonicon-color-foreground-active: var(--slds-g-color-neutral-base-90);
649
649
 
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -233,7 +233,6 @@
233
233
  name={name}
234
234
  accesskey={accesskey}
235
235
  aria-label={ariaLabel}
236
- aria-details={ariaDetails}
237
236
  aria-disabled={ariaDisabled}
238
237
  variant={variant}
239
238
  time-style={timeStyle}
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -246,7 +246,7 @@
246
246
  --sds-c-inputtext-text-color: var(--slds-c-inputtext-text-color);
247
247
  --sds-c-inputtext-font-size: var(
248
248
  --slds-c-inputtext-font-size,
249
- var(--slds-g-font-size-base)
249
+ var(--slds-g-font-scale-neg-2)
250
250
  );
251
251
  --sds-c-inputtext-text-color-placeholder: var(
252
252
  --slds-c-inputtext-text-color-placeholder,
@@ -264,7 +264,7 @@
264
264
 
265
265
  display: flex;
266
266
  flex-wrap: wrap;
267
- flex-direction: column;
267
+ align-items: center;
268
268
  }
269
269
  /**
270
270
  * Input Container
@@ -371,10 +371,6 @@
371
371
  --sds-c-inputtext-color-border: var(--slds-g-color-border-disabled-1);
372
372
  --sds-c-inputtext-text-color: var(--slds-g-color-on-disabled-2);
373
373
  }
374
- :host([data-render-mode="shadow"][disabled]) [part='input-text'] {
375
- --sds-c-inputtext-text-color-placeholder:
376
- var(--slds-g-color-on-disabled-2);
377
- }
378
374
  /**
379
375
  * Label
380
376
  *
@@ -388,7 +384,10 @@
388
384
  --slds-c-inputtext-label-color,
389
385
  var(--slds-g-color-on-surface-2)
390
386
  );
391
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
387
+ font-size: var(
388
+ --slds-c-inputtext-label-font-size,
389
+ var(--slds-g-font-scale-neg-3)
390
+ );
392
391
  margin-block-end: var(--slds-g-sizing-1);
393
392
 
394
393
  /* We inline flex to control the spacing between elements and not have to rely on whitespace characters */
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -246,7 +246,7 @@
246
246
  --sds-c-inputtext-text-color: var(--slds-c-inputtext-text-color);
247
247
  --sds-c-inputtext-font-size: var(
248
248
  --slds-c-inputtext-font-size,
249
- var(--slds-g-font-size-base)
249
+ var(--slds-g-font-scale-neg-2)
250
250
  );
251
251
  --sds-c-inputtext-text-color-placeholder: var(
252
252
  --slds-c-inputtext-text-color-placeholder,
@@ -264,7 +264,7 @@
264
264
 
265
265
  display: flex;
266
266
  flex-wrap: wrap;
267
- flex-direction: column;
267
+ align-items: center;
268
268
  }
269
269
  /**
270
270
  * Input Container
@@ -371,10 +371,6 @@
371
371
  --sds-c-inputtext-color-border: var(--slds-g-color-border-disabled-1);
372
372
  --sds-c-inputtext-text-color: var(--slds-g-color-on-disabled-2);
373
373
  }
374
- :host([data-render-mode="shadow"][disabled]) [part='input-text'] {
375
- --sds-c-inputtext-text-color-placeholder:
376
- var(--slds-g-color-on-disabled-2);
377
- }
378
374
  /**
379
375
  * Label
380
376
  *
@@ -388,7 +384,10 @@
388
384
  --slds-c-inputtext-label-color,
389
385
  var(--slds-g-color-on-surface-2)
390
386
  );
391
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
387
+ font-size: var(
388
+ --slds-c-inputtext-label-font-size,
389
+ var(--slds-g-font-scale-neg-3)
390
+ );
392
391
  margin-block-end: var(--slds-g-sizing-1);
393
392
 
394
393
  /* We inline flex to control the spacing between elements and not have to rely on whitespace characters */
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -246,7 +246,7 @@
246
246
  --sds-c-inputtext-text-color: var(--slds-c-inputtext-text-color);
247
247
  --sds-c-inputtext-font-size: var(
248
248
  --slds-c-inputtext-font-size,
249
- var(--slds-g-font-size-base)
249
+ var(--slds-g-font-scale-neg-2)
250
250
  );
251
251
  --sds-c-inputtext-text-color-placeholder: var(
252
252
  --slds-c-inputtext-text-color-placeholder,
@@ -264,7 +264,7 @@
264
264
 
265
265
  display: flex;
266
266
  flex-wrap: wrap;
267
- flex-direction: column;
267
+ align-items: center;
268
268
  }
269
269
  /**
270
270
  * Input Container
@@ -371,10 +371,6 @@
371
371
  --sds-c-inputtext-color-border: var(--slds-g-color-border-disabled-1);
372
372
  --sds-c-inputtext-text-color: var(--slds-g-color-on-disabled-2);
373
373
  }
374
- :host([data-render-mode="shadow"][disabled]) [part='input-text'] {
375
- --sds-c-inputtext-text-color-placeholder:
376
- var(--slds-g-color-on-disabled-2);
377
- }
378
374
  /**
379
375
  * Label
380
376
  *
@@ -388,7 +384,10 @@
388
384
  --slds-c-inputtext-label-color,
389
385
  var(--slds-g-color-on-surface-2)
390
386
  );
391
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
387
+ font-size: var(
388
+ --slds-c-inputtext-label-font-size,
389
+ var(--slds-g-font-scale-neg-3)
390
+ );
392
391
  margin-block-end: var(--slds-g-sizing-1);
393
392
 
394
393
  /* We inline flex to control the spacing between elements and not have to rely on whitespace characters */
@@ -46,7 +46,7 @@
46
46
  hyphens: auto;
47
47
  display: inline-block;
48
48
  color: var(--slds-g-color-on-surface-2);
49
- font-size: var(--slds-s-label-font-size, var(--slds-g-font-scale-neg-2));
49
+ font-size: var(--slds-g-font-scale-neg-3);
50
50
  padding-inline-end: var(--slds-g-spacing-2);
51
51
  padding-block-start: var(--slds-g-spacing-1);
52
52
  margin-block-end: calc(var(--slds-g-spacing-1) / 2);
@@ -411,6 +411,8 @@ Let's see this workflow in action. In this example, we'll create a button (`ligh
411
411
 
412
412
  Because `lightning-navigation` requires you to pass in a `recordId` to construct a page reference, we need to pass the record's data out of `LightningModal`, and then use the methods provided by `lightning-navigation`. With modal's limitations for event bubbling to the Aura layer, we can't just wrap the button or treegrid with `lightning-navigation`. We need to pull that data up to the topmost LWC component, where the `LightningModal` `.open()` is called, for our Aura wrapper to handle the navigation.
413
413
 
414
+ However, in [Aura-based Experience Builder sites](https://developer.salesforce.com/docs/atlas.en-us.communities_dev.meta/communities_dev/communities_dev_basics_templates.htm), the `NavigationMixin` event can reach the Aura layer without being affected by the modal's limitations.
415
+
414
416
  So, we `import` the `lightning-navigation` component into the topmost LWC component that sits within the Aura layer by passing the data through `LightningModal`'s close method, `this.close({ data })`. Then the parent LWC component invokes the methods provided by `lightning-navigation`, which handles the navigation away from the page after the modal exits. From a UX perspective, this also lets us close the modal first, since `lightning-navigation` takes the user away from the current page.
415
417
 
416
418
  Note that this sample code isn't fully functional. We're only showing the relevant code that makes the `lightning-navigation` use case work with `LightningModal`.
@@ -18,6 +18,8 @@
18
18
  onprivatemodalfooterregister={handleFooterRegister}
19
19
  onprivateclose={handlePrivateClose}
20
20
  onprivatedisableclosebutton={handlePrivateDisableCloseButton}
21
+ onfocusin={handleModalBaseFocusin}
22
+ onprivatelightningmodallastfocus={handleLastFocusedElem}
21
23
  data-modal
22
24
  >
23
25
  <template if:true={showAriaDescribedBy}>
@@ -19,7 +19,7 @@ import {
19
19
  import closeButtonAltText from '@salesforce/label/LightningModalBase.cancelandclose';
20
20
  import disableCloseBtnMessage from '@salesforce/label/LightningModalBase.waitstate';
21
21
  import AriaObserver from 'lightning/ariaObserver';
22
- import { isLwcModalActive } from 'lightning/overlayManager';
22
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
23
23
 
24
24
  const DEBOUNCE_RESIZE = 300;
25
25
  const SMALL_SCREEN_SIZE = 480;
@@ -27,7 +27,6 @@ const SIZE_SMALL = 'small';
27
27
  const SIZE_MEDIUM = 'medium';
28
28
  const SIZE_LARGE = 'large';
29
29
  const SIZE_FULL = 'full';
30
- const MODAL_CONTAINER = 'lightning-overlay-container';
31
30
 
32
31
  export default class LightningModalBase extends LightningShadowBaseClass {
33
32
  // this is visible in DOM, changed from 'lightning-modal-base'
@@ -69,10 +68,9 @@ export default class LightningModalBase extends LightningShadowBaseClass {
69
68
  portraitMatchMedia = null;
70
69
  screenOrientationChangeHandler = null;
71
70
 
72
- // state utilized when performing keyboard Tab/Shift-Tab interactions
71
+ // state utilized when performing keyboard focus trap
73
72
  focusinEventBound = false;
74
- focusinEventHandler = null;
75
- lastFocussedElementOnModal = null;
73
+ lastFocusedElement = null;
76
74
 
77
75
  // modalFooter, child
78
76
  footerRegistered = false;
@@ -468,27 +466,6 @@ export default class LightningModalBase extends LightningShadowBaseClass {
468
466
  }
469
467
  }
470
468
 
471
- /**
472
- * Handler for 'focusin' events, responsible for trapping user focus to open Modal
473
- * @param e - Event
474
- */
475
- handleFocusinEvents(e) {
476
- // eslint-disable-next-line @lwc/lwc/no-async-operation
477
- requestAnimationFrame(() => {
478
- // is current active (open) modal is lwc
479
- if (isLwcModalActive() && this.isModalOpen) {
480
- const isTargetRelatedToModal =
481
- e.target?.closest(MODAL_CONTAINER) ||
482
- e.relatedTarget?.closest(MODAL_CONTAINER);
483
- if (isTargetRelatedToModal) {
484
- this.lastFocussedElementOnModal = getElementWithFocus();
485
- } else {
486
- returnFocusToElement(this.lastFocussedElementOnModal);
487
- }
488
- }
489
- });
490
- }
491
-
492
469
  /**
493
470
  * Opening the modal involves first performing necessary steps to
494
471
  * prepare for when the modal closes
@@ -794,7 +771,11 @@ export default class LightningModalBase extends LightningShadowBaseClass {
794
771
  : fallbackFocusElem;
795
772
 
796
773
  if (focusElem !== null) {
797
- focusElem.focus();
774
+ this.lastFocusedElement = focusElem;
775
+ // eslint-disable-next-line @lwc/lwc/no-async-operation
776
+ requestAnimationFrame(() => {
777
+ focusElem.focus();
778
+ });
798
779
  this.autoFocusCompletedOnce = true;
799
780
  } else {
800
781
  // Should never happen since outerModalElem always present
@@ -1178,8 +1159,10 @@ export default class LightningModalBase extends LightningShadowBaseClass {
1178
1159
  addFocusinEventListener() {
1179
1160
  if (!this.focusinEventBound) {
1180
1161
  this.focusinEventBound = true;
1181
- this.focusinEventHandler = this.handleFocusinEvents.bind(this);
1182
- window.addEventListener('focusin', this.focusinEventHandler);
1162
+ window.addEventListener(
1163
+ 'focusin',
1164
+ modalFocusinEventHandler.bind(this)
1165
+ );
1183
1166
  }
1184
1167
  }
1185
1168
 
@@ -1192,11 +1175,27 @@ export default class LightningModalBase extends LightningShadowBaseClass {
1192
1175
  removeFocusinEventListener() {
1193
1176
  if (this.focusinEventBound) {
1194
1177
  this.focusinEventBound = false;
1195
- window.removeEventListener('focusin', this.focusinEventHandler);
1196
- this.focusinEventHandler = null;
1178
+ window.removeEventListener(
1179
+ 'focusin',
1180
+ modalFocusinEventHandler.bind(this)
1181
+ );
1197
1182
  }
1198
1183
  }
1199
1184
 
1185
+ handleModalBaseFocusin = modalFocusinEventHandler.bind(this);
1186
+
1187
+ handleLastFocusedElem(e) {
1188
+ if (!(e.detail && e.detail[secure])) {
1189
+ console.error(
1190
+ 'Invalid access to onprivatelightningmodallastfocus event'
1191
+ );
1192
+ return;
1193
+ }
1194
+ e.stopPropagation();
1195
+
1196
+ this.lastFocusedElement = e.detail.privatelightningmodallastfocus;
1197
+ }
1198
+
1200
1199
  /**
1201
1200
  * determine if the current screen is less than SMALL_SCREEN_SIZE
1202
1201
  * for Modal, screen size detection is simplified to what's required
@@ -5,6 +5,7 @@
5
5
  part="modal-body"
6
6
  data-content-container
7
7
  onprivatescrollablecontainer={handleScrollableContainerRepositionEvent}
8
+ onfocusin={handleModalBodyFocusin}
8
9
  >
9
10
  <slot
10
11
  data-default-slot
@@ -2,6 +2,7 @@ import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
2
2
  import { classSet } from 'lightning/utils';
3
3
  import { getRealDOMId } from 'lightning/utilsPrivate';
4
4
  import { findAllTabbableElements, filterTooltips } from 'lightning/focusUtils';
5
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
5
6
 
6
7
  /**
7
8
  * The modal body component to display main content area in lightning modal.
@@ -294,6 +295,8 @@ export default class LightningModalBody extends LightningShadowBaseClass {
294
295
  this.dispatchEvent(evtRegister);
295
296
  }
296
297
 
298
+ handleModalBodyFocusin = modalFocusinEventHandler.bind(this);
299
+
297
300
  /**
298
301
  * When modal body is being created, initialize
299
302
  * private tracked modal body state
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <div class={footerCssClasses} part="modal-footer">
2
+ <div
3
+ class={footerCssClasses}
4
+ part="modal-footer"
5
+ onfocusin={handleModalFooterFocusin}
6
+ >
3
7
  <slot
4
8
  data-footer-slot
5
9
  onslotchange={handleDefaultSlotChange}
@@ -1,5 +1,6 @@
1
1
  import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
2
2
  import { classSet } from 'lightning/utils';
3
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
3
4
 
4
5
  // SLDS Modal Footer classes
5
6
  const footerClass = 'slds-modal__footer';
@@ -104,6 +105,8 @@ export default class LightningModalFooter extends LightningShadowBaseClass {
104
105
  this.dispatchEvent(evtRegister);
105
106
  }
106
107
 
108
+ handleModalFooterFocusin = modalFocusinEventHandler.bind(this);
109
+
107
110
  /**
108
111
  * When modal footer is being created, initialize
109
112
  * private tracked modal footer state
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <div class="slds-modal__header" part="modal-header">
2
+ <div class="slds-modal__header"
3
+ part="modal-header"
4
+ onfocusin={handleModalHeaderFocusin}
5
+ >
3
6
  <template if:true={label}>
4
7
  <h1
5
8
  id="modal-label"
@@ -1,6 +1,7 @@
1
1
  import { api } from 'lwc';
2
2
  import LightningShadowBaseClass from 'lightning/shadowBaseClassPrivate';
3
3
  import { getRealDOMId } from 'lightning/utilsPrivate';
4
+ import { modalFocusinEventHandler } from 'lightning/modalUtils';
4
5
 
5
6
  // selectors
6
7
  const modalHeaderSelector = '.slds-modal__header';
@@ -152,6 +153,8 @@ export default class LightningModalHeader extends LightningShadowBaseClass {
152
153
  this.dispatchEvent(evtRegister);
153
154
  }
154
155
 
156
+ handleModalHeaderFocusin = modalFocusinEventHandler.bind(this);
157
+
155
158
  /**
156
159
  * When modal header is being created, initialize
157
160
  * private tracked modal header state
@@ -436,7 +436,7 @@ function initAuraOverlayState() {
436
436
 
437
437
  /**
438
438
  * Helper function to detect if a lightning-modal is currently open
439
- * Used in modalBase.js to trap a user's focus while lightning-modal is open
439
+ * Used in modalUtil.js to trap a user's focus while lightning-modal is open
440
440
  * @returns {boolean}
441
441
  */
442
442
  export function isLwcModalActive() {
@@ -1,4 +1,4 @@
1
- import { isInDom, WindowManager, pxToInt } from './util';
1
+ import { isInDom, WindowManager, pxToFloat, getTransformValues } from './util';
2
2
 
3
3
  export class ElementProxy {
4
4
  constructor(el, id) {
@@ -137,18 +137,21 @@ export class ElementProxy {
137
137
 
138
138
  const originalLeft = style.left.match(/auto|fixed/)
139
139
  ? '0'
140
- : parseInt(style.left.replace('px', ''), 10);
140
+ : pxToFloat(style.left);
141
141
  const originalTop = style.top.match(/auto|fixed/)
142
142
  ? '0'
143
- : parseInt(style.top.replace('px', ''), 10);
143
+ : pxToFloat(style.top);
144
144
 
145
145
  const marginOffset =
146
146
  this.top < absPos.top
147
- ? pxToInt(style.marginBottom)
148
- : pxToInt(style.marginTop) * -1;
147
+ ? pxToFloat(style.marginBottom) * -1
148
+ : pxToFloat(style.marginTop);
149
+
150
+ const transform = getTransformValues(style.transform);
151
+ const topOffset = transform.y;
149
152
 
150
153
  let leftDif = Math.round(this.left - (absPos.left + scrollLeft));
151
- const topDif = this.top - (absPos.top + marginOffset + scrollTop);
154
+ const topDif = this.top - (absPos.top + scrollTop) + topOffset;
152
155
 
153
156
  const viewPortWidth = w.innerWidth || document.body.clientWidth;
154
157
  let rightPos = parseInt(style.right, 10);
@@ -164,6 +167,10 @@ export class ElementProxy {
164
167
 
165
168
  this._node.style.left = `${originalLeft + leftDif}px`;
166
169
  this._node.style.top = `${originalTop + topDif}px`;
170
+ // translate3d enables CSS Hardware Acceleration and switches to GPU
171
+ this._node.style.transform = `translate3d(0, ${
172
+ topOffset ? topOffset : marginOffset
173
+ }px, 0)`;
167
174
 
168
175
  if (this._restoreSize) {
169
176
  // Only store the first height/width which is the original height/width.
@@ -244,6 +244,24 @@ function isPx(value) {
244
244
  return value.slice(-2) === 'px';
245
245
  }
246
246
 
247
- export function pxToInt(value) {
248
- return value && isPx(value) ? parseInt(value, 10) : 0;
247
+ export function pxToFloat(value) {
248
+ return value && isPx(value) ? parseFloat(value) : 0;
249
+ }
250
+
251
+ export function getTransformValues(value = '') {
252
+ // DOMMatrix is used to get scalar values for css transform string
253
+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly
254
+ const matrix = new DOMMatrixReadOnly(value);
255
+ if (matrix.is2D) {
256
+ return {
257
+ x: matrix.e, // translateX
258
+ y: matrix.f, // translateY
259
+ z: 0,
260
+ };
261
+ }
262
+ return {
263
+ x: matrix.m41, // translateX
264
+ y: matrix.m42, // translateY
265
+ z: matrix.m43, // translateZ
266
+ };
249
267
  }
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <lightning-button-menu
3
+ lwc:ref="buttonMenu"
3
4
  icon-size="x-small"
4
5
  alternative-text={buttonAlternateText}
5
6
  menu-alignment={computedMenuAlignment}
@@ -68,7 +68,7 @@ export default class PrimitiveCellActions extends LightningElement {
68
68
  @api
69
69
  focus() {
70
70
  if (this._connected) {
71
- this.template.querySelector('lightning-button-menu').focus();
71
+ this.refs.buttonMenu.focus();
72
72
  }
73
73
  }
74
74
 
@@ -81,7 +81,7 @@ export default class PrimitiveCellActions extends LightningElement {
81
81
  // focus/click without changing tabindex doesnt work W-6185168
82
82
  // eslint-disable-next-line @lwc/lwc/no-async-operation
83
83
  setTimeout(() => {
84
- this.template.querySelector('lightning-button-menu').click();
84
+ this.refs.buttonMenu.click();
85
85
  }, 0);
86
86
  }
87
87
  }
@@ -141,9 +141,7 @@ export default class PrimitiveCellActions extends LightningElement {
141
141
  * Handles the opening of an action menu
142
142
  */
143
143
  handleMenuOpen() {
144
- this.elementRect = this.template
145
- .querySelector('lightning-button-menu')
146
- .getBoundingClientRect();
144
+ this.elementRect = this.refs.buttonMenu.getBoundingClientRect();
147
145
 
148
146
  const detail = {
149
147
  rowKeyValue: this.rowKeyValue,
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <template if:true={isButtonIconType}>
3
3
  <lightning-button-icon
4
+ lwc:ref="buttonIcon"
4
5
  variant={variant}
5
6
  alternative-text={alternativeText}
6
7
  icon-name={iconName}
@@ -14,6 +15,7 @@
14
15
  </template>
15
16
  <template if:false={isButtonIconType}>
16
17
  <lightning-button
18
+ lwc:ref="button"
17
19
  variant={variant}
18
20
  label={label}
19
21
  icon-name={iconName}
@@ -61,11 +61,9 @@ export default class PrivateCellButton extends LightningElement {
61
61
 
62
62
  get buttonCustomElement() {
63
63
  if (this._connected) {
64
- const qs = this.isButtonIconType
65
- ? 'lightning-button-icon'
66
- : 'lightning-button';
67
-
68
- return this.template.querySelector(qs);
64
+ return this.isButtonIconType
65
+ ? this.refs.buttonIcon
66
+ : this.refs.button;
69
67
  }
70
68
  return undefined;
71
69
  }
@@ -4,7 +4,8 @@
4
4
  onclick={handleCheckboxContainerClick}
5
5
  onmousedown={handleCheckboxContainerMouseDown}
6
6
  >
7
- <input type="checkbox"
7
+ <input lwc:ref="input"
8
+ type="checkbox"
8
9
  name={computedOptionName}
9
10
  id="primitive-cell-checkbox-id"
10
11
  tabindex={internalTabIndex}
@@ -13,7 +14,7 @@
13
14
  onclick={handleCheckboxClick}
14
15
  disabled={isDisabled}
15
16
  checked={isSelected}>
16
- <label
17
+ <label lwc:ref="label"
17
18
  id={labelId}
18
19
  class="slds-checkbox__label"
19
20
  for="primitive-cell-checkbox-id"