Inital code commit
Some checks failed
Build, Test, and Publish (to Private NPM Registry) UI Components Library / publish (push) Failing after 52m26s

This commit is contained in:
Alan Bridgeman 2026-05-13 01:39:35 -05:00
commit 5024375e20
32 changed files with 5379 additions and 0 deletions

View file

@ -0,0 +1,19 @@
# Accessible Drawer
Drawers allow for the opening and closing of information sections.
## Usage
to use this component:
```ejs
<%- useComponent('drawer', { id: 'example-drawer', content: `<div><h2>Hello World!</h2><p>This is a drawer!</p></div>` }) %>
```
## Parameters
| Parameter | type | Description |
| -------------------- | ------- | ------------------------------------------------------------ |
| `id` | string | The ID of the drawer |
| `label` | HTML | The label on the drawer's "handle" (button) |
| `content` | HTML | The content of the drawer |
| `drawerExtraStyles` | Various | Extra CSS to be included in the components Shadow DOM |
| `drawerExtraScripts` | Various | Extra JS scripts to be included in the components Shadow DOM |

View file

@ -0,0 +1,25 @@
.drawer {
display: flex;
width: 100%;
flex-direction: column;
}
.drawer-header {
padding: 0.5rem 1rem;
cursor: pointer;
border: 1px solid light-dark(#000000, #FFFFFF);
}
.drawer-header:hover, .drawer-header:focus {
background-color: light-dark(#000000, #FFFFFF);
color: light-dark(#FFFFFF, #000000);
}
.drawer-contents {
padding: 0.5rem 1rem;
}
.hidden {
display: none;
visibility: hidden;
}

View file

@ -0,0 +1,62 @@
<ba-drawer>
<%# Because of complexities with web components and specifically more legacy support and the `createTemplateInJS` method, we need to pass the drawer data available in EJS to the JavaScript for the web component (easiest way was via a script tag) %>
<!-- JSON config data so that `createTemplateInJS` can recreate the drawer DOM structure accurately if needed -->
<script type="application/json" data-drawer-config>
<%- JSON.stringify({
drawerId: id,
drawerExtraStyles: typeof drawerExtraStyles !== 'undefined' ? (Array.isArray(drawerExtraStyles) ? drawerExtraStyles : [drawerExtraStyles]) : [],
drawerExtraScripts: typeof drawerExtraScripts !== 'undefined' ? (Array.isArray(drawerExtraScripts) ? drawerExtraScripts : [drawerExtraScripts]) : [],
componentsStyleHref
}) %>
</script>
<template shadowrootmode="open">
<!-- Styles -->
<!-- Component Specific Styling -->
<!-- Component Styling (Part of Component Library CSS) -->
<link rel="stylesheet" type="text/css" href="<%= componentsStyleHref %>">
<!-- END: Component Specific Styling -->
<!-- Additional Styles -->
<% if (typeof drawerExtraStyles !== 'undefined') { %>
<% const drawerStyles = Array.isArray(drawerExtraStyles) ? drawerExtraStyles : [drawerExtraStyles]; %>
<% for (let style of drawerStyles) { %>
<link rel="stylesheet" type="text/css" href="/css/<%= style %>.css">
<% } %>
<% } %>
<!-- END: Additional Styles -->
<!-- END: Styles -->
<!-- Scripts -->
<% if (typeof drawerExtraScripts !== 'undefined') { %>
<% const drawerScripts = Array.isArray(drawerExtraScripts) ? drawerExtraScripts : [drawerExtraScripts]; %>
<% for (let script of drawerScripts) { %>
<% if(typeof script === 'object') { %>
<script type="<%= typeof script.module === 'boolean' && script.module ? 'module' : 'application/javascript' %>" src="<%= script.script %>"></script>
<% } else if(typeof script === 'string' && (script.startsWith('http') || script.startsWith('https'))) { %>
<script type="<%= script.endsWith('.mjs') ? 'module' : 'application/javascript' %>" src="<%= script %>"></script>
<% } else if(typeof script === 'string') { %>
<script type="<%= script.endsWith('.mjs') ? 'module' : 'application/javascript' %>" src="/js/<%= script.endsWith('.mjs') ? script : script + '.js' %>"></script>
<% } %>
<% } %>
<% } %>
<!-- END: Scripts -->
<div id="<%= id %>" class="drawer">
<div id="<%= id %>-drawer-header" role="button" class="drawer-header" tabindex="0" aria-expanded="false" aria-controls="<%= id %>-drawer-contents">
<slot name="drawer-header"></slot>
</div>
<div id="<%= id %>-drawer-contents" class="drawer-contents hidden">
<slot name="drawer-contents"></slot>
</div>
</div>
</template>
<div slot="drawer-header">
<%- label %>
</div>
<div slot="drawer-contents">
<%- content %>
</div>
</ba-drawer>

View file

@ -0,0 +1,180 @@
/**
* Drawer Web Component
*
* A simple drawer component that toggles the visibility of its content when the header is clicked or activated with the keyboard.
*/
class Drawer extends HTMLElement {
constructor() {
super();
// Event handler bindings for click and keydown events on the drawer handle (button)
this._handleClick = this._clicked.bind(this);
this._handleKeyDown = this._keyDown.bind(this)
}
// ----------------------
// Private Event Handlers
// ----------------------
/** Click handler for the drawer "handle" (button) */
_clicked(event) {
event.preventDefault();
event.currentTarget.setAttribute('aria-expanded', event.currentTarget.getAttribute('aria-expanded') === 'true' ? 'false' : 'true');
this.contentDiv.classList.toggle('hidden');
}
/** Keydown handler for the drawer "handle" (button) */
_keyDown(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
event.currentTarget.setAttribute('aria-expanded', event.currentTarget.getAttribute('aria-expanded') === 'true' ? 'false' : 'true');
this.contentDiv.classList.toggle('hidden');
}
}
// -------------------------------
// Web Component Lifecycle Methods
// -------------------------------
/**
* Does initial setup and adds event listeners for interactivity
*
* `connectedCallback` is a lifecycle method in web components that runs when the custom element is inserted into the document's Document Object Model (DOM).
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element's constructor() but before the element's children are necessarily connected or fully rendered.
* Purpose: It is the ideal place to set up tasks that should only occur when the element is actually present in the live document. Common uses include:
*/
connectedCallback() {
const internals = this.attachInternals();
this.shadow = this.shadowRoot;
if (!this.shadow) {
this.shadow = this.attachShadow({ mode: 'open' });
// Defer execution until the browser finishes parsing the children
setTimeout(() => {
// Recreate the template using the shadow DOM that is only available through JavaScript
this.createTemplateInJS(this.shadow);
}, 0);
}
setTimeout(() => {
// Native Popover handles the click, enter, space, and dismiss logic.
// You only need event listeners here if you want to trigger
// custom analytics or highly specific behavior on open/close.
const drawerHandle = this.shadow.querySelector('[aria-controls]');
if (drawerHandle) {
// Get the content div that the drawer handle controls so we can toggle it in the click and keydown handlers
this.contentDiv = this.shadow.querySelector(`#${drawerHandle.getAttribute('aria-controls')}`);
// Add event listeners to the drawer handle (button)
drawerHandle.addEventListener('click', this._handleClick);
drawerHandle.addEventListener('keydown', this._handleKeyDown);
}
}, 0);
}
/**
* Cleans up event listeners when the component is removed from the DOM
*
* `disconnectedCallback` is a lifecycle method in web components that runs when the custom element is removed from the document's DOM.
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element is removed from the DOM but before it is garbage collected.
* Purpose: It is the ideal place to clean up any resources or event listeners that were set up in `connectedCallback`.
*
* Common uses include:
* - Removing event listeners to prevent memory leaks
* - Clearing timers or intervals
* - Disconnecting from external data sources or APIs
*/
disconnectedCallback() {
const drawerHandle = this.shadow.querySelector('[aria-controls]');
if (drawerHandle) {
drawerHandle.removeEventListener('click', this._handleClick);
drawerHandle.removeEventListener('keydown', this._handleKeyDown);
}
}
/**
* Recreate the template in the shadow DOM through JavaScript instead of relying on the `shadowrootmode` attribute
*
* @param {ShadowRoot} shadow The shadow DOM to attach the template to
*/
createTemplateInJS(shadow) {
// Retrieve the scoped data island
const configScript = this.querySelector('script[data-drawer-config]');
if (!configScript) {
console.error('Drawer configuration missing. Cannot build JS fallback.');
return;
}
const config = JSON.parse(configScript.textContent);
const { drawerExtraStyles, drawerExtraScripts, drawerId, componentsStyleHref } = config;
// Create and append the link tag for the components library CSS (including component specific styles)
const drawerStyle = document.createElement('link');
drawerStyle.rel = 'stylesheet';
drawerStyle.type = 'text/css';
drawerStyle.href = componentsStyleHref;
shadow.appendChild(drawerStyle);
// Create additional link tags for any extra CSS files to include
drawerExtraStyles.forEach(style => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = `/css/${style}.css`;
shadow.appendChild(link);
});
// Create and append script tags for any extra JavaScript files to include
drawerExtraScripts.forEach(script => {
const scriptElem = document.createElement('script');
scriptElem.type = typeof script === 'object' && typeof script.module === 'boolean' && script.module ? 'module' : typeof script === 'string' && script.endsWith('.mjs') ? 'module' : 'application/javascript';
scriptElem.src = typeof script === 'object' ? script.script.startsWith('http') ? script.script : `/js/${script.script.endsWith('.mjs') ? script.script : script.script + '.js'}` : script.startsWith('http') ? script : `/js/${script.endsWith('.mjs') ? script : script + '.js'}`;
shadow.appendChild(scriptElem);
});
// Create the container div for the drawer component
const drawerContainerDiv = document.createElement('div');
drawerContainerDiv.id = drawerId;
drawerContainerDiv.classList.add('drawer');
// Create the button element for the tooltip trigger
const drawerBtnElem = document.createElement('div');
drawerBtnElem.id = `${drawerId}-drawer-header`;
drawerBtnElem.role = 'button';
drawerBtnElem.classList.add('drawer-header');
drawerBtnElem.tabIndex = 0;
drawerBtnElem.setAttribute('aria-expanded', 'false');
drawerBtnElem.setAttribute('aria-controls', `${drawerId}-drawer-contents`);
const drawerHeaderSlotElem = document.createElement('slot');
drawerHeaderSlotElem.name = 'drawer-header';
drawerBtnElem.appendChild(drawerHeaderSlotElem);
drawerContainerDiv.appendChild(drawerBtnElem);
// Create the div that will contain the drawer content
const contentDiv = document.createElement('div');
contentDiv.id = `${drawerId}-drawer-contents`;
contentDiv.classList.add('drawer-contents', 'hidden');
const contentSlotElem = document.createElement('slot');
contentSlotElem.name = 'drawer-contents';
contentDiv.appendChild(contentSlotElem);
drawerContainerDiv.appendChild(contentDiv);
// Finally, append the entire drawer container div to the shadow DOM of the component
shadow.appendChild(drawerContainerDiv);
}
}
customElements.define('ba-drawer', Drawer);

7
src/components/import.css vendored Normal file
View file

@ -0,0 +1,7 @@
/* Import Open Props (or specific modules if you don't want the whole library) */
@import "open-props/index.css";
@import "open-props/normalize.css";
@import "./library.css";
/* Component Styles */

View file

@ -0,0 +1,10 @@
/* Define Brand Overrides */
:root {
/* Overriding an Open Prop with Bridgeman Accessible brand color */
--brand-primary: var(--indigo-7); /* Or your exact hex code */
--font-sans: 'Your Brand Font', system-ui, sans-serif;
/* You can even alias them to the generic vars your components use */
--tooltip-bg: var(--gray-9);
}

View file

@ -0,0 +1,19 @@
# Accessible Tooltip
Where many tooltips can be incredibly frustrated and inaccessible in a variety of ways to different users (ex. only available on hover so screen magnifier users struggle, not properly setup for screen readers, only icon or text not multi-modal, etc...). This component endeavors to create one that addresses these issues. It uses the browser native Popover API in conjunction with good semantics and well structured client JS code to create something that hopefully works for everyone.
## Usage
to use this component:
```ejs
<%- useComponent('tooltip', { id: 'example-tip', srText: 'Example Tooltip', content: `<div><h2>Hello World!</h2><p>This is a tooltip!</p></div>` }) %>
```
## Parameters
| Parameter | Description |
| --------------------- | ------------------------------------------------------------ |
| `id` | The ID of the tooltip |
| `content` | The content of the tooltip |
| `srText` | The screen reader text used for the tooltip |
| `tooltipExtraStyles` | Extra CSS to be included in the components Shadow DOM |
| `tooltipExtraScripts` | Extra JS scripts to be included in the components Shadow DOM |

View file

@ -0,0 +1,88 @@
/* AAA Compliant Encapsulated Styles */
:host {
display: inline-block;
--primary-color: #113c9c;
--text-main: #0f172a;
--radius-md: 0.5rem;
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--focus-ring: #b91c1c;
}
.tool-tip-icon {
position: relative;
display: inline-flex;
}
.popover-btn {
background: none;
border: none;
padding: 0;
cursor: pointer;
color: var(--primary-color);
font-size: 1rem;
display: flex;
align-items: center;
min-width: 44px; /* AAA touch target */
min-height: 44px; /* AAA touch target */
justify-content: center;
border-radius: 4px;
/* Declare this button as an anchor point */
anchor-name: --tooltip-trigger;
}
.popover-btn:focus-visible {
outline: 3px solid var(--focus-ring);
outline-offset: 2px;
}
.tool-tip-content {
/* Popover API handles display/hide natively */
margin: 0;
border: none;
background-color: var(--text-main);
color: #ffffff;
text-align: left;
padding: 1rem;
border-radius: var(--radius-md);
font-size: 0.875rem;
font-weight: 400;
line-height: 1.6;
box-shadow: var(--shadow-md);
width: max-content;
max-width: 280px;
}
/* Tooltip positioning overrides for native popover */
.tool-tip-content:popover-open {
position: absolute;
inset: auto;
/*top: auto;
left: auto;
right: auto;
bottom: auto;
transform: translateX(-50%) translateY(-100%);*/
/* Tell the popover to tether to that specific anchor */
/*position-anchor: --tooltip-trigger;*/
/* Position the bottom of the popover to the top of the anchor */
/* bottom: anchor(top); */
/* Center it horizontally */
/* justify-self: anchor-center; */
/* Add the 10px gap */
/* margin-bottom: 10px; */
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; /* Prevents text from wrapping */
}

View file

@ -0,0 +1,63 @@
<ba-tooltip>
<%# Because of complexities with web components and specifically more legacy support and the `createTemplateInJS` method, we need to pass the tooltip data available in EJS to the JavaScript for the web component (easiest way was via a script tag) %>
<!-- JSON config data so that `createTemplateInJS` can recreate the tooltip DOM structure accurately if needed -->
<script type="application/json" data-tooltip-config>
<%- JSON.stringify({
tooltipId: id,
tooltipExtraStyles: typeof tooltipExtraStyles !== 'undefined' ? (Array.isArray(tooltipExtraStyles) ? tooltipExtraStyles : [tooltipExtraStyles]) : [],
tooltipExtraScripts: typeof tooltipExtraScripts !== 'undefined' ? (Array.isArray(tooltipExtraScripts) ? tooltipExtraScripts : [tooltipExtraScripts]) : [],
componentsStyleHref
}) %>
</script>
<template shadowrootmode="open">
<!-- Styles -->
<!-- Component Specific Styling -->
<!-- Component Styling (Part of Component Library CSS) -->
<link rel="stylesheet" type="text/css" href="<%= componentsStyleHref %>">
<!-- END: Component Specific Styling -->
<!-- Additional Styles -->
<% if (typeof tooltipExtraStyles !== 'undefined') { %>
<% const tooltipStyles = Array.isArray(tooltipExtraStyles) ? tooltipExtraStyles : [tooltipExtraStyles]; %>
<% for (let style of tooltipStyles) { %>
<link rel="stylesheet" type="text/css" href="/css/<%= style %>.css">
<% } %>
<% } %>
<!-- END: Additional Styles -->
<!-- END: Styles -->
<!-- Scripts -->
<% if (typeof tooltipExtraScripts !== 'undefined') { %>
<% const tooltipScripts = Array.isArray(tooltipExtraScripts) ? tooltipExtraScripts : [tooltipExtraScripts]; %>
<% for (let script of tooltipScripts) { %>
<% if(typeof script === 'object') { %>
<script type="<%= typeof script.module === 'boolean' && script.module ? 'module' : 'application/javascript' %>" src="<%= script.script %>"></script>
<% } else if(typeof script === 'string' && (script.startsWith('http') || script.startsWith('https'))) { %>
<script type="<%= script.endsWith('.mjs') ? 'module' : 'application/javascript' %>" src="<%= script %>"></script>
<% } else if(typeof script === 'string') { %>
<script type="<%= script.endsWith('.mjs') ? 'module' : 'application/javascript' %>" src="/js/<%= script.endsWith('.mjs') ? script : script + '.js' %>"></script>
<% } %>
<% } %>
<% } %>
<!-- END: Scripts -->
<div class="tool-tip-icon">
<button id="<%= id %>" class="popover-btn" popovertarget="<%= id %>-content">
<slot name="tooltip-btn-content"></slot>
</button>
<div id="<%= id %>-content" popover class="tool-tip-content">
<slot name="tooltip-content"></slot>
</div>
</div>
</template>
<div slot="tooltip-btn-content">
<span class="sr-only"><%= srText %></span>
<i class="fa-solid fa-circle-info"></i>
</div>
<div slot="tooltip-content">
<%- content %>
</div>
</ba-tooltip>

View file

@ -0,0 +1,202 @@
/**
* Tooltip Web Component
*
* A simple tooltip component that toggles the visibility of its content when the button is clicked or activated with the keyboard.
* This component uses the browser native Popover API to create a tooltip that is accessible, modern, and easy to manage.
* The component also demonstrates how to use JavaScript to position the tooltip above the button and how to listen for open/close events on the popover.
*/
class Tooltip extends HTMLElement {
constructor() {
super();
// Event handler bindings for click and keydown events on the tooltip button
//this._handleClick = this._clicked.bind(this);
//this._handleKeyDown = this._keyDown.bind(this)
this._handleCustomLogic = this._customLogic.bind(this);
}
// ----------------------
// Private Event Handlers
// ----------------------
/** Click handler for the tooltip button */
/*_clicked(event) {
event.preventDefault();
this.shadow.querySelector('.tool-tip-content').classList.toggle('visible');
}*/
/** Keydown handler for the tooltip button */
/*_keyDown(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
this.shadow.querySelector('.tool-tip-content').classList.toggle('visible');
}
}*/
_customLogic(event) {
// event.newState will be "open" or "closed"
// Useful if you need to log analytics when someone reads the tooltip
// console.log(`Tooltip is now ${event.newState}`);
const popover = event.target;
if (event.newState === "open") {
// Measure the physical boundaries of the Web Component (the Light DOM host)
const hostRect = this.getBoundingClientRect();
// Measure the physical boundaries of the Popover itself
const popoverRect = popover.getBoundingClientRect();
// Calculate the exact X/Y coordinates to center it above the button
// We add scrollX/scrollY just in case the page is scrolled
const topPosition = hostRect.top + window.scrollY - popoverRect.height - 10;
const leftPosition = hostRect.left + window.scrollX + (hostRect.width / 2) - (popoverRect.width / 2);
// Force the physical coordinates onto the Top Layer element
popover.style.margin = '0'; // Popovers default to margin: auto which ruins positioning
popover.style.top = `${topPosition}px`;
popover.style.left = `${leftPosition}px`;
}
}
// -------------------------------
// Web Component Lifecycle Methods
// -------------------------------
/**
* Does initial setup and adds event listeners for interactivity
*
* `connectedCallback` is a lifecycle method in web components that runs when the custom element is inserted into the document's Document Object Model (DOM).
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element's constructor() but before the element's children are necessarily connected or fully rendered.
* Purpose: It is the ideal place to set up tasks that should only occur when the element is actually present in the live document. Common uses include:
*/
connectedCallback() {
const internals = this.attachInternals();
this.shadow = this.shadowRoot;
if (!this.shadow) {
this.shadow = this.attachShadow({ mode: 'open' });
// FIX: Defer execution until the browser finishes parsing the children
setTimeout(() => {
// Recreate the template using the shadow DOM that is only available through JavaScript
this.createTemplateInJS(this.shadow);
}, 0);
}
setTimeout(() => {
//this.shadow.querySelector('.popover-btn').addEventListener('click', this._handleClick);
//this.shadow.querySelector('.popover-btn').addEventListener('keydown', this._handleKeyDown);
// Native Popover handles the click, enter, space, and dismiss logic.
// You only need event listeners here if you want to trigger
// custom analytics or highly specific behavior on open/close.
const popoverContent = this.shadow.querySelector('[popover]');
if (popoverContent) {
popoverContent.addEventListener('toggle', this._handleCustomLogic);
}
}, 0);
}
/**
* Cleans up event listeners when the component is removed from the DOM
*
* `disconnectedCallback` is a lifecycle method in web components that runs when the custom element is removed from the document's DOM.
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element is removed from the DOM but before it is garbage collected.
* Purpose: It is the ideal place to clean up any resources or event listeners that were set up in `connectedCallback`.
*
* Common uses include:
* - Removing event listeners to prevent memory leaks
* - Clearing timers or intervals
* - Disconnecting from external data sources or APIs
*/
disconnectedCallback() {
//this.shadow.querySelector('.popover-btn').removeEventListener('click', this._handleClick);
//this.shadow.querySelector('.popover-btn').removeEventListener('keydown', this._handleKeyDown);
const popoverContent = this.shadow.querySelector('[popover]');
if (popoverContent) {
popoverContent.removeEventListener('toggle', this._handleCustomLogic);
}
}
/**
* Recreate the template in the shadow DOM through JavaScript instead of relying on the `shadowrootmode` attribute
*
* @param {ShadowRoot} shadow The shadow DOM to attach the template to
*/
createTemplateInJS(shadow) {
// Retrieve the scoped data island
const configScript = this.querySelector('script[data-tooltip-config]');
if (!configScript) {
console.error('Tooltip configuration missing. Cannot build JS fallback.');
return;
}
const config = JSON.parse(configScript.textContent);
const { tooltipExtraStyles, tooltipExtraScripts, tooltipId, componentsStyleHref } = config;
// Create and append the link tag for the components library CSS (including component specific styles)
const tooltipStyle = document.createElement('link');
tooltipStyle.rel = 'stylesheet';
tooltipStyle.type = 'text/css';
tooltipStyle.href = componentsStyleHref;
shadow.appendChild(tooltipStyle);
// Create additional link tags for any extra CSS files to include
tooltipExtraStyles.forEach(style => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = `/css/${style}.css`;
shadow.appendChild(link);
});
// Create and append script tags for any extra JavaScript files to include
tooltipExtraScripts.forEach(script => {
const scriptElem = document.createElement('script');
scriptElem.type = typeof script === 'object' && typeof script.module === 'boolean' && script.module ? 'module' : typeof script === 'string' && script.endsWith('.mjs') ? 'module' : 'application/javascript';
scriptElem.src = typeof script === 'object' ? script.script.startsWith('http') ? script.script : `/js/${script.script.endsWith('.mjs') ? script.script : script.script + '.js'}` : script.startsWith('http') ? script : `/js/${script.endsWith('.mjs') ? script : script + '.js'}`;
shadow.appendChild(scriptElem);
});
// Create the container div for the tooltip component
const tooltipContainerDiv = document.createElement('div');
tooltipContainerDiv.classList.add('tool-tip-icon');
// Create the button element for the tooltip trigger
const btnElem = document.createElement('button');
btnElem.id = tooltipId;
btnElem.classList.add('popover-btn');
btnElem.setAttribute('popovertarget', `${tooltipId}-content`);
const btnSlotElem = document.createElement('slot');
btnSlotElem.name = 'tooltip-btn-content';
btnElem.appendChild(btnSlotElem);
tooltipContainerDiv.appendChild(btnElem);
// Create the div that will contain the tooltip content
const contentDiv = document.createElement('div');
contentDiv.id = `${tooltipId}-content`;
contentDiv.classList.add('tool-tip-content');
contentDiv.setAttribute('popover', '');
const contentSlotElem = document.createElement('slot');
contentSlotElem.name = 'tooltip-content';
contentDiv.appendChild(contentSlotElem);
tooltipContainerDiv.appendChild(contentDiv);
// Finally, append the entire tooltip container div to the shadow DOM of the component
shadow.appendChild(tooltipContainerDiv);
}
}
customElements.define('ba-tooltip', Tooltip);