lightning-base-components 1.17.1-alpha → 1.17.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 (64) hide show
  1. package/metadata/raptor.json +32 -17
  2. package/package.json +15 -11
  3. package/scopedImports/@salesforce-label-AddressAutocomplete.LookupButton.js +1 -0
  4. package/scopedImports/@salesforce-label-LightningDatatable.chooseARowSelectAll.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningLookup.noAccess.js +1 -0
  6. package/scopedImports/@salesforce-label-LightningToast.close.js +1 -0
  7. package/src/lightning/accordionSection/accordionSection.html +2 -2
  8. package/src/lightning/accordionSection/accordionSection.js +21 -2
  9. package/src/lightning/baseCombobox/baseCombobox.html +1 -1
  10. package/src/lightning/baseCombobox/baseCombobox.js +56 -3
  11. package/src/lightning/baseCombobox/keyboard.js +26 -0
  12. package/src/lightning/breadcrumb/__docs__/breadcrumb.md +5 -6
  13. package/src/lightning/buttonGroup/buttonGroup.css +9 -0
  14. package/src/lightning/buttonGroup/buttonGroup.html +1 -1
  15. package/src/lightning/buttonStateful/buttonStateful.html +2 -1
  16. package/src/lightning/buttonStateful/buttonStateful.js +10 -0
  17. package/src/lightning/card/__docs__/card.md +2 -2
  18. package/src/lightning/card/card.html +3 -1
  19. package/src/lightning/card/card.js +51 -15
  20. package/src/lightning/card/utils.js +0 -14
  21. package/src/lightning/checkboxGroup/checkboxGroup.html +1 -1
  22. package/src/lightning/datatable/datatable.js +6 -15
  23. package/src/lightning/datatable/renderManager.js +14 -5
  24. package/src/lightning/datatable/rowSelection.js +4 -4
  25. package/src/lightning/datatable/rows.js +1 -0
  26. package/src/lightning/datatable/templates/div/div.html +4 -2
  27. package/src/lightning/datatable/templates/table/table.html +6 -2
  28. package/src/lightning/dialog/README.md +1 -1
  29. package/src/lightning/focusUtils/focus.js +42 -0
  30. package/src/lightning/focusUtils/focusUtils.js +1 -0
  31. package/src/lightning/formattedAddress/formattedAddress.js +1 -1
  32. package/src/lightning/input/__docs__/input.md +1 -1
  33. package/src/lightning/input/input.html +5 -2
  34. package/src/lightning/input/input.js +14 -2
  35. package/src/lightning/modal/__docs__/modal.md +187 -20
  36. package/src/lightning/modalBase/modalBase.js +7 -6
  37. package/src/lightning/positionLibrary/overlayDetector.js +10 -1
  38. package/src/lightning/primitiveBubble/primitiveBubble.css +9 -0
  39. package/src/lightning/primitiveBubble/primitiveBubble.js +3 -1
  40. package/src/lightning/primitiveCellActions/primitiveCellActions.html +1 -0
  41. package/src/lightning/primitiveCellActions/primitiveCellActions.js +1 -1
  42. package/src/lightning/primitiveCellCheckbox/primitiveCellCheckbox.js +15 -1
  43. package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +3 -1
  44. package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +1 -0
  45. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +29 -0
  46. package/src/lightning/primitiveHeaderFactory/selectableHeader.html +3 -6
  47. package/src/lightning/primitiveTreegridCellToggle/primitiveTreegridCellToggle.js +8 -3
  48. package/src/lightning/progressIndicator/progressIndicator.js +1 -1
  49. package/src/lightning/radioGroup/radioGroup.html +1 -1
  50. package/src/lightning/textarea/textarea.js +13 -1
  51. package/src/lightning/tooltipLibrary/tooltipLibrary.js +7 -0
  52. package/src/lightning/tree/tree.html +1 -1
  53. package/src/lightning/tree/tree.js +25 -1
  54. package/src/lightning/treeGrid/__docs__/treeGrid.md +15 -0
  55. package/src/lightning/treeGrid/treeGrid.js +25 -22
  56. package/src/lightning/utilsPrivate/ariaLevelHeadingUtils.js +11 -0
  57. package/src/lightning/utilsPrivate/normalize.js +22 -6
  58. package/src/lightning/utilsPrivate/os.js +36 -0
  59. package/src/lightning/utilsPrivate/utilsPrivate.js +7 -0
  60. package/src/lightning/verticalNavigationSection/verticalNavigationSection.html +1 -1
  61. package/src/lightning/verticalNavigationSection/verticalNavigationSection.js +22 -1
  62. package/scopedImports/@salesforce-label-LightningToast.missingToastLabel.js +0 -1
  63. package/scopedImports/@salesforce-label-LightningToastContainer.missingToastConfig.js +0 -1
  64. package/scopedImports/@salesforce-label-LightningToastContainer.missingToastProperty.js +0 -1
@@ -1,17 +1,17 @@
1
- A `lightningModal` component overlays a message modal on top of the current app window. A modal interrupts a user’s workflow and draws attention to the message.
1
+ A `lightningModal` component overlays a message modal on top of the current app window. A modal interrupts a user’s workflow and draws attention to the message.
2
2
 
3
3
  `LightningModal` implements the SLDS [modals](https://www.lightningdesignsystem.com/components/modals/) blueprint.
4
4
 
5
5
  Create a modal component in response to a user action, such as clicking a button or link. The modal blocks interaction with everything else on the page until the user acts upon or dismisses the modal.
6
6
 
7
- Unlike other components, this component doesn't use a `lightning-modal` tag or extend `LightningElement`. There is no `lightning-modal` component. Instead, you create a modal by extending `LightningModal` and using these helper `lightning-modal-*` components to provide a header, footer and the body of the modal.
7
+ Unlike other components, this component doesn't use a `lightning-modal` tag or extend `LightningElement`. There is no `lightning-modal` component. Instead, you create a modal by extending `LightningModal` and using these helper `lightning-modal-*` components to provide a header, footer and the body of the modal.
8
8
  - `lightning-modal-body`
9
9
  - `lightning-modal-header`
10
10
  - `lightning-modal-footer`
11
11
 
12
12
  To create a modal component, import `LightningModal` from `lightning/modal`. The component has access to the normal LWC resources as well as the special container, helper components, methods, and events of the `lightning/modal` module.
13
13
 
14
- In this example, the `content` property passes data to the modal from the component that invokes it.
14
+ In this example, the `content` property passes data to the modal from the component that invokes it.
15
15
 
16
16
  ```js
17
17
  /* c/myModal.js */
@@ -28,7 +28,7 @@ export default class MyModal extends LightningModal {
28
28
  }
29
29
  ```
30
30
 
31
- The modal’s HTML template uses helper `lightning-modal-*` components to provide a header, footer, and the body of the modal. In this example, the content for the modal body comes from the `content` property we defined in the modal's JavaScript file.
31
+ The modal’s HTML template uses helper `lightning-modal-*` components to provide a header, footer, and the body of the modal. In this example, the content for the modal body comes from the `content` property we defined in the modal's JavaScript file.
32
32
 
33
33
  ```html
34
34
  <!-- c/myModal.html -->
@@ -42,19 +42,19 @@ The modal’s HTML template uses helper `lightning-modal-*` components to provid
42
42
  </template>
43
43
  ```
44
44
 
45
- The `lightning-modal-body` component is required for the modal template.
45
+ The `lightning-modal-body` component is required for the modal template.
46
46
 
47
- The `lightning-modal-header` and `lightning-modal-footer` components are optional, but recommended. The `lightning-modal-*` components render in the order they appear in the template. Place the `lightning-modal-body` component after `lightning-modal-header` and before the `lightning-modal-footer` component.
47
+ The `lightning-modal-header` and `lightning-modal-footer` components are optional, but recommended. The `lightning-modal-*` components render in the order they appear in the template. Place the `lightning-modal-body` component after `lightning-modal-header` and before the `lightning-modal-footer` component.
48
48
 
49
49
  #### Open a Modal Instance
50
50
 
51
51
  `LightningModal` provides an `.open()` method which opens a modal and returns a promise that asynchronously resolves with the result of the user’s interaction with the modal.
52
52
 
53
- Each invocation of a modal component’s `.open()` method creates a unique instance of the modal. You can think of a modal as a self-contained application that starts from scratch when it opens. It displays the content you pass in through the `.open()` method or that you set within the modal's HTML template.
53
+ Each invocation of a modal component’s `.open()` method creates a unique instance of the modal. You can think of a modal as a self-contained application that starts from scratch when it opens. It displays the content you pass in through the `.open()` method or that you set within the modal's HTML template.
54
54
 
55
- When you close a modal, the modal instance is destroyed, not hidden. On close, the modal must save the user’s input data or pass it to the invoking component as the promise result. Otherwise, the data is lost when the modal instance is closed.
55
+ When you close a modal, the modal instance is destroyed, not hidden. On close, the modal must save the user’s input data or pass it to the invoking component as the promise result. Otherwise, the data is lost when the modal instance is closed.
56
56
 
57
- The `.open()` method lets you assign values to the modal's properties. `LightningModal` provides these properties.
57
+ The `.open()` method lets you assign values to the modal's properties. `LightningModal` provides these properties.
58
58
 
59
59
  * `label` - Required. Sets the modal's title and assistive device label. If the modal has a header, set `label` in the `lightning-modal-header` component. If the modal doesn't have a header, set the `label` property when opening the modal.
60
60
 
@@ -95,14 +95,14 @@ The HTML template for this app contains a button that opens the modal and displa
95
95
  <template>
96
96
  <lightning-button
97
97
  onclick={handleClick}
98
- aria-haspopup="modal"
98
+ aria-haspopup="dialog"
99
99
  label="Open My Modal">
100
- </lightning-button>
100
+ </lightning-button>
101
101
  <p>Result: {result}</p>
102
102
  </template>
103
103
  ```
104
104
 
105
- You can also use `.open()` to pass data from your invoking component into the modal with custom properties decorated with `@api`. These properties can be any type, such as a string or an object that’s an array of key/value pairs to be assigned to the new modal instance.
105
+ You can also use `.open()` to pass data from your invoking component into the modal with custom properties decorated with `@api`. These properties can be any type, such as a string or an object that’s an array of key/value pairs to be assigned to the new modal instance.
106
106
 
107
107
  For example, this app component sets an `options` property to a set of key/value pairs in `MyModal.open()`. The promise is handled using an arrow function that logs the result to the console.
108
108
 
@@ -155,14 +155,14 @@ export default class MyModal extends LightningModal {
155
155
  >
156
156
  {option.label}
157
157
  </lightning-button>
158
- </template>
158
+ </template>
159
159
  </lightning-modal-body>
160
160
  </template>
161
161
  ```
162
162
 
163
163
  #### Close a Modal Instance
164
164
 
165
- Use `this.close(result)` to close the modal, where `result` is anything you want to return from the modal. The `.close()` operation is asynchronous to display a brief fade out animation before the modal is destroyed. The `result` data can’t be modified after the close operation begins.
165
+ Use `this.close(result)` to close the modal, where `result` is anything you want to return from the modal. The `.close()` operation is asynchronous to display a brief fade out animation before the modal is destroyed. The `result` data can’t be modified after the close operation begins.
166
166
 
167
167
  You can also close the modal with the default close button, the X at the top right corner. Closing a modal like this is the same as calling `this.close()` with an `undefined` result, so any data input is lost.
168
168
 
@@ -320,7 +320,7 @@ export default class MyModalForm extends LightningModal {
320
320
 
321
321
  A modal can only fire events captured by the component that opened it, not the modal itself. Normal techniques can't catch events that fire from the modal, because the events bubble up to a top root element outside of the component that opened the modal.
322
322
 
323
- To capture modal events, attach them in the `.open()` method invoked by the component that opens the modal.
323
+ To capture modal events, attach them in the `.open()` method invoked by the component that opens the modal.
324
324
 
325
325
  For example, here's a custom `select` event dispatched from `MyModal`.
326
326
 
@@ -374,18 +374,185 @@ handleOpenModal() {
374
374
 
375
375
  See [Create and Dispatch Events](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/events_create_dispatch) in the LWC Dev Guide for more information about events.
376
376
 
377
+ #### Modal Events with Aura
378
+
379
+ For `LightningModal`, only the top level LWC component or application can communicate to the parent Aura component or application layer with eventing. This topmost component is usually the one that opens the `LightningModal`. `LightningModal`'s child components can't event to a parent Aura component or application layer.
380
+
381
+ All required eventing that should occur during the `LightningModal`'s life cycle must be passed in when you call `Modal.open()`. See `onselect` within `.open()` in the **Modal Events** section.
382
+
383
+ If you want the Aura layer to respond to events within child components embedded in the `LightningModal`, use event bubbling to move any data that you want to make available to the Aura layer into the topmost LWC component that opened the modal. Then, send the event from the LWC component.
384
+
385
+ With this in mind, there are two suggested methods for extracting data from the `LightningModal` to the Aura layer.
386
+
387
+ 1. To only communicate data out of modal after it's closed, first, close the modal, and pass the data out with `this.close({ data })`, and handle the data received in `.then((result) { ... })` where the Modal is initially opened.
388
+ 2. To continuously communicate data out of the `LightningModal` while the modal remains open, use events created and passed in when opening the modal from `Modal.open({ size, title, onmyevent })`.
389
+
390
+ These extracting methods fit into the larger LWC Modal-to-Aura event workflow.
391
+
392
+ 1. Pass any events that should occur within the modal through `LightningModal`'s `.open()` method
393
+ 2. Have the `LightningModal` JavaScript code fire any custom events
394
+ 3. In the topmost LWC component that opened the modal, create an event handler to process the events, including stopping propagation.
395
+ 4. Fire a separate event containing the LWC-processed event details and send it to the Aura parent component.
396
+ 5. Use an Aura-based event handler to handle and process the event.
397
+
398
+ For more information, see [Send Events to an Enclosing Aura Component](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.events_sending_to_aura_components) and [Events Best Practices](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/events_best_practices).
399
+
400
+ Let's see this workflow in action. In this example, we'll create a button (`lightning-button`) that launches a modal (`LightningModal`) containing a tree grid component (`lightning-tree-grid`) with a button in each record row that automatically navigates our user to that record's page (`lightning-navigation`). This use case requires data passing between our LWC components and a parent Aura component.
401
+
402
+ 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.
403
+
404
+ 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.
405
+
406
+ 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`.
407
+
408
+ Here's our Aura component, containing our topmost LWC component, `myLwcAppModalLauncher`.
409
+
410
+ ```html
411
+ /* c/myApp.cmp */
412
+ <aura:component>
413
+ <!-- <c:myLwcTreeGridWithNavigation/> component is a child component
414
+ inside of <c:myLwcAppModalLauncher/>
415
+ -->
416
+ <c:myLwcAppModalLauncher/>
417
+ </aura:component>
418
+ ```
419
+
420
+ The topmost component, `myLwcAppModalLauncher`, launches and handles events that occur within our modal (`MyModal`). `myLwcAppModalLauncher` is also where we import the `lightning-navigation` component and use the `rowId` handed up through modal's `this.close({ ..., rowId })` function.
421
+
422
+ ```html
423
+ <!-- c/myLwcAppModalLauncher.html -->
424
+
425
+ <template>
426
+ <lightning-button
427
+ onclick={handleModalOpen}
428
+ aria-haspopup="dialog"
429
+ label="Launch Navigation Modal">
430
+ </lightning-button>
431
+ </template>
432
+ ```
433
+
434
+ ```js
435
+ /* c/myLwcAppModalLauncher.js */
436
+
437
+ import { LightningElement, wire } from 'lwc';
438
+ import { NavigationMixin } from 'lightning/navigation';
439
+ import MyModal from 'c/myModalWithTreeGridNavigation';
440
+
441
+ export default class MyLwcAppModalLauncher extends NavigationMixin(LightningElement) {
442
+
443
+ /// ... other modal code
444
+
445
+ handleModalOpen() {
446
+ // open up the Modal
447
+ MyModal.open({
448
+ size: 'medium',
449
+ heading: 'Navigate to Record Page',
450
+ description: 'Navigate to a record page by clicking the row button',
451
+ options: [{ data }, { data }],
452
+ }).then((result) => {
453
+ // when the LightningModal closes, result is whatever
454
+ // data that was passed out using this.close({ data })
455
+ if (result === null) {
456
+ // do something else
457
+ } else {
458
+ // shouldNavigate is boolean, arbitrary
459
+ // rowId is what's needed for lightning-navigation
460
+ const { shouldNavigate, rowId } = result;
461
+ if (shouldNavigate) {
462
+ this.navigateToObjectHome(rowId);
463
+ }
464
+ }
465
+ });
466
+ }
467
+
468
+ navigateToObjectHome(rowId) {
469
+ // construct the page ref
470
+ const pageRef = {
471
+ type: 'standard__recordPage',
472
+ attributes: {
473
+ recordId: rowId,
474
+ actionName: 'view'
475
+ }
476
+ }
477
+ // then call the .Navigate method with the pageRef
478
+ this[NavigationMixin.Navigate](pageRef);
479
+ }
480
+
481
+ /* ... other modal code */
482
+ ```
483
+
484
+ This `template` is our modal, containing a tree grid with the navigation buttons, named `c-my-lwc-tree-grid-with-navigation`. The `handleNavSelection` function in this component processes the `rowId` data for the modal component to pass to its parent.
485
+
486
+ ```html
487
+ <!-- c/myModalWithTreeGridNavigation.html -->
488
+ <template>
489
+ <lightning-modal-header label="My Modal Heading">
490
+ The modal tagline.
491
+ </lightning-modal-header>
492
+ <lightning-modal-body>
493
+ <h2>Choose a record to navigate to:</h2>
494
+ <!-- custom event listener when button clicked inside tree grid -->
495
+ <div onnavselection={handleNavSelection}>
496
+ <c-my-lwc-tree-grid-with-navigation></c-my-lwc-tree-grid-with-navigation>
497
+ </div>
498
+ </lightning-modal-body>
499
+ <!-- no <lightning-modal-footer> in this example -->
500
+ </template>
501
+ ```
502
+
503
+ ```js
504
+ /* c/myModalWithTreeGridNavigation.js */
505
+ handleNavSelection(event) {
506
+ event.stopPropagation();
507
+ const { detail: { rowId } } = event;
508
+ if (rowId) {
509
+ // rowId value is important to lightning-navigation
510
+ // passing this data out through the LightningModal's
511
+ // .close() method, then handled in the .then((result) {})
512
+ // see code above: c/myLwcAppModalLauncher.js
513
+ this.close({ shouldNavigate: true, rowId });
514
+ }
515
+ }
516
+ ```
517
+
518
+ ```js
519
+ /* c/myLwcTreeGridWithNavigation.js */
520
+
521
+ dispatchNavSelectionEvent(rowId) {
522
+ // add rowId to event.detail
523
+ // this custom event listener exists in
524
+ // LightningModal body code, see code above:
525
+ // c/myModalWithTreeGridNavigation.html
526
+ const eventToFire = new CustomEvent('navselection', {
527
+ detail: { rowId },
528
+ bubbles: true,
529
+ cancelable: false
530
+ });
531
+ // dispatch custom event
532
+ // see event listener added to lightning-modal-body
533
+ this.dispatchEvent(eventToFire);
534
+ }
535
+
536
+ handleRowButtonClick(event) {
537
+ // simplified handler to get row.Id
538
+ // from the tree grid row button that was clicked
539
+ const row = event.detail.row;
540
+ this.dispatchNavSelectionEvent(row.Id);
541
+ }
542
+ ```
543
+
377
544
  #### Styling Variants
378
545
 
379
- The `lightning-modal-header` and `lightning-modal-footer` child components are optional, and you can choose to not include one or the other in your modal.
546
+ The `lightning-modal-header` and `lightning-modal-footer` child components are optional, and you can choose to not include one or the other in your modal.
380
547
 
381
548
  The headerless variant of `LightningModal` has these additional requirements.
382
549
  - Must set a descriptive modal title with the `label` property using `Modal.open({ label })` or you’ll get a console error.
383
- - The `label` property is required for all variants of `LightningModal`. Assistive devices read the `label` value, even though the headerless modal variant doesn't display the label.
550
+ - The `label` property is required for all variants of `LightningModal`. Assistive devices read the `label` value, even though the headerless modal variant doesn't display the label.
384
551
  - Because this variant doesn't use `lightning-modal-header`, you have to manually create an `<h1>` heading in `lightning-modal-body`. Provide accessible structure by starting with heading level `<h1>` and using levels up to `<h6>` appropriately. For more information, see [Semantic Structure, Headings on WebAim.org](https://webaim.org/techniques/semanticstructure/#headings).
385
552
 
386
553
  The `LightningModal` component also supports the SLDS [Directional variant](https://www.lightningdesignsystem.com/components/modals/#Directional) modal blueprint pattern.
387
554
 
388
- To achieve the directional button layout, place the buttons in a `div` with the `slds-modal__footer_directional` class.
555
+ To achieve the directional button layout, place the buttons in a `div` with the `slds-modal__footer_directional` class.
389
556
 
390
557
  ```html
391
558
  <!-- c/modalDirectional.html -->
@@ -403,7 +570,7 @@ To achieve the directional button layout, place the buttons in a `div` with the
403
570
 
404
571
  #### Styling Hooks
405
572
 
406
- The `lightning-modal-*` helper components support [style hooks](https://www.lightningdesignsystem.com/components/modals/#Styling-Hooks-Overview). The styling hooks for the template that invokes the helper components doesn't carry over to them, so you must style each helper component individually.
573
+ The `lightning-modal-*` helper components support [style hooks](https://www.lightningdesignsystem.com/components/modals/#Styling-Hooks-Overview). The styling hooks for the template that invokes the helper components doesn't carry over to them, so you must style each helper component individually.
407
574
 
408
575
  Customizing the styling on the white modal frame and background, close button, or gray backdrop isn't supported.
409
576
 
@@ -411,4 +578,4 @@ Customizing the styling on the white modal frame and background, close button, o
411
578
 
412
579
  The `lightning-modal-header` component renders the `label` value in an `<h1>` element. If your modal uses the header, begin any additional heading levels in the modal with `<h2>` for accessibility. Provide accessible structure by using heading levels up to `<h6>` appropriately. For more information, see [Semantic Structure, Headings on WebAim.org](https://webaim.org/techniques/semanticstructure/#headings).
413
580
 
414
- To include tagline text or link content for the header section, add it between the `<lightning-modal-header>` tags.
581
+ To include tagline text or link content for the header section, add it between the `<lightning-modal-header>` tags.
@@ -10,7 +10,10 @@ import {
10
10
  isAriaDescriptionSupported,
11
11
  } from 'lightning/utilsPrivate';
12
12
  import { instanceName, secure } from 'lightning/overlayUtils';
13
- import { getElementWithFocus } from 'lightning/focusUtils';
13
+ import {
14
+ getElementWithFocus,
15
+ returnFocusToElement,
16
+ } from 'lightning/focusUtils';
14
17
  import closeButtonAltText from '@salesforce/label/LightningModalBase.cancelandclose';
15
18
  import disableCloseBtnMessage from '@salesforce/label/LightningModalBase.waitstate';
16
19
 
@@ -147,7 +150,7 @@ export default class LightningModalBase extends LightningElement {
147
150
  // we track both in order to handle transition correctly
148
151
  const isSwitchingToDisabled =
149
152
  !this.disableCloseButton && this.disableClose;
150
- /* Future enhancement possibility - trigger setInterval to remove and
153
+ /* Future enhancement possibility - trigger setInterval to remove and
151
154
  again add back 'Processing' text, as this will indicate to the screen
152
155
  reader user that the interface continues to be busy
153
156
  */
@@ -349,10 +352,8 @@ export default class LightningModalBase extends LightningElement {
349
352
  */
350
353
  returnFocusToBackground() {
351
354
  const { savedActiveElement } = this;
352
- const isSavedElemInDOM = document.body.contains(savedActiveElement);
353
- if (savedActiveElement && isSavedElemInDOM) {
354
- savedActiveElement.focus();
355
- } else {
355
+ const elementWasFocused = returnFocusToElement(savedActiveElement);
356
+ if (!elementWasFocused) {
356
357
  // eslint-disable-next-line no-console
357
358
  console.warn('Modal :: Nothing to return focus to');
358
359
  }
@@ -6,6 +6,7 @@ export const OVERLAY_TYPE = {
6
6
  DIALOG: 'lightning-dialog',
7
7
  POPOVER: 'lightning-popover',
8
8
  PANEL: 'uiPanel',
9
+ SLDSMODAL: 'slds-modal',
9
10
  };
10
11
 
11
12
  export function isOverlay(element) {
@@ -30,6 +31,13 @@ export function isOverlay(element) {
30
31
  if (isPanel) {
31
32
  return OVERLAY_TYPE.PANEL;
32
33
  }
34
+
35
+ const isSldsModal =
36
+ element.classList && element.classList.contains(OVERLAY_TYPE.SLDSMODAL);
37
+ if (isSldsModal) {
38
+ return OVERLAY_TYPE.SLDSMODAL;
39
+ }
40
+
33
41
  return OVERLAY_TYPE.NONE;
34
42
  }
35
43
 
@@ -80,7 +88,8 @@ export class OverlayDetector {
80
88
  return (
81
89
  this.isInside &&
82
90
  (this._detection.type === OVERLAY_TYPE.MODAL ||
83
- this._detection.type === OVERLAY_TYPE.DIALOG)
91
+ this._detection.type === OVERLAY_TYPE.DIALOG ||
92
+ this._detection.type === OVERLAY_TYPE.SLDSMODAL)
84
93
  );
85
94
  }
86
95
 
@@ -1,2 +1,11 @@
1
1
  /* @import 'lightning/sldsCommon';
2
2
  @import './tooltip.slds.css'; */
3
+
4
+ /* Fix for tooltip alignment issue, for details see: W-11677142
5
+ *
6
+ * fix-tooltip_alignment - the custom class that edits min-width
7
+ */
8
+
9
+ .fix-popover_tooltip_alignment {
10
+ min-width: inherit;
11
+ }
@@ -102,7 +102,9 @@ export default class LightningPrimitiveBubble extends LightningElement {
102
102
 
103
103
  // compute class value for this bubble
104
104
  get computedPopoverClass() {
105
- const classes = classSet('slds-popover').add('slds-popover_tooltip');
105
+ const classes = classSet('slds-popover')
106
+ .add('slds-popover_tooltip')
107
+ .add('fix-popover_tooltip_alignment'); // fix for W-11677142
106
108
 
107
109
  // show or hide bubble
108
110
  classes.add({
@@ -7,6 +7,7 @@
7
7
  onopen={handleMenuOpen}
8
8
  is-loading={_isLoadingActions}
9
9
  loading-state-alternative-text={spinnerAlternateText}
10
+ tab-index={internalTabIndex}
10
11
  >
11
12
  <template for:each={_actions} for:item="action">
12
13
  <lightning-menu-item
@@ -33,13 +33,13 @@ export default class PrimitiveCellActions extends LightningElement {
33
33
  static delegatesFocus = true;
34
34
  _isLoadingActions;
35
35
  _menuAlignment = DEFAULT_MENU_ALIGNMENT;
36
- _internalTabIndex = false;
37
36
 
38
37
  /************************** PUBLIC ATTRIBUTES ***************************/
39
38
 
40
39
  @api rowKeyValue;
41
40
  @api colKeyValue;
42
41
  @api rowActions;
42
+ @api internalTabIndex;
43
43
 
44
44
  /**
45
45
  * Defines the current menu alignment
@@ -11,12 +11,26 @@ const i18n = {
11
11
  };
12
12
 
13
13
  export default class PrimitiveCellCheckbox extends PrimitiveDatatableCell {
14
+ _columnHeaderId = '';
14
15
  @api rowIndex = 0;
15
16
  @api isSelected = false;
16
17
  @api isDisabled = false;
17
18
  @api type = 'checkbox';
18
19
  @api dtContextId;
19
- @api columnHeaderId = ''; //required as a part for aria-labelledby
20
+ @api
21
+ get columnHeaderId() {
22
+ return this._columnHeaderId;
23
+ }
24
+
25
+ set columnHeaderId(id) {
26
+ this._columnHeaderId = id || '';
27
+ const labelId = this.computedLabelId;
28
+ if (labelId) {
29
+ synchronizeAttrs(this.template.querySelector('input'), {
30
+ 'aria-labelledby': `${labelId} ${this._columnHeaderId}`,
31
+ });
32
+ }
33
+ }
20
34
 
21
35
  render() {
22
36
  if (this.type === 'radio') {
@@ -8,6 +8,7 @@
8
8
  <template if:true={hasTreeData}>
9
9
  <lightning-primitive-treegrid-cell-toggle row-key-value={rowKeyValue}
10
10
  col-key-value={colKeyValue}
11
+ display-value={displayValue}
11
12
  value={value}
12
13
  has-children={typeAttribute21}
13
14
  is-expanded={typeAttribute22}
@@ -33,6 +34,7 @@
33
34
  row-key-value={rowKeyValue}
34
35
  col-key-value={colKeyValue}
35
36
  tabindex={internalTabIndex}
37
+ internal-tab-index={internalTabIndex}
36
38
  menu-alignment={typeAttribute0}
37
39
  row-actions={typeAttribute1}>
38
40
  </lightning-primitive-cell-actions>
@@ -278,7 +280,7 @@
278
280
  </button>
279
281
  </template>
280
282
  <!-- TODO: displayReadOnlyIcon is true only when the cell's "editable" property is false and its "displayReadOnlyIcon"
281
- property is true. The markup in this template therefore cannot be rendered concurrently with the template above that checks
283
+ property is true. The markup in this template therefore cannot be rendered concurrently with the template above that checks
282
284
  the editable property. -->
283
285
  <template if:true={shouldDisplayReadOnlyIcon}>
284
286
  <!-- TODO: Update the svg-classes once the SLDS team updates their read only icon design to not use classes that have the word 'button'
@@ -35,6 +35,7 @@ export default class PrivateCellFactory extends PrimitiveDatatableCell {
35
35
  @api types;
36
36
  @api alignment;
37
37
  @api value;
38
+ @api displayValue;
38
39
  @api iconName;
39
40
  @api iconLabel;
40
41
  @api iconPosition;
@@ -1,4 +1,5 @@
1
1
  import labelChooseARow from '@salesforce/label/LightningDatatable.chooseARow';
2
+ import labelChooseARowSelectAll from '@salesforce/label/LightningDatatable.chooseARowSelectAll';
2
3
  import labelSelectAll from '@salesforce/label/LightningDatatable.selectAll';
3
4
  import labelSort from '@salesforce/label/LightningDatatable.sort';
4
5
  import labelSortAsc from '@salesforce/label/LightningDatatable.sortAsc';
@@ -15,6 +16,7 @@ import nonsortable from './nonsortableHeader.html';
15
16
 
16
17
  const i18n = {
17
18
  chooseARow: labelChooseARow,
19
+ chooseARowSelectAll: labelChooseARowSelectAll,
18
20
  selectAll: labelSelectAll,
19
21
  sort: labelSort,
20
22
  sortAsc: labelSortAsc,
@@ -201,6 +203,17 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
201
203
  );
202
204
  }
203
205
 
206
+ /**
207
+ * Computes column header label
208
+ *
209
+ * @return {string} The computed column header label
210
+ */
211
+ get computedColumnHeaderLabel() {
212
+ return this.showCheckbox
213
+ ? this.i18n.chooseARowSelectAll
214
+ : this.i18n.chooseARow;
215
+ }
216
+
204
217
  /**
205
218
  * Returns the header's aria role
206
219
  *
@@ -316,6 +329,22 @@ export default class PrimitiveHeaderFactory extends PrimitiveDatatableCell {
316
329
  if (this.isSelectableHeader && this.showCheckbox) {
317
330
  this.updateBulkSelectionCheckbox();
318
331
  }
332
+ if (this.isSelectableHeader) {
333
+ const columnHeaderId = this.computedColumnHeaderId;
334
+ const columnHeaderEvent = new CustomEvent('privatecolumnheaderid', {
335
+ detail: columnHeaderId,
336
+ });
337
+ this.dispatchEvent(columnHeaderEvent);
338
+ }
339
+ }
340
+
341
+ disconnectedCallback() {
342
+ if (this.isSelectableHeader) {
343
+ const columnHeaderEvent = new CustomEvent('privatecolumnheaderid', {
344
+ detail: null,
345
+ });
346
+ this.dispatchEvent(columnHeaderEvent);
347
+ }
319
348
  }
320
349
 
321
350
  /************************** EVENT HANDLERS ***************************/
@@ -1,9 +1,11 @@
1
1
  <template>
2
+ <span id="column-group-header" class="slds-assistive-text" data-column-header>
3
+ {computedColumnHeaderLabel}
4
+ </span>
2
5
  <!-- Header Content -->
3
6
  <div class="slds-th__action slds-th__action_form slds-cell-fixed" style={columnStyles}>
4
7
  <template if:true={showCheckbox}>
5
8
  <span class="slds-checkbox">
6
-
7
9
  <!-- Selectable Checkbox -->
8
10
  <input
9
11
  type="checkbox"
@@ -23,10 +25,5 @@
23
25
  </label>
24
26
  </span>
25
27
  </template>
26
- <template if:false={showCheckbox}>
27
- <span id="column-group-header" class="slds-assistive-text" data-column-header>
28
- {i18n.chooseARow}
29
- </span>
30
- </template>
31
28
  </div>
32
29
  </template>
@@ -2,7 +2,7 @@ import labelCollapseBranch from '@salesforce/label/LightningPrimitiveCellTree.co
2
2
  import labelExpandBranch from '@salesforce/label/LightningPrimitiveCellTree.expandBranch';
3
3
  import { LightningElement, api } from 'lwc';
4
4
  import { classSet, formatLabel } from 'lightning/utils';
5
- import { normalizeBoolean } from 'lightning/utilsPrivate';
5
+ import { normalizeString, normalizeBoolean } from 'lightning/utilsPrivate';
6
6
 
7
7
  const i18n = {
8
8
  collapseBranch: labelCollapseBranch,
@@ -13,6 +13,7 @@ export default class PrivateTreeGridCellToggle extends LightningElement {
13
13
  @api rowKeyValue;
14
14
  @api colKeyValue;
15
15
  @api value;
16
+ @api displayValue;
16
17
 
17
18
  _expanded = false;
18
19
  _hasChildren = false;
@@ -60,10 +61,14 @@ export default class PrivateTreeGridCellToggle extends LightningElement {
60
61
  }
61
62
 
62
63
  get buttonTitle() {
64
+ let title =
65
+ normalizeString(this.displayValue) !== ''
66
+ ? this.displayValue
67
+ : this.value;
63
68
  if (this.isExpanded) {
64
- return formatLabel(i18n.collapseBranch, this.value);
69
+ return formatLabel(i18n.collapseBranch, title);
65
70
  }
66
- return formatLabel(i18n.expandBranch, this.value);
71
+ return formatLabel(i18n.expandBranch, title);
67
72
  }
68
73
 
69
74
  handleChevronClick() {
@@ -33,7 +33,7 @@ export default class LightningProgressIndicator extends LightningElement {
33
33
 
34
34
  /**
35
35
  * Changes the appearance of the progress indicator for the base type only.
36
- * Valid values are base or shaded. The shaded variant adds a light gray border to the step indicators.
36
+ * Valid values are base or shade. The shade variant adds a light gray border to the step indicators.
37
37
  * The default is base.
38
38
  * @type {string}
39
39
  * @default base
@@ -58,7 +58,7 @@
58
58
  </div>
59
59
 
60
60
  <template if:true={_helpMessage}>
61
- <div data-help-message id="help-message" class="slds-form-element__help">{_helpMessage}</div>
61
+ <div data-help-message id="help-message" role="alert" class="slds-form-element__help">{_helpMessage}</div>
62
62
  </template>
63
63
 
64
64
  </fieldset>
@@ -102,6 +102,12 @@ export default class LightningTextarea extends LightningElement {
102
102
  @track _helpMessage;
103
103
  @track _fieldLevelHelp;
104
104
 
105
+ /**
106
+ * Aria Described by value on parent lighting-textarea
107
+ * @type {string}
108
+ */
109
+ @api ariaDescribedBy;
110
+
105
111
  connectedCallback() {
106
112
  this.classList.add('slds-form-element');
107
113
  this.updateClassList();
@@ -433,7 +439,13 @@ export default class LightningTextarea extends LightningElement {
433
439
 
434
440
  get computedUniqueHelpElementId() {
435
441
  const helpMessage = this.template.querySelector('[data-help-message]');
436
- return getRealDOMId(helpMessage);
442
+ let spaceSeperatedDescribedByIds = getRealDOMId(helpMessage);
443
+ if (this.ariaDescribedBy && spaceSeperatedDescribedByIds) {
444
+ spaceSeperatedDescribedByIds += ` ${this.ariaDescribedBy}`;
445
+ } else if (this.ariaDescribedBy) {
446
+ spaceSeperatedDescribedByIds = this.ariaDescribedBy;
447
+ }
448
+ return spaceSeperatedDescribedByIds;
437
449
  }
438
450
 
439
451
  _setInputValue(value) {