From 4a6b733113488e26d4892981a057e38559bd6d53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=A7=84=ED=98=B8?=
 <52993842+birariro@users.noreply.github.com>
Date: Thu, 25 May 2023 17:47:04 +0900
Subject: [PATCH 01/49] CTable put 0 data in but not add

CTable put 0 data in but not add
---
 packages/coreui-react/src/components/table/CTable.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/table/CTable.tsx b/packages/coreui-react/src/components/table/CTable.tsx
index cc99a4e1..059363dc 100644
--- a/packages/coreui-react/src/components/table/CTable.tsx
+++ b/packages/coreui-react/src/components/table/CTable.tsx
@@ -201,7 +201,7 @@ export const CTable = forwardRef<HTMLTableElement, CTableProps>(
                 <CTableRow {...(item._props && { ...item._props })} key={index}>
                   {columnNames &&
                     columnNames.map((colName: string, index: number) => {
-                      return item[colName] ? (
+                      return item[colName] !== undefined && item[colName] !== null ? (
                         <CTableDataCell
                           {...(item._cellProps && {
                             ...(item._cellProps['all'] && { ...item._cellProps['all'] }),

From d6ecc7460de3e80796a712884b023b03c0ed5b7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Holeczek?= <lukasz@holeczek.pl>
Date: Thu, 8 Jun 2023 12:29:09 +0200
Subject: [PATCH 02/49] Update CTable.tsx

It allows to pass empty empty column using null
---
 packages/coreui-react/src/components/table/CTable.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/table/CTable.tsx b/packages/coreui-react/src/components/table/CTable.tsx
index 059363dc..98edb5e1 100644
--- a/packages/coreui-react/src/components/table/CTable.tsx
+++ b/packages/coreui-react/src/components/table/CTable.tsx
@@ -201,7 +201,7 @@ export const CTable = forwardRef<HTMLTableElement, CTableProps>(
                 <CTableRow {...(item._props && { ...item._props })} key={index}>
                   {columnNames &&
                     columnNames.map((colName: string, index: number) => {
-                      return item[colName] !== undefined && item[colName] !== null ? (
+                      return item[colName] !== undefined ? (
                         <CTableDataCell
                           {...(item._cellProps && {
                             ...(item._cellProps['all'] && { ...item._cellProps['all'] }),

From 616a60db90f33bcad22384860c86e774b85426f8 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 28 Jun 2023 22:16:27 +0200
Subject: [PATCH 03/49] docs: update API documentation

---
 packages/docs/content/api/CDropdown.api.mdx        |  3 ++-
 packages/docs/content/api/CPopover.api.mdx         |  5 ++++-
 packages/docs/content/api/CProgress.api.mdx        |  3 ++-
 packages/docs/content/api/CProgressStacked.api.mdx | 10 ++++++++++
 packages/docs/content/api/CTooltip.api.mdx         | 11 +++++++----
 5 files changed, 25 insertions(+), 7 deletions(-)
 create mode 100644 packages/docs/content/api/CProgressStacked.api.mdx

diff --git a/packages/docs/content/api/CDropdown.api.mdx b/packages/docs/content/api/CDropdown.api.mdx
index 451f42fc..46230d01 100644
--- a/packages/docs/content/api/CDropdown.api.mdx
+++ b/packages/docs/content/api/CDropdown.api.mdx
@@ -13,7 +13,8 @@ import CDropdown from '@coreui/react/src/components/dropdown/CDropdown'
 | **component** | Component used for the root node. Either a string to use a HTML element or a component. | `string` \| `ComponentClass<any, any>` \| `FunctionComponent<any>` | div |
 | **dark** | Sets a darker color scheme to match a dark navbar. | `boolean` | - |
 | **direction** | Sets a specified  direction and location of the dropdown menu. | `'center'` \| `'dropup'` \| `'dropup-center'` \| `'dropend'` \| `'dropstart'` | - |
-| **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
+| **offset** | Offset of the dropdown menu relative to its target. | `[number, number]` | [0, 2] |
+| **onHide** **_4.9.0-beta.2+_** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
 | **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top-end'` \| `'top'` \| `'top-start'` \| `'bottom-end'` \| `'bottom'` \| `'bottom-start'` \| `'right-start'` \| `'right'` \| `'right-end'` \| `'left-start'` \| `'left'` \| `'left-end'` | bottom-start |
 | **popper** | If you want to disable dynamic positioning set this property to `true`. | `boolean` | true |
diff --git a/packages/docs/content/api/CPopover.api.mdx b/packages/docs/content/api/CPopover.api.mdx
index 0e991b9e..c373ba69 100644
--- a/packages/docs/content/api/CPopover.api.mdx
+++ b/packages/docs/content/api/CPopover.api.mdx
@@ -7,12 +7,15 @@ import CPopover from '@coreui/react/src/components/popover/CPopover'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
+| **animation** **_4.9.0-beta.2+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
+| **delay** **_4.9.0-beta.2+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0-beta.2+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
 | **offset** | Offset of the popover relative to its target. | `[number, number]` | [0, 8] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
-| **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top'` \| `'right'` \| `'bottom'` \| `'left'` | top |
+| **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top'` \| `'bottom'` \| `'right'` \| `'left'` | top |
 | **title** | Title node for your component. | `ReactNode` | - |
 | **trigger** | Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them. | `'hover'` \| `'focus'` \| `'click'` | click |
 | **visible** | Toggle the visibility of popover component. | `boolean` | - |
diff --git a/packages/docs/content/api/CProgress.api.mdx b/packages/docs/content/api/CProgress.api.mdx
index c7c4388f..e7d61f16 100644
--- a/packages/docs/content/api/CProgress.api.mdx
+++ b/packages/docs/content/api/CProgress.api.mdx
@@ -11,7 +11,8 @@ import CProgress from '@coreui/react/src/components/progress/CProgress'
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **color** | Sets the color context of the component to one of CoreUI’s themed colors. | `'primary'` \| `'secondary'` \| `'success'` \| `'danger'` \| `'warning'` \| `'info'` \| `'dark'` \| `'light'` \| `string` | - |
 | **height** | Sets the height of the component. If you set that value the inner `<CProgressBar>` will automatically resize accordingly. | `number` | - |
+| **progressBarClassName** **_4.9.0+_** | A string of all className you want applied to the `<CProgressBar/>` component. | `string` | - |
 | **thin** | Makes progress bar thinner. | `boolean` | - |
-| **value** | The percent to progress the ProgressBar (out of 100). | `number` | 0 |
+| **value** | The percent to progress the ProgressBar (out of 100). | `number` | - |
 | **variant** | Set the progress bar variant to optional striped. | `'striped'` | - |
 | **white** | Change the default color to white. | `boolean` | - |
diff --git a/packages/docs/content/api/CProgressStacked.api.mdx b/packages/docs/content/api/CProgressStacked.api.mdx
new file mode 100644
index 00000000..109af3cf
--- /dev/null
+++ b/packages/docs/content/api/CProgressStacked.api.mdx
@@ -0,0 +1,10 @@
+
+```jsx
+import { CProgressStacked } from '@coreui/react'
+// or
+import CProgressStacked from '@coreui/react/src/components/progress/CProgressStacked'
+```
+
+| Property | Description | Type | Default |
+| --- | --- | --- | --- |
+| **className** | A string of all className you want applied to the component. | `string` | - |
diff --git a/packages/docs/content/api/CTooltip.api.mdx b/packages/docs/content/api/CTooltip.api.mdx
index 010885cb..66f664e7 100644
--- a/packages/docs/content/api/CTooltip.api.mdx
+++ b/packages/docs/content/api/CTooltip.api.mdx
@@ -7,11 +7,14 @@ import CTooltip from '@coreui/react/src/components/tooltip/CTooltip'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
+| **animation** **_4.9.0-beta.2+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
-| **offset** | Offset of the popover relative to its target. | `[number, number]` | [0, 0] |
+| **delay** **_4.9.0-beta.2+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0-beta.2+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
+| **offset** | Offset of the tooltip relative to its target. | `[number, number]` | [0, 6] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
-| **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top'` \| `'right'` \| `'bottom'` \| `'left'` | top |
-| **trigger** | Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them. | `'hover'` \| `'focus'` \| `'click'` | hover |
-| **visible** | Toggle the visibility of popover component. | `boolean` | - |
+| **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top'` \| `'bottom'` \| `'right'` \| `'left'` | top |
+| **trigger** | Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them. | `'hover'` \| `'focus'` \| `'click'` | ['hover', 'focus'] |
+| **visible** | Toggle the visibility of tooltip component. | `boolean` | - |

From 7996d2b2efb84299712acca72c22641c3e2489c3 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 29 Jun 2023 10:10:12 +0200
Subject: [PATCH 04/49] chore: clean-up

---
 packages/docs/src/components/Header.tsx | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/packages/docs/src/components/Header.tsx b/packages/docs/src/components/Header.tsx
index 677847a6..70e4e58a 100644
--- a/packages/docs/src/components/Header.tsx
+++ b/packages/docs/src/components/Header.tsx
@@ -7,23 +7,10 @@ import {
   cibTwitter,
   cilCloudDownload,
   cilMenu,
-  cilSun,
-  cilMoon,
-  cilContrast,
   cilHandshake,
 } from '@coreui/icons'
 
-import {
-  CButton,
-  CDropdown,
-  CDropdownItem,
-  CDropdownMenu,
-  CDropdownToggle,
-  CHeader,
-  CHeaderNav,
-  CHeaderToggler,
-  CNavItem,
-} from '@coreui/react/src'
+import { CButton, CHeader, CHeaderNav, CHeaderToggler, CNavItem } from '@coreui/react/src'
 import { AppContext } from './../AppContext'
 
 const Header: FC = () => {

From 67450929bfd33ae6fe13248909c1aefcbf28e33f Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 29 Jun 2023 12:46:34 +0200
Subject: [PATCH 05/49] release: v4.9.0-rc.0

---
 README.md                                                   | 2 +-
 lerna.json                                                  | 2 +-
 packages/coreui-react/README.md                             | 2 +-
 packages/coreui-react/package.json                          | 2 +-
 packages/coreui-react/src/components/dropdown/CDropdown.tsx | 2 +-
 packages/coreui-react/src/components/popover/CPopover.tsx   | 6 +++---
 packages/coreui-react/src/components/tooltip/CTooltip.tsx   | 6 +++---
 packages/docs/content/api/CDropdown.api.mdx                 | 2 +-
 packages/docs/content/api/CPopover.api.mdx                  | 6 +++---
 packages/docs/content/api/CTooltip.api.mdx                  | 6 +++---
 packages/docs/package.json                                  | 2 +-
 11 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md
index a26ec056..79bef1fb 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-beta.2.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-rc.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index c7f755c9..f5ece03e 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.9.0-beta.2",
+  "version": "4.9.0-rc.0",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index d3472677..b3281539 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-beta.2.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-rc.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index c4223250..04747829 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.9.0-beta.2",
+  "version": "4.9.0-rc.0",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/coreui-react/src/components/dropdown/CDropdown.tsx b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
index ca25f5f3..9d785923 100644
--- a/packages/coreui-react/src/components/dropdown/CDropdown.tsx
+++ b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
@@ -66,7 +66,7 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
   /**
    * Callback fired when the component requests to be hidden.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   onHide?: () => void
   /**
diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index f2b128b8..cbd92ec7 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -13,7 +13,7 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
   /**
    * Apply a CSS fade transition to the popover.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   animation?: boolean
   /**
@@ -31,13 +31,13 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
   /**
    * The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   delay?: number | { show: number; hide: number }
   /**
    * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   fallbackPlacements?: Placements | Placements[]
   /**
diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index 32593916..dcecf2ee 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -13,7 +13,7 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
   /**
    * Apply a CSS fade transition to the tooltip.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   animation?: boolean
   /**
@@ -27,13 +27,13 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
   /**
    * The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   delay?: number | { show: number; hide: number }
   /**
    * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
    *
-   * @since 4.9.0-beta.2
+   * @since 4.9.0-rc.0
    */
   fallbackPlacements?: Placements | Placements[]
   /**
diff --git a/packages/docs/content/api/CDropdown.api.mdx b/packages/docs/content/api/CDropdown.api.mdx
index 46230d01..7d493cd5 100644
--- a/packages/docs/content/api/CDropdown.api.mdx
+++ b/packages/docs/content/api/CDropdown.api.mdx
@@ -14,7 +14,7 @@ import CDropdown from '@coreui/react/src/components/dropdown/CDropdown'
 | **dark** | Sets a darker color scheme to match a dark navbar. | `boolean` | - |
 | **direction** | Sets a specified  direction and location of the dropdown menu. | `'center'` \| `'dropup'` \| `'dropup-center'` \| `'dropend'` \| `'dropstart'` | - |
 | **offset** | Offset of the dropdown menu relative to its target. | `[number, number]` | [0, 2] |
-| **onHide** **_4.9.0-beta.2+_** | Callback fired when the component requests to be hidden. | `() => void` | - |
+| **onHide** **_4.9.0-rc.0+_** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
 | **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top-end'` \| `'top'` \| `'top-start'` \| `'bottom-end'` \| `'bottom'` \| `'bottom-start'` \| `'right-start'` \| `'right'` \| `'right-end'` \| `'left-start'` \| `'left'` \| `'left-end'` | bottom-start |
 | **popper** | If you want to disable dynamic positioning set this property to `true`. | `boolean` | true |
diff --git a/packages/docs/content/api/CPopover.api.mdx b/packages/docs/content/api/CPopover.api.mdx
index c373ba69..ea5724ba 100644
--- a/packages/docs/content/api/CPopover.api.mdx
+++ b/packages/docs/content/api/CPopover.api.mdx
@@ -7,11 +7,11 @@ import CPopover from '@coreui/react/src/components/popover/CPopover'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
-| **animation** **_4.9.0-beta.2+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
+| **animation** **_4.9.0-rc.0+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
-| **delay** **_4.9.0-beta.2+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
-| **fallbackPlacements** **_4.9.0-beta.2+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
+| **delay** **_4.9.0-rc.0+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0-rc.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
 | **offset** | Offset of the popover relative to its target. | `[number, number]` | [0, 8] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
diff --git a/packages/docs/content/api/CTooltip.api.mdx b/packages/docs/content/api/CTooltip.api.mdx
index 66f664e7..a89da7ed 100644
--- a/packages/docs/content/api/CTooltip.api.mdx
+++ b/packages/docs/content/api/CTooltip.api.mdx
@@ -7,11 +7,11 @@ import CTooltip from '@coreui/react/src/components/tooltip/CTooltip'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
-| **animation** **_4.9.0-beta.2+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
+| **animation** **_4.9.0-rc.0+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
-| **delay** **_4.9.0-beta.2+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
-| **fallbackPlacements** **_4.9.0-beta.2+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
+| **delay** **_4.9.0-rc.0+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0-rc.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
 | **offset** | Offset of the tooltip relative to its target. | `[number, number]` | [0, 6] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
diff --git a/packages/docs/package.json b/packages/docs/package.json
index 0f252f84..2e530d22 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.9.0-beta.2",
+  "version": "4.9.0-rc.0",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From 2dc71cae9009e2b7b204c6f09b64d35e9a4b1190 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:19:43 +0200
Subject: [PATCH 06/49] chore: update depenendencies and devDependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

@typescript-eslint/eslint-plugin  ^5.59.11  →  ^5.61.0
@typescript-eslint/parser         ^5.59.11  →  ^5.61.0
eslint                              8.43.0  →   8.44.0
lerna                               ^7.1.0  →   ^7.1.1
prettier                            ^2.8.8  →   ^3.0.0
---
 package.json | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 39792254..2bd8a7de 100644
--- a/package.json
+++ b/package.json
@@ -22,17 +22,17 @@
     "test:update": "npm-run-all charts:test:update icons:test:update lib:test:update"
   },
   "devDependencies": {
-    "@typescript-eslint/eslint-plugin": "^5.59.11",
-    "@typescript-eslint/parser": "^5.59.11",
-    "eslint": "8.43.0",
+    "@typescript-eslint/eslint-plugin": "^5.61.0",
+    "@typescript-eslint/parser": "^5.61.0",
+    "eslint": "8.44.0",
     "eslint-config-prettier": "^8.8.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-react": "^7.32.2",
     "eslint-plugin-react-hooks": "^4.6.0",
     "eslint-plugin-unicorn": "^47.0.0",
-    "lerna": "^7.1.0",
+    "lerna": "^7.1.1",
     "npm-run-all": "^4.1.5",
-    "prettier": "^2.8.8"
+    "prettier": "^3.0.0"
   },
   "overrides": {
     "gatsby-remark-external-links": {

From aac5a8213125c188d0aaceb7056f08700df7cc8e Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:21:21 +0200
Subject: [PATCH 07/49] chore: update dependencies and devDependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

@rollup/plugin-commonjs    ^25.0.1  →  ^25.0.2
@rollup/plugin-typescript  ^11.1.1  →  ^11.1.2
@types/react               18.2.12  →  18.2.14
@types/react-dom           ^18.2.5  →  ^18.2.6
jest                       ^29.5.0  →  ^29.6.1
jest-environment-jsdom     ^29.5.0  →  ^29.6.1
rollup                     ^3.25.1  →  ^3.26.2
ts-jest                    ^29.1.0  →  ^29.1.1
tslib                       ^2.5.3  →   ^2.6.0
---
 packages/coreui-react/package.json | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index 04747829..ce54108d 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -38,25 +38,25 @@
   },
   "devDependencies": {
     "@popperjs/core": "^2.11.8",
-    "@rollup/plugin-commonjs": "^25.0.1",
+    "@rollup/plugin-commonjs": "^25.0.2",
     "@rollup/plugin-node-resolve": "^15.1.0",
-    "@rollup/plugin-typescript": "^11.1.1",
+    "@rollup/plugin-typescript": "^11.1.2",
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^14.0.0",
-    "@types/react": "18.2.12",
-    "@types/react-dom": "^18.2.5",
+    "@types/react": "18.2.14",
+    "@types/react-dom": "^18.2.6",
     "@types/react-transition-group": "^4.4.6",
     "classnames": "^2.3.2",
-    "jest": "^29.5.0",
-    "jest-environment-jsdom": "^29.5.0",
+    "jest": "^29.6.1",
+    "jest-environment-jsdom": "^29.6.1",
     "prop-types": "^15.8.1",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-popper": "^2.3.0",
     "react-transition-group": "^4.4.5",
-    "rollup": "^3.25.1",
-    "ts-jest": "^29.1.0",
-    "tslib": "^2.5.3",
+    "rollup": "^3.26.2",
+    "ts-jest": "^29.1.1",
+    "tslib": "^2.6.0",
     "typescript": "^4.9.5"
   },
   "peerDependencies": {

From 984d90025623b5de95a23aee1a549805d0f29a54 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:22:44 +0200
Subject: [PATCH 08/49] chore: update dependencies and devDependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

prism-react-renderer   ^2.0.5  →   ^2.0.6
sass                  ^1.63.4  →  ^1.63.6
---
 packages/docs/package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/docs/package.json b/packages/docs/package.json
index 2e530d22..fc8b46ca 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -50,7 +50,7 @@
     "gatsby-transformer-sharp": "^5.11.0",
     "glob": "^7.2.0",
     "globby": "^11.1.0",
-    "prism-react-renderer": "^2.0.5",
+    "prism-react-renderer": "^2.0.6",
     "prismjs": "^1.29.0",
     "prop-types": "^15.8.1",
     "react": "^18.2.0",
@@ -59,7 +59,7 @@
     "react-helmet": "^6.1.0",
     "react-imask": "^7.0.1",
     "rimraf": "^5.0.1",
-    "sass": "^1.63.4"
+    "sass": "^1.63.6"
   },
   "devDependencies": {
     "npm-run-all": "^4.1.5"

From f3731cb62ad1be97fc8acff89914b02cef9564bf Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:31:14 +0200
Subject: [PATCH 09/49] docs: update API documentation

---
 packages/coreui-react/src/components/dropdown/CDropdown.tsx | 2 +-
 packages/coreui-react/src/components/popover/CPopover.tsx   | 6 +++---
 packages/coreui-react/src/components/tooltip/CTooltip.tsx   | 6 +++---
 packages/docs/content/api/CDropdown.api.mdx                 | 2 +-
 packages/docs/content/api/CPopover.api.mdx                  | 6 +++---
 packages/docs/content/api/CTooltip.api.mdx                  | 6 +++---
 6 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/packages/coreui-react/src/components/dropdown/CDropdown.tsx b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
index 9d785923..59dfbdb9 100644
--- a/packages/coreui-react/src/components/dropdown/CDropdown.tsx
+++ b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
@@ -66,7 +66,7 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
   /**
    * Callback fired when the component requests to be hidden.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   onHide?: () => void
   /**
diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index cbd92ec7..ecf8597b 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -13,7 +13,7 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
   /**
    * Apply a CSS fade transition to the popover.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   animation?: boolean
   /**
@@ -31,13 +31,13 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
   /**
    * The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   delay?: number | { show: number; hide: number }
   /**
    * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   fallbackPlacements?: Placements | Placements[]
   /**
diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index dcecf2ee..ed44be0d 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -13,7 +13,7 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
   /**
    * Apply a CSS fade transition to the tooltip.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   animation?: boolean
   /**
@@ -27,13 +27,13 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
   /**
    * The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   delay?: number | { show: number; hide: number }
   /**
    * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
    *
-   * @since 4.9.0-rc.0
+   * @since 4.9.0
    */
   fallbackPlacements?: Placements | Placements[]
   /**
diff --git a/packages/docs/content/api/CDropdown.api.mdx b/packages/docs/content/api/CDropdown.api.mdx
index 7d493cd5..d1ebd44f 100644
--- a/packages/docs/content/api/CDropdown.api.mdx
+++ b/packages/docs/content/api/CDropdown.api.mdx
@@ -14,7 +14,7 @@ import CDropdown from '@coreui/react/src/components/dropdown/CDropdown'
 | **dark** | Sets a darker color scheme to match a dark navbar. | `boolean` | - |
 | **direction** | Sets a specified  direction and location of the dropdown menu. | `'center'` \| `'dropup'` \| `'dropup-center'` \| `'dropend'` \| `'dropstart'` | - |
 | **offset** | Offset of the dropdown menu relative to its target. | `[number, number]` | [0, 2] |
-| **onHide** **_4.9.0-rc.0+_** | Callback fired when the component requests to be hidden. | `() => void` | - |
+| **onHide** **_4.9.0+_** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
 | **placement** | Describes the placement of your component after Popper.js has applied all the modifiers that may have flipped or altered the originally provided placement property. | `'auto'` \| `'top-end'` \| `'top'` \| `'top-start'` \| `'bottom-end'` \| `'bottom'` \| `'bottom-start'` \| `'right-start'` \| `'right'` \| `'right-end'` \| `'left-start'` \| `'left'` \| `'left-end'` | bottom-start |
 | **popper** | If you want to disable dynamic positioning set this property to `true`. | `boolean` | true |
diff --git a/packages/docs/content/api/CPopover.api.mdx b/packages/docs/content/api/CPopover.api.mdx
index ea5724ba..3cad4f11 100644
--- a/packages/docs/content/api/CPopover.api.mdx
+++ b/packages/docs/content/api/CPopover.api.mdx
@@ -7,11 +7,11 @@ import CPopover from '@coreui/react/src/components/popover/CPopover'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
-| **animation** **_4.9.0-rc.0+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
+| **animation** **_4.9.0+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
-| **delay** **_4.9.0-rc.0+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
-| **fallbackPlacements** **_4.9.0-rc.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
+| **delay** **_4.9.0+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
 | **offset** | Offset of the popover relative to its target. | `[number, number]` | [0, 8] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |
diff --git a/packages/docs/content/api/CTooltip.api.mdx b/packages/docs/content/api/CTooltip.api.mdx
index a89da7ed..9aa3050d 100644
--- a/packages/docs/content/api/CTooltip.api.mdx
+++ b/packages/docs/content/api/CTooltip.api.mdx
@@ -7,11 +7,11 @@ import CTooltip from '@coreui/react/src/components/tooltip/CTooltip'
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
-| **animation** **_4.9.0-rc.0+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
+| **animation** **_4.9.0+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
-| **delay** **_4.9.0-rc.0+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
-| **fallbackPlacements** **_4.9.0-rc.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
+| **delay** **_4.9.0+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
+| **fallbackPlacements** **_4.9.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
 | **offset** | Offset of the tooltip relative to its target. | `[number, number]` | [0, 6] |
 | **onHide** | Callback fired when the component requests to be hidden. | `() => void` | - |
 | **onShow** | Callback fired when the component requests to be shown. | `() => void` | - |

From adfaf78b9e12c881cd505eb465d6e8f3b3432021 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:36:22 +0200
Subject: [PATCH 10/49] fix: resolve circular dependency warning

---
 packages/coreui-react/src/utils/getRTLPlacement.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/utils/getRTLPlacement.ts b/packages/coreui-react/src/utils/getRTLPlacement.ts
index cc60b801..87c38517 100644
--- a/packages/coreui-react/src/utils/getRTLPlacement.ts
+++ b/packages/coreui-react/src/utils/getRTLPlacement.ts
@@ -1,5 +1,5 @@
 import { Placement } from '@popperjs/core'
-import { isRTL } from '../utils'
+import isRTL from './isRTL'
 
 const getRTLPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
   switch (placement) {

From f0e845a4bbc6b356392b84b982efe9f9369c245e Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 11:37:21 +0200
Subject: [PATCH 11/49] release: v4.9.0

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 79bef1fb..97c53036 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-rc.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index f5ece03e..3d5e4faf 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.9.0-rc.0",
+  "version": "4.9.0",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index b3281539..013d1770 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0-rc.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index ce54108d..c19af195 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.9.0-rc.0",
+  "version": "4.9.0",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index fc8b46ca..ebd7086b 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.9.0-rc.0",
+  "version": "4.9.0",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From b716422bfbb4ca69151ca52bedc4b38104109624 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 7 Jul 2023 23:53:46 +0200
Subject: [PATCH 12/49] build: update API generator

---
 packages/docs/build/api.js | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/packages/docs/build/api.js b/packages/docs/build/api.js
index 72f52002..084599da 100644
--- a/packages/docs/build/api.js
+++ b/packages/docs/build/api.js
@@ -7,11 +7,15 @@ const path = require('node:path')
 const globby = require('globby')
 const docgen = require('react-docgen-typescript')
 
-const GLOB = ['**/src/**/*.tsx']
+const GLOB = [
+  '**/src/**/*.tsx',
+  '../node_modules/@coreui/icons-react/src/**/*.tsx',
+  '../node_modules/@coreui/react-chartjs/src/**/*.tsx',
+]
 const GLOBBY_OPTIONS = {
   absolute: true,
   cwd: path.join(__dirname, '..', '..'),
-  gitignore: true,
+  gitignore: false,
   ignore: ['**/docs/**', '**/__tests__/**'],
 }
 const EXCLUDED_FILES = []
@@ -35,13 +39,20 @@ async function createMdx(file, filename, name, props) {
   }
 
   const pro = PRO_COMPONENTS.some((v) => file.includes(v))
-  const relativeFilename = file.replace(GLOBBY_OPTIONS.cwd, '').replace('coreui-', '')
+  let relativeFilename
+  if (file.includes('node_modules')) {
+    relativeFilename = file.replace(path.join(file, '..', '..', '..'), '').replace('coreui-', '')
+  } else {
+    relativeFilename = file.replace(GLOBBY_OPTIONS.cwd, '').replace('coreui-', '')
+  }
+
+  if (!pro) {
+    relativeFilename = relativeFilename.replace('-pro', '')
+  }
 
   let content = `\n`
   content += `\`\`\`jsx\n`
-  content += `import { ${name} } from '@coreui/${relativeFilename.split('/')[1]}${
-    pro ? '-pro' : ''
-  }'\n`
+  content += `import { ${name} } from '@coreui/${relativeFilename.split('/')[1]}'\n`
   content += `// or\n`
   content += `import ${name} from '@coreui${relativeFilename.replace('.tsx', '')}'\n`
   content += `\`\`\`\n\n`

From 7dd7f205f27a74c7ec0ee58262cb4cd229e80ff0 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Tue, 11 Jul 2023 12:39:47 +0200
Subject: [PATCH 13/49] docs: update Icons documentation

---
 packages/docs/content/components/icon.mdx | 147 ++++++++++++++++++++--
 packages/docs/package.json                |   2 +-
 2 files changed, 136 insertions(+), 13 deletions(-)

diff --git a/packages/docs/content/components/icon.mdx b/packages/docs/content/components/icon.mdx
index 89caf47c..e014af45 100644
--- a/packages/docs/content/components/icon.mdx
+++ b/packages/docs/content/components/icon.mdx
@@ -1,7 +1,7 @@
 ---
 title: React Icons Component
 name: Icon
-description: React icons is a great resource for React developers, who can use its customizable SVG icons in their applications. It offers an extensive library of icons to choose from, which can be easily inserted into projects with just a few lines of code. Not only that, but users are also able to customize the appearance of these icons by setting various props on them. This provides developers with an efficient and flexible way to integrate useful graphical elements into their webpages without doing any extra work.
+description: React icons library is a great resource for React developers, who can use its customizable SVG icons in their applications. It offers an extensive library of icons to choose from, which can be easily inserted into projects with just a few lines of code. Not only that, but users are also able to customize the appearance of these icons by setting various props on them. This provides developers with an efficient and flexible way to integrate useful graphical elements into their web pages without doing any extra work.
 menu: Components
 route: /components/icon
 ---
@@ -21,28 +21,27 @@ import * as icon from '@coreui/icons';
 
 ## Installation
 
-To use React icons in your project, you will need to install it as a dependency:
+To start using CoreUI React Icons in your project, you need to install it as a dependency. Follow the instructions below based on your package manager of choice:
 
 ### Npm
 
 ```bash
-// CoreUI Icons library
-npm install @coreui/icons
-
-// CIcon component
-npm install @coreui/icons-react 
+npm install @coreui/icons @coreui/icons-react 
 ```
 
 ### Yarn
 
 ```bash
-yarn add @coreui/icons
-yarn add @coreui/icons-react
+yarn add @coreui/icons @coreui/icons-react 
 ```
 
 ## Usage
 
-### Single icon
+Import react icons using one of these two options:
+
+### Single react icon
+
+To use a single react icon, import the `<CIcon>` component and the desired icon(s) from the `@coreui/icons` library. Then, include the `<CIcon>` component in your code and specify the icon prop with the imported icon variable. Additionally, you can set the desired size for the icon using the `size` prop.
 
 <Example>
   <CIcon icon={cilList} size="xl"/>
@@ -59,7 +58,9 @@ import { cilList, cilShieldAlt } from '@coreui/icons';
 ...
 ```
 
-### All icons
+### All react icons
+
+To use all icons available in the CoreUI React Icons package, import the CIcon component and the entire `@coreui/icons` library using the `* as` syntax. Then, reference the desired icon within the `icon` prop.
 
 ```jsx
 import CIcon from '@coreui/icons-react';
@@ -74,9 +75,125 @@ render() {
 ...
 ```
 
+### Color
+
+The CoreUI React Icon component offers versatile color customization options, empowering you to personalize the icons in multiple ways. You can effortlessly modify the colors by utilizing either class names or CSS variables, providing flexibility and ease in creating visually stunning and cohesive icon designs.
+
+#### Utility classes
+
+With some [color utility classes](https://coreui.io/docs/utilities/colors/), you may use color to convey message.
+
+```jsx preview
+<CIcon icon={cilList} size="xl" />
+<CIcon icon={cilList} className="text-primary" size="xl" />
+<CIcon icon={cilList} className="text-secondary" size="xl" />
+<CIcon icon={cilList} className="text-success" size="xl" />
+<CIcon icon={cilList} className="text-danger" size="xl" />
+<CIcon icon={cilList} className="text-warning" size="xl" />
+<CIcon icon={cilList} className="text-info" size="xl" />
+```
+
+#### CSS Variables
+
+CoreUI React Icons leverage local CSS variables, such as `--ci-primary-color` and `--ci-secondary-color` (for Duotone icons), to facilitate real-time customization. This allows developers to easily customize the icons by providing their own custom CSS variables.
+
+```jsx preview
+<CIcon icon={cilList} size="xl" style={{'--ci-primary-color': 'red'}} />
+<CIcon icon={cilList} size="xl" style={{'--ci-primary-color': 'green'}} />
+```
+
+### Sizing
+
+Set heights of react icons using size property like size="lg" and size="sm".
+
+```jsx preview
+<CIcon icon={cilList} size="sm" />
+<CIcon icon={cilList} size="md" />
+<CIcon icon={cilList} size="lg" />
+<CIcon icon={cilList} size="xl" />
+<CIcon icon={cilList} size="xxl" />
+<CIcon icon={cilList} size="3xl" />
+```
+
+
+## Accessibility
+
+It's crucial for react icons to be seen by as many people as possible because they have the power to communicate a variety of meaningful information.
+
+People who are blind, have low vision, or have other visual impairments make up approximately 10% of the world's population, and more than 5% of people worldwide have hearing loss that makes them unable to function normally.
+
+Therefore, it's crucial to make sure that the assistive equipment for people with disabilities, such as screen readers, either ignores or better understands the react icons you use online.
+
+Icons are used in one of two ways on websites, apps, and other digital spaces.
+
+#### Decorative Icons
+
+It is not necessary to declare an icon to visitors when they are using your website or app if you are utilizing it to offer extra decoration or branding.
+
+Additionally, if you use an icon to visually emphasize or add flair to content that is already present in your HTML, an assistive technology user does not need to see it again.
+
+In certain circumstances, the details of the icon ought to be concealed from the screenreader so as not to obstruct the intended message.
+
+#### Semantic Icons
+
+You need to make sure that consumers understand the meaning an icon is intended to represent by giving them text-based alternatives.
+
+This applies to both the content you're using icons to represent (such as the status of your shopping cart or the number of unread messages), as well react icons as interactive controls (such as buttons, form elements, toggles, etc.).
+
+### CoreUI React Icons and Accessibility
+
+Our React Icon component automatically takes care of accessibility concerns by adding appropriate elements.
+
+#### Decorative icons
+
+If your icons are only for decorative purposes, the CoreUI React Icon Component will ensure that assistive technology ignores the icon. In addition to referencing an icon as normal, the `aria-hidden=true` attribute has been introduced, so there is nothing else you need to do.
+
+If your markup looks like this:
+
+```jsx
+<CButton>
+  <CIcon icon={cilCloudDownload} />
+</CButton>
+```
+
+By including the `aria-hidden` attribute, CoreUI React Icon Component will afterwards automatically hide it from screenreaders.
+
+```html
+<button class="btn btn-primary" type="button">
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="icon" role="img" aria-hidden="true">
+    <polygon fill="var(--ci-primary-color, currentColor)" points="272 434.744 272 209.176 240 209.176 240 434.744 188.118 382.862 165.49 405.489 256 496 346.51 405.489 323.882 382.862 272 434.744" class="ci-primary"></polygon><path fill="var(--ci-primary-color, currentColor)" d="M400,161.176c0-79.4-64.6-144-144-144s-144,64.6-144,144a96,96,0,0,0,0,192h80v-32H112a64,64,0,0,1,0-128h32v-32a112,112,0,0,1,224,0v32h32a64,64,0,0,1,0,128H320v32h80a96,96,0,0,0,0-192Z" class="ci-primary"></path>
+  </svg>
+</button>
+```
+
+#### Semantic icons
+
+The description that you must set using the title property will be used by CoreUI React Icon Component to generate alternative text for the semantic icon.
+
+Thus, if your markup appears as follows:
+
+```jsx
+<CButton>
+  <CIcon icon={cilCloudDownload} title="Download file" />
+</CButton>
+```
+
+CoreUI React Icon Component will make the necessary adjustments so that only screenreaders can "see" the supporting elements that convey the message.
+
+```html
+<button class="btn btn-primary" type="button">
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="icon" role="img" aria-hidden="true">
+    <polygon fill="var(--ci-primary-color, currentColor)" points="272 434.744 272 209.176 240 209.176 240 434.744 188.118 382.862 165.49 405.489 256 496 346.51 405.489 323.882 382.862 272 434.744" class="ci-primary"></polygon><path fill="var(--ci-primary-color, currentColor)" d="M400,161.176c0-79.4-64.6-144-144-144s-144,64.6-144,144a96,96,0,0,0,0,192h80v-32H112a64,64,0,0,1,0-128h32v-32a112,112,0,0,1,224,0v32h32a64,64,0,0,1,0,128H320v32h80a96,96,0,0,0,0-192Z" class="ci-primary"></path>
+  </svg>
+  <span class="visually-hidden">Download file</span>
+</button>
+```
+
 ## Available react icons
 
-CoreUI React Icons package is delivered with more than 1500 icons in multiple formats SVG, PNG, and Webfonts. CoreUI Icons are beautifully crafted symbols for common actions and items. You can use them in your digital products for web or mobile app.
+The CoreUI React Icons package includes a comprehensive library of more than 1500 icons, available in various formats such as SVG, PNG, and Webfonts. These popular icons are meticulously crafted symbols representing common actions and items. You can utilize them in your digital products, whether they are web or mobile applications, to enhance their visual appeal and user experience.
+
+By leveraging the capabilities of the React Icons component from CoreUI, you can easily incorporate visually appealing icons into their React applications, allowing for more engaging and intuitive user interfaces.
 
 export const LinearExample = () => {
   const icons = ['cilAccountLogout', 'cilActionRedo', 'cilActionUndo', 'cilAddressBook', 'cilAirplaneModeOff', 'cilAirplaneMode', 'cilAirplay', 'cilAlarm', 'cilAlbum', 'cilAlignCenter', 'cilAlignLeft', 'cilAlignRight', 'cilAmericanFootball', 'cilAnimal', 'cilAperture', 'cilApple', 'cilApplicationsSettings', 'cilApplications', 'cilAppsSettings', 'cilApps', 'cilArrowBottom', 'cilArrowCircleBottom', 'cilArrowCircleLeft', 'cilArrowCircleRight', 'cilArrowCircleTop', 'cilArrowLeft', 'cilArrowRight', 'cilArrowThickBottom', 'cilArrowThickFromBottom', 'cilArrowThickFromLeft', 'cilArrowThickFromRight', 'cilArrowThickFromTop', 'cilArrowThickLeft', 'cilArrowThickRight', 'cilArrowThickToBottom', 'cilArrowThickToLeft', 'cilArrowThickToRight', 'cilArrowThickToTop', 'cilArrowThickTop', 'cilArrowTop', 'cilAssistiveListeningSystem', 'cilAsteriskCircle', 'cilAsterisk', 'cilAt', 'cilAudioDescription', 'cilAudioSpectrum', 'cilAudio', 'cilAvTimer', 'cilBabyCarriage', 'cilBaby', 'cilBackspace', 'cilBadge', 'cilBalanceScale', 'cilBan', 'cilBank', 'cilBarChart', 'cilBarcode', 'cilBaseball', 'cilBasket', 'cilBasketball', 'cilBath', 'cilBathroom', 'cilBattery0', 'cilBattery3', 'cilBattery5', 'cilBatteryAlert', 'cilBatteryEmpty', 'cilBatteryFull', 'cilBatterySlash', 'cilBeachAccess', 'cilBeaker', 'cilBed', 'cilBellExclamation', 'cilBell', 'cilBike', 'cilBirthdayCake', 'cilBlind', 'cilBluetooth', 'cilBlurCircular', 'cilBlurLinear', 'cilBlur', 'cilBoatAlt', 'cilBold', 'cilBoltCircle', 'cilBolt', 'cilBook', 'cilBookmark', 'cilBorderAll', 'cilBorderBottom', 'cilBorderClear', 'cilBorderHorizontal', 'cilBorderInner', 'cilBorderLeft', 'cilBorderOuter', 'cilBorderRight', 'cilBorderStyle', 'cilBorderTop', 'cilBorderVertical', 'cilBowling', 'cilBraille', 'cilBriefcase', 'cilBrightness', 'cilBritishPound', 'cilBrowser', 'cilBrushAlt', 'cilBrush', 'cilBug', 'cilBuilding', 'cilBullhorn', 'cilBurger', 'cilBurn', 'cilBusAlt', 'cilCalculator', 'cilCalendarCheck', 'cilCalendar', 'cilCameraControl', 'cilCameraRoll', 'cilCamera', 'cilCarAlt', 'cilCaretBottom', 'cilCaretLeft', 'cilCaretRight', 'cilCaretTop', 'cilCart', 'cilCash', 'cilCasino', 'cilCast', 'cilCat', 'cilCc', 'cilCenterFocus', 'cilChartLine', 'cilChartPie', 'cilChart', 'cilChatBubble', 'cilCheckAlt', 'cilCheckCircle', 'cilCheck', 'cilChevronBottom', 'cilChevronCircleDownAlt', 'cilChevronCircleLeftAlt', 'cilChevronCircleRightAlt', 'cilChevronCircleUpAlt', 'cilChevronDoubleDown', 'cilChevronDoubleLeft', 'cilChevronDoubleRight', 'cilChevronDoubleUp', 'cilChevronLeft', 'cilChevronRight', 'cilChevronTop', 'cilChildFriendly', 'cilChild', 'cilCircle', 'cilClearAll', 'cilClipboard', 'cilClock', 'cilClone', 'cilClosedCaptioning', 'cilCloudDownload', 'cilCloudUpload', 'cilCloud', 'cilCloudy', 'cilCode', 'cilCoffee', 'cilCog', 'cilColorBorder', 'cilColorFill', 'cilColorPalette', 'cilColumns', 'cilCommand', 'cilCommentBubble', 'cilCommentSquare', 'cilCompass', 'cilCompress', 'cilContact', 'cilContrast', 'cilControl', 'cilCopy', 'cilCouch', 'cilCreditCard', 'cilCropRotate', 'cilCrop', 'cilCursorMove', 'cilCursor', 'cilCut', 'cilDataTransferDown', 'cilDataTransferUp', 'cilDeaf', 'cilDelete', 'cilDescription', 'cilDevices', 'cilDialpad', 'cilDiamond', 'cilDinner', 'cilDisabled', 'cilDog', 'cilDollar', 'cilDoor', 'cilDoubleQuoteSansLeft', 'cilDoubleQuoteSansRight', 'cilDrinkAlcohol', 'cilDrink', 'cilDrop', 'cilEco', 'cilEducation', 'cilElevator', 'cilEnvelopeClosed', 'cilEnvelopeLetter', 'cilEnvelopeOpen', 'cilEqualizer', 'cilEthernet', 'cilEuro', 'cilExcerpt', 'cilExitToApp', 'cilExpandDown', 'cilExpandLeft', 'cilExpandRight', 'cilExpandUp', 'cilExposure', 'cilExternalLink', 'cilEyedropper', 'cilFaceDead', 'cilFace', 'cilFactorySlash', 'cilFactory', 'cilFastfood', 'cilFax', 'cilFeaturedPlaylist', 'cilFile', 'cilFilterFrames', 'cilFilterPhoto', 'cilFilterSquare', 'cilFilterX', 'cilFilter', 'cilFindInPage', 'cilFingerprint', 'cilFire', 'cilFlagAlt', 'cilFlightTakeoff', 'cilFlipToBack', 'cilFlipToFront', 'cilFlip', 'cilFlower', 'cilFolderOpen', 'cilFolder', 'cilFont', 'cilFootball', 'cilFork', 'cilFridge', 'cilFrown', 'cilFullscreenExit', 'cilFullscreen', 'cilFunctionsAlt', 'cilFunctions', 'cilGamepad', 'cilGarage', 'cilGem', 'cilGif', 'cilGift', 'cilGlobeAlt', 'cilGolfAlt', 'cilGolf', 'cilGradient', 'cilGrain', 'cilGraph', 'cilGridSlash', 'cilGrid', 'cilGroup', 'cilHamburgerMenu', 'cilHandPointDown', 'cilHandPointLeft', 'cilHandPointRight', 'cilHandPointUp', 'cilHappy', 'cilHd', 'cilHdr', 'cilHeader', 'cilHeadphones', 'cilHealing', 'cilHeart', 'cilHighlighter', 'cilHighligt', 'cilHistory', 'cilHome', 'cilHospital', 'cilHotTub', 'cilHouse', 'cilHttps', 'cilImageBroken', 'cilImagePlus', 'cilImage', 'cilInbox', 'cilIndentDecrease', 'cilIndentIncrease', 'cilIndustrySlash', 'cilIndustry', 'cilInfinity', 'cilInfo', 'cilInputHdmi', 'cilInputPower', 'cilInput', 'cilInstitution', 'cilItalic', 'cilJustifyCenter', 'cilJustifyLeft', 'cilJustifyRight', 'cilKeyboard', 'cilLan', 'cilLanguage', 'cilLaptop', 'cilLayers', 'cilLeaf', 'cilLemon', 'cilLevelDown', 'cilLevelUp', 'cilLibraryAdd', 'cilLibraryBuilding', 'cilLibrary', 'cilLifeRing', 'cilLightbulb', 'cilLineSpacing', 'cilLineStyle', 'cilLineWeight', 'cilLinkAlt', 'cilLinkBroken', 'cilLink', 'cilListFilter', 'cilListHighPriority', 'cilListLowPriority', 'cilListNumberedRtl', 'cilListNumbered', 'cilListRich', 'cilList', 'cilLocationPin', 'cilLockLocked', 'cilLockUnlocked', 'cilLocomotive', 'cilLoop1', 'cilLoopCircular', 'cilLoop', 'cilLowVision', 'cilMagnifyingGlass', 'cilMap', 'cilMediaEject', 'cilMediaPause', 'cilMediaPlay', 'cilMediaRecord', 'cilMediaSkipBackward', 'cilMediaSkipForward', 'cilMediaStepBackward', 'cilMediaStepForward', 'cilMediaStop', 'cilMedicalCross', 'cilMeh', 'cilMemory', 'cilMenu', 'cilMic', 'cilMicrophone', 'cilMinus', 'cilMobileLandscape', 'cilMobile', 'cilMoney', 'cilMonitor', 'cilMoodBad', 'cilMoodGood', 'cilMoodVeryBad', 'cilMoodVeryGood', 'cilMoon', 'cilMouse', 'cilMouthSlash', 'cilMove', 'cilMovie', 'cilMugTea', 'cilMug', 'cilMusicNote', 'cilNewspaper', 'cilNoteAdd', 'cilNotes', 'cilObjectGroup', 'cilObjectUngroup', 'cilOpacity', 'cilOpentype', 'cilOptions', 'cilPaintBucket', 'cilPaint', 'cilPaperPlane', 'cilPaperclip', 'cilParagraph', 'cilPaw', 'cilPenAlt', 'cilPenNib', 'cilPen', 'cilPencil', 'cilPeople', 'cilPhone', 'cilPin', 'cilPizza', 'cilPlant', 'cilPlaylistAdd', 'cilPlus', 'cilPool', 'cilPowerStandby', 'cilPregnant', 'cilPrint', 'cilPushchair', 'cilPuzzle', 'cilQrCode', 'cilRain', 'cilRectangle', 'cilRecycle', 'cilReload', 'cilReportSlash', 'cilResizeBoth', 'cilResizeHeight', 'cilResizeWidth', 'cilRestaurant', 'cilRoom', 'cilRouter', 'cilRowing', 'cilRss', 'cilRuble', 'cilRunning', 'cilSad', 'cilSatelite', 'cilSave', 'cilSchool', 'cilScreenDesktop', 'cilScreenSmartphone', 'cilScrubber', 'cilSearch', 'cilSend', 'cilSettings', 'cilShareAll', 'cilShareAlt', 'cilShareBoxed', 'cilShare', 'cilShieldAlt', 'cilShortText', 'cilShower', 'cilSignLanguage', 'cilSignalCellular0', 'cilSignalCellular3', 'cilSignalCellular4', 'cilSim', 'cilSitemap', 'cilSmilePlus', 'cilSmile', 'cilSmokeFree', 'cilSmokeSlash', 'cilSmoke', 'cilSmokingRoom', 'cilSnowflake', 'cilSoccer', 'cilSofa', 'cilSortAlphaDown', 'cilSortAlphaUp', 'cilSortAscending', 'cilSortDescending', 'cilSortNumericDown', 'cilSortNumericUp', 'cilSpa', 'cilSpaceBar', 'cilSpeak', 'cilSpeaker', 'cilSpeech', 'cilSpeedometer', 'cilSpreadsheet', 'cilSquare', 'cilStarHalf', 'cilStar', 'cilStorage', 'cilStream', 'cilStrikethrough', 'cilSun', 'cilSwapHorizontal', 'cilSwapVertical', 'cilSwimming', 'cilSync', 'cilTablet', 'cilTag', 'cilTags', 'cilTask', 'cilTaxi', 'cilTennisBall', 'cilTennis', 'cilTerminal', 'cilTerrain', 'cilTextShapes', 'cilTextSize', 'cilTextSquare', 'cilTextStrike', 'cilText', 'cilThumbDown', 'cilThumbUp', 'cilToggleOff', 'cilToggleOn', 'cilToilet', 'cilTouchApp', 'cilTransfer', 'cilTranslate', 'cilTrash', 'cilTriangle', 'cilTruck', 'cilTv', 'cilUnderline', 'cilUsb', 'cilUserFemale', 'cilUserFollow', 'cilUserPlus', 'cilUserUnfollow', 'cilUserX', 'cilUser', 'cilVector', 'cilVerticalAlignBottom', 'cilVerticalAlignCenter', 'cilVerticalAlignTop', 'cilVideo', 'cilVideogame', 'cilViewColumn', 'cilViewModule', 'cilViewQuilt', 'cilViewStream', 'cilVoiceOverRecord', 'cilVoice', 'cilVolumeHigh', 'cilVolumeLow', 'cilVolumeOff', 'cilWalk', 'cilWallet', 'cilWallpaper', 'cilWarning', 'cilWatch', 'cilWc', 'cilWeightlifitng', 'cilWheelchair', 'cilWifiSignal0', 'cilWifiSignal1', 'cilWifiSignal2', 'cilWifiSignal3', 'cilWifiSignal4', 'cilWifiSignalOff', 'cilWindowMaximize', 'cilWindowMinimize', 'cilWindowRestore', 'cilWindow', 'cilWrapText', 'cilXCircle', 'cilX', 'cilYen', 'cilZoomIn', 'cilZoomOut', 'cilZoom']
@@ -190,6 +307,12 @@ export const TabPanesExample = () => {
 
 React Icons also provides a variety of customization options, such as the ability to change the size, color, and style of the icons, as well as the ability to add additional CSS classes to the icons. You can find more information on these customization options in the documentation.
 
+## Premium icons
+
+If you find yourself in need of a greater selection of icons, we've got you covered with our [premium icon pack](https://coreui.io/icons/all/). This incredible package boasts an extensive collection of over 4,000 meticulously crafted icons, ensuring that you'll find the perfect representation for any concept or idea. Explore the vast range of options and unlock a world of visual possibilities. 
+
+So if you need more icons our PRO package will be a great choice for you.
+
 ## API
 
 ### CIcon
diff --git a/packages/docs/package.json b/packages/docs/package.json
index ebd7086b..aaa53830 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -27,7 +27,7 @@
     "@coreui/chartjs": "^3.1.2",
     "@coreui/coreui": "4.2.6",
     "@coreui/icons": "^3.0.1",
-    "@coreui/icons-react": "^2.1.0",
+    "@coreui/icons-react": "^2.2.0",
     "@coreui/react-chartjs": "^2.1.3",
     "@coreui/utils": "^2.0.2",
     "@docsearch/css": "^3.5.1",

From 140e2853c6afe25b1ec19a7de86042217eb817fe Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 12 Jul 2023 11:35:17 +0200
Subject: [PATCH 14/49] fix(CModal): remove click outside listener when the
 modal is not visible; fire `handleClickOutside` method on `mouseup` event not
 `click`

---
 packages/coreui-react/src/components/modal/CModal.tsx | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index ec119c41..7a81b99f 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -128,11 +128,13 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
     }, [visible])
 
     useEffect(() => {
-      document.addEventListener('click', handleClickOutside)
-      document.addEventListener('keydown', handleKeyDown)
+      if (_visible) {
+        document.addEventListener('mouseup', handleClickOutside)
+        document.addEventListener('keydown', handleKeyDown)
+      }
 
       return () => {
-        document.removeEventListener('click', handleClickOutside)
+        document.removeEventListener('mouseup', handleClickOutside)
         document.removeEventListener('keydown', handleKeyDown)
       }
     }, [_visible])

From 4eb476beb558629f95e9d5c2ff0a999c3deead9c Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 12 Jul 2023 13:27:42 +0200
Subject: [PATCH 15/49] release: v4.9.1

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-icons-react        | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 97c53036..469701f6 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index 3d5e4faf..14405247 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.9.0",
+  "version": "4.9.1",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-icons-react b/packages/coreui-icons-react
index 1dae3585..8a617788 160000
--- a/packages/coreui-icons-react
+++ b/packages/coreui-icons-react
@@ -1 +1 @@
-Subproject commit 1dae358508d06a45b9722476300169fb876319ba
+Subproject commit 8a617788ae9f1f634be14e8f98436145aaee6c61
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index 013d1770..f2a4a49a 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index c19af195..0ebf909e 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.9.0",
+  "version": "4.9.1",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index aaa53830..543b2b6e 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.9.0",
+  "version": "4.9.1",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From 6dbefa88603b6c720a20823e05e165f26f40d924 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sun, 16 Jul 2023 23:28:12 +0200
Subject: [PATCH 16/49] fix(CNavGroup): improve open group handling

---
 .../coreui-react/src/components/nav/CNavGroup.tsx     | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/packages/coreui-react/src/components/nav/CNavGroup.tsx b/packages/coreui-react/src/components/nav/CNavGroup.tsx
index 9d18ea45..1b100bca 100644
--- a/packages/coreui-react/src/components/nav/CNavGroup.tsx
+++ b/packages/coreui-react/src/components/nav/CNavGroup.tsx
@@ -36,6 +36,13 @@ export interface CNavGroupProps {
   idx?: string
 }
 
+const isInVisibleGroup = (el1: string, el2: string) => {
+  const array1 = el1.toString().split('.')
+  const array2 = el2.toString().split('.')
+
+  return array2.every((item, index) => item === array1[index])
+}
+
 export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
   ({ children, className, compact, idx, toggler, visible, ...rest }, ref) => {
     const [height, setHeight] = useState<number | string>()
@@ -45,12 +52,12 @@ export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
 
     const [_visible, setVisible] = useState(
       Boolean(
-        visible || (idx && visibleGroup && visibleGroup.toString().startsWith(idx.toString())),
+        visible || (idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)),
       ),
     )
 
     useEffect(() => {
-      setVisible(Boolean(idx && visibleGroup && visibleGroup.toString().startsWith(idx.toString())))
+      setVisible(Boolean(idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)))
     }, [visibleGroup])
 
     const handleTogglerOnCLick = (event: React.MouseEvent<HTMLElement>) => {

From db86607ae728d43c5e0d142ab56477312b3c6b4d Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sun, 16 Jul 2023 23:45:19 +0200
Subject: [PATCH 17/49] chore: clean-up

---
 .gitignore | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index e069e0ee..70f24f47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,31 @@ coverage/
 dist/
 node_modules/
 public/
-yarn.lock
\ No newline at end of file
+yarn.lock
+
+# IDEs and editors
+.idea/
+
+# Visual Studio Code
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# System files
+.DS_Store
+Thumbs.db
+
+# Numerous always-ignore extensions
+*.diff
+*.err
+*.log
+*.orig
+*.rej
+*.swo
+*.swp
+*.vi
+*.zip
+*~
\ No newline at end of file

From 0ee921954bc7e739f57c9387b1655505b520eecc Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 2 Aug 2023 23:49:18 +0200
Subject: [PATCH 18/49] docs: update content

---
 .../docs/content/components/button-group.mdx  |   2 +-
 .../docs/content/components/offcanvas.mdx     |  37 +++--
 packages/docs/content/components/spinner.mdx  | 144 +++++++++++++-----
 packages/docs/content/layout/gutters.mdx      |  82 +++++-----
 4 files changed, 178 insertions(+), 87 deletions(-)

diff --git a/packages/docs/content/components/button-group.mdx b/packages/docs/content/components/button-group.mdx
index 496654b9..d14bcb53 100644
--- a/packages/docs/content/components/button-group.mdx
+++ b/packages/docs/content/components/button-group.mdx
@@ -49,7 +49,7 @@ These classes can also be added to groups of links, as an alternative to the `<C
 <CButtonGroup>
   <CButton href="#" color="primary" active>Active link</CButton>
   <CButton href="#" color="primary">Link</CButton>
-  <CButton href="#" color="primary">yarLink</CButton>
+  <CButton href="#" color="primary">Link</CButton>
 </CButtonGroup>
 ```
 
diff --git a/packages/docs/content/components/offcanvas.mdx b/packages/docs/content/components/offcanvas.mdx
index a90301c5..02be75bd 100644
--- a/packages/docs/content/components/offcanvas.mdx
+++ b/packages/docs/content/components/offcanvas.mdx
@@ -26,14 +26,14 @@ import {
 
 Below is an offcanvas example that is shown by default (via `visible={true}`). Offcanvas includes support for a header with a close button and an optional body class for some initial `padding`. We suggest that you include offcanvas headers with dismiss actions whenever possible, or provide an explicit dismiss action.
 
-```jsx preview className="docs-example-offcanvas bg-light p-0"
+```jsx preview className="docs-example-offcanvas bg-body-tertiary p-0 overflow-hidden"
 <COffcanvas backdrop={false} placement="start" visible={true}>
   <COffcanvasHeader>
     <COffcanvasTitle>Offcanvas</COffcanvasTitle>
     <CCloseButton className="text-reset" />
   </COffcanvasHeader>
   <COffcanvasBody>
-    Content for the offcanvas goes here. You can place just about any Bootstrap component or custom
+    Content for the offcanvas goes here. You can place just about any React component or custom
     elements here.
   </COffcanvasBody>
 </COffcanvas>
@@ -57,7 +57,7 @@ export const LiveDemoExample = () => {
           <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
         </COffcanvasHeader>
         <COffcanvasBody>
-          Content for the offcanvas goes here. You can place just about any Bootstrap component or
+          Content for the offcanvas goes here. You can place just about any React component or
           custom elements here.
         </COffcanvasBody>
       </COffcanvas>
@@ -80,7 +80,7 @@ return (
         <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
       </COffcanvasHeader>
       <COffcanvasBody>
-        Content for the offcanvas goes here. You can place just about any Bootstrap component or
+        Content for the offcanvas goes here. You can place just about any React component or
         custom elements here.
       </COffcanvasBody>
     </COffcanvas>
@@ -219,6 +219,23 @@ return (
 )
 ```
 
+## Dark offcanvas
+
+Change the appearance of offcanvases with utilities to better match them to different contexts like dark navbars. Here we add `.text-bg-dark` to the `<COffcanvas>` and `white` property to `<CCloseButton>` for proper styling with a dark offcanvas.
+
+```jsx preview className="docs-example-offcanvas bg-body-secondary p-0 overflow-hidden"
+<COffcanvas backdrop={false} className="text-bg-dark" placement="start" visible={true}>
+  <COffcanvasHeader>
+    <COffcanvasTitle>Offcanvas</COffcanvasTitle>
+    <CCloseButton white />
+  </COffcanvasHeader>
+  <COffcanvasBody>
+    Content for the offcanvas goes here. You can place just about any React component or custom
+    elements here.
+  </COffcanvasBody>
+</COffcanvas>
+```
+
 ## Responsive 
 
 Responsive offcanvas properties hide content outside the viewport from a specified breakpoint and down.
@@ -290,7 +307,7 @@ export const PlacementTopExample = () => {
           <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
         </COffcanvasHeader>
         <COffcanvasBody>
-          Content for the offcanvas goes here. You can place just about any Bootstrap component or
+          Content for the offcanvas goes here. You can place just about any React component or
           custom elements here.
         </COffcanvasBody>
       </COffcanvas>
@@ -313,7 +330,7 @@ return (
         <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
       </COffcanvasHeader>
       <COffcanvasBody>
-        Content for the offcanvas goes here. You can place just about any Bootstrap component or
+        Content for the offcanvas goes here. You can place just about any React component or
         custom elements here.
       </COffcanvasBody>
     </COffcanvas>
@@ -332,7 +349,7 @@ export const PlacementRightExample = () => {
           <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
         </COffcanvasHeader>
         <COffcanvasBody>
-          Content for the offcanvas goes here. You can place just about any Bootstrap component or
+          Content for the offcanvas goes here. You can place just about any React component or
           custom elements here.
         </COffcanvasBody>
       </COffcanvas>
@@ -355,7 +372,7 @@ return (
         <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
       </COffcanvasHeader>
       <COffcanvasBody>
-        Content for the offcanvas goes here. You can place just about any Bootstrap component or
+        Content for the offcanvas goes here. You can place just about any React component or
         custom elements here.
       </COffcanvasBody>
     </COffcanvas>
@@ -374,7 +391,7 @@ export const PlacementBottomExample = () => {
           <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
         </COffcanvasHeader>
         <COffcanvasBody>
-          Content for the offcanvas goes here. You can place just about any Bootstrap component or
+          Content for the offcanvas goes here. You can place just about any React component or
           custom elements here.
         </COffcanvasBody>
       </COffcanvas>
@@ -397,7 +414,7 @@ return (
         <CCloseButton className="text-reset" onClick={() => setVisible(false)} />
       </COffcanvasHeader>
       <COffcanvasBody>
-        Content for the offcanvas goes here. You can place just about any Bootstrap component or
+        Content for the offcanvas goes here. You can place just about any React component or
         custom elements here.
       </COffcanvasBody>
     </COffcanvas>
diff --git a/packages/docs/content/components/spinner.mdx b/packages/docs/content/components/spinner.mdx
index 152eae3a..c4321079 100644
--- a/packages/docs/content/components/spinner.mdx
+++ b/packages/docs/content/components/spinner.mdx
@@ -19,10 +19,8 @@ For accessibility purposes, each loader here includes `role="status"` and a nest
 
 Use the border spinners for a lightweight loading indicator.
 
-## Basic usage
-
 ```jsx preview
-  <CSpinner/>
+<CSpinner/>
 ```
 
 ### Colors
@@ -30,14 +28,14 @@ Use the border spinners for a lightweight loading indicator.
 The border spinner uses `currentColor` for its `border-color`. You can use any of our text color utilities on the standard spinner.
 
 ```jsx preview
-  <CSpinner color="primary"/>
-  <CSpinner color="secondary"/>
-  <CSpinner color="success"/>
-  <CSpinner color="danger"/>
-  <CSpinner color="warning"/>
-  <CSpinner color="info"/>
-  <CSpinner color="light"/>
-  <CSpinner color="dark"/>
+<CSpinner color="primary" />
+<CSpinner color="secondary" />
+<CSpinner color="success" />
+<CSpinner color="danger" />
+<CSpinner color="warning" />
+<CSpinner color="info" />
+<CSpinner color="light" />
+<CSpinner color="dark" />
 ```
 
 ## Growing spinner
@@ -45,29 +43,83 @@ The border spinner uses `currentColor` for its `border-color`. You can use any o
 If you don't fancy a border spinner, switch to the grow spinner. While it doesn't technically spin, it does repeatedly grow!
 
 ```jsx preview
-  <CSpinner variant="grow"/>
+<CSpinner variant="grow" />
 ```
 
 Once again, this spinner is built with `currentColor`, so you can easily change its appearance. Here it is in blue, along with the supported variants.
 
 ```jsx preview
-  <CSpinner color="primary" variant="grow"/>
-  <CSpinner color="secondary" variant="grow"/>
-  <CSpinner color="success" variant="grow"/>
-  <CSpinner color="danger" variant="grow"/>
-  <CSpinner color="warning" variant="grow"/>
-  <CSpinner color="info" variant="grow"/>
-  <CSpinner color="light" variant="grow"/>
-  <CSpinner color="dark" variant="grow"/>
+<CSpinner color="primary" variant="grow" />
+<CSpinner color="secondary" variant="grow" />
+<CSpinner color="success" variant="grow" />
+<CSpinner color="danger" variant="grow" />
+<CSpinner color="warning" variant="grow" />
+<CSpinner color="info" variant="grow" />
+<CSpinner color="light" variant="grow" />
+<CSpinner color="dark" variant="grow" />
+```
+
+## Alignment 
+
+CoreUI React spinners are built with `rems`, `currentColor`, and `display: inline-flex`. This means they can easily be resized, recolored, and quickly aligned.
+
+### Margin 
+
+Use [margin utilities](https://coreui.io/docs/utilities/spacing/#margin-and-padding) like `.m-5` for easy spacing.
+
+```jsx preview
+<CSpinner className="m-5" />
+```
+
+### Placement
+
+Use [flexbox utilities][https://coreui.io/docs/utilities/flex/], [float utilities][https://coreui.io/docs/utilities/float/], or [text alignment][https://coreui.io/docs/utilities/text/] utilities to place spinners exactly where you need them in any situation.
+
+#### Flex
+
+```jsx preview
+<div className="d-flex justify-content-center">
+  <CSpinner />
+</div>
+```
+
+```jsx preview
+<div className="d-flex align-items-center">
+  <strong role="status">Loading...</strong>
+  <CSpinner className="ms-auto" />
+</div>
+```
+
+#### Floats
+
+```jsx preview
+<div className="clearfix">
+  <CSpinner className="float-end" />
+</div>
+```
+
+#### Text align
+
+```jsx preview
+<div className="text-center">
+  <CSpinner />
+</div>
 ```
 
 ## Size
 
-Add `size="sm"`property` to make a smaller spinner that can quickly be used within other components.
+Add `size="sm"` property to make a smaller spinner that can quickly be used within other components.
 
 ```jsx preview
-  <CSpinner size="sm"/>
-  <CSpinner size="sm" variant="grow"/>
+<CSpinner size="sm" />
+<CSpinner size="sm" variant="grow" />
+```
+
+Or, use custom CSS or inline styles to change the dimensions as needed.
+
+```jsx preview
+<CSpinner size="sm" style={{ width: '3rem', height: '3rem'}}/>
+<CSpinner size="sm" variant="grow" style={{ width: '3rem', height: '3rem'}}/>
 ```
 
 ## Buttons
@@ -75,23 +127,23 @@ Add `size="sm"`property` to make a smaller spinner that can quickly be used with
 Use spinners within buttons to indicate an action is currently processing or taking place. You may also swap the text out of the spinner element and utilize button text as needed.
 
 ```jsx preview
-  <CButton disabled>
-    <CSpinner component="span" size="sm" aria-hidden="true"/>
-  </CButton>
-  <CButton disabled>
-    <CSpinner component="span" size="sm" aria-hidden="true"/>
-    Loading...
-  </CButton>
+<CButton disabled>
+  <CSpinner component="span" size="sm" aria-hidden="true" />
+</CButton>
+<CButton disabled>
+  <CSpinner component="span" size="sm" aria-hidden="true" />
+  Loading...
+</CButton>
 ```
 
 ```jsx preview
-  <CButton disabled>
-    <CSpinner component="span" size="sm" variant="grow" aria-hidden="true"/>
-  </CButton>
-  <CButton disabled>
-    <CSpinner component="span" size="sm" variant="grow" aria-hidden="true"/>
-    Loading...
-  </CButton>
+<CButton disabled>
+  <CSpinner component="span" size="sm" variant="grow" aria-hidden="true" />
+</CButton>
+<CButton disabled>
+  <CSpinner component="span" size="sm" variant="grow" aria-hidden="true" />
+  Loading...
+</CButton>
 ```
 
 ## Customizing
@@ -102,15 +154,15 @@ React spinners use local CSS variables on `.spinner-border` and `.spinner-grow`
 
 Border spinner variables:
 
-<ScssDocs file="_spinners.scss" capture="spinner-border-css-vars"/>
+<ScssDocs file="_spinners.scss" capture="spinner-border-css-vars" />
 
 Growing spinner variables:
 
-<ScssDocs file="_spinners.scss" capture="spinner-grow-css-vars"/>
+<ScssDocs file="_spinners.scss" capture="spinner-grow-css-vars" />
 
 For both spinners, small spinner modifier classes are used to update the values of these CSS variables as needed. For example, the `.spinner-border-sm` class does the following:
 
-<ScssDocs file="_spinners.scss" capture="spinner-border-sm-css-vars"/>
+<ScssDocs file="_spinners.scss" capture="spinner-border-sm-css-vars" />
 
 #### How to use CSS variables
 
@@ -124,10 +176,18 @@ return <CSpinner style={vars}>...</CSpinner>
 
 ### SASS variables
 
-<ScssDocs file="_variables.scss" capture="spinner-variables"/>
+<ScssDocs file="_variables.scss" capture="spinner-variables" />
+
+### Keyframes
+
+Used for creating the CSS animations for our spinners. Included in `_spinners.scss`.
+
+<ScssDocs file="_spinners.scss" capture="spinner-border-keyframes" />
+
+<ScssDocs file="_spinners.scss" capture="spinner-grow-keyframes" />
 
 ## API
 
 ### CSpinner
 
-`markdown:CSpinner.api.mdx`
\ No newline at end of file
+`markdown:CSpinner.api.mdx`
diff --git a/packages/docs/content/layout/gutters.mdx b/packages/docs/content/layout/gutters.mdx
index ea0afe94..0674a963 100644
--- a/packages/docs/content/layout/gutters.mdx
+++ b/packages/docs/content/layout/gutters.mdx
@@ -20,14 +20,14 @@ import { CCol, CContainer, CRow } from '@coreui/react/src/index'
 
 `{breakpoint}={{ gutterX: * }}` props can be used to control the horizontal gutter widths. The `<CContainer>` or `<CContainer fluid>` parent may need to be adjusted if larger gutters are used too to avoid unwanted overflow, using a matching padding utility. For example, in the following example we've increased the padding with `.px-4`:
 
-```jsx preview
+```jsx preview className="docs-example m-0 border-0 docs-example-cols"
 <CContainer className="px-4">
   <CRow xs={{ gutterX: 5 }}>
     <CCol>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
   </CRow>
 </CContainer>
@@ -35,14 +35,14 @@ import { CCol, CContainer, CRow } from '@coreui/react/src/index'
 
 An alternative solution is to add a wrapper around the `<CRow>` with the `.overflow-hidden` class:
 
-```jsx preview
+```jsx preview className="docs-example m-0 border-0 docs-example-cols"
 <CContainer className="overflow-hidden">
   <CRow xs={{ gutterX: 5 }}>
     <CCol>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
   </CRow>
 </CContainer>
@@ -52,20 +52,20 @@ An alternative solution is to add a wrapper around the `<CRow>` with the `.overf
 
 `{breakpoint}={{ gutterY: * }}` props can be used to control the vertical gutter widths. Like the horizontal gutters, the vertical gutters can cause some overflow below the `<CRow>` at the end of a page. If this occurs, you add a wrapper around `<CRow>` with the `.overflow-hidden` class:
 
-```jsx preview
+```jsx preview className="docs-example m-0 border-0 docs-example-cols"
 <CContainer className="overflow-hidden">
   <CRow xs={{ gutterY: 5 }}>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
   </CRow>
 </CContainer>
@@ -75,20 +75,20 @@ An alternative solution is to add a wrapper around the `<CRow>` with the `.overf
 
 `{breakpoint}={{ gutter: * }}` props can be used to control the horizontal gutter widths, for the following example we use a smaller gutter width, so there won't be a need to add the `.overflow-hidden` wrapper class.
 
-```jsx preview
+```jsx preview className="docs-example m-0 border-0 docs-example-cols"
 <CContainer>
   <CRow xs={{ gutter: 2 }}>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
     <CCol xs={{ span: 6 }}>
-      <div className="p-3 border bg-light">Custom column padding</div>
+      <div className="p-3">Custom column padding</div>
     </CCol>
   </CRow>
 </CContainer>
@@ -98,38 +98,38 @@ An alternative solution is to add a wrapper around the `<CRow>` with the `.overf
 
 Gutter props can also be added to [row columns](../layout/grid#row-columns). In the following example, we use responsive row columns and responsive gutter props.
 
-```jsx preview
+```jsx preview className="docs-example m-0 border-0 docs-example-cols"
 <CContainer>
   <CRow xs={{ cols:2, gutter: 2 }} lg={{ cols: 5, gutter: 3}}>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
     <CCol>
-      <div className="p-3 border bg-light">Row column</div>
+      <div className="p-3">Row column</div>
     </CCol>
   </CRow>
 </CContainer>
@@ -143,13 +143,27 @@ The gutters between columns in our predefined grid props can be removed with `{b
 
 In practice, here's how it looks. Note you can continue to use this with all other predefined grid props (including column widths, responsive tiers, reorders, and more).
 
-```jsx preview
-<div className="docs-example-row">
-  <CRow xs={{ gutter: 0 }}>
-    <CCol sm={6} md={8}>.col-sm-6 .col-md-8</CCol>
-    <CCol xs={6} md={4}>.col-6 .col-md-4</CCol>
-  </CRow>
-</div>
+```jsx preview className="docs-example m-0 border-0 docs-example-row"
+<CRow xs={{ gutter: 0 }}>
+  <CCol sm={6} md={8}>.col-sm-6 .col-md-8</CCol>
+  <CCol xs={6} md={4}>.col-6 .col-md-4</CCol>
+</CRow>
+```
+
+## Change the gutters
+
+Classes are built from the `$gutters` Sass map which is inherited from the `$spacers` Sass map.
+
+```scss
+$grid-gutter-width: 1.5rem;
+$gutters: (
+  0: 0,
+  1: $spacer * .25,
+  2: $spacer * .5,
+  3: $spacer,
+  4: $spacer * 1.5,
+  5: $spacer * 3,
+);
 ```
 
 ## API

From c8e1e0ca0f96eccd7426bbf1672ebc7c9e346fa3 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 2 Aug 2023 23:49:58 +0200
Subject: [PATCH 19/49] docs: update theme

---
 packages/docs/src/components/CodeBlock.tsx        |  6 +++++-
 packages/docs/src/components/Sidebar.tsx          |  2 +-
 packages/docs/src/nav.tsx                         |  2 +-
 packages/docs/src/styles/_component-examples.scss | 15 ++++++++++-----
 packages/docs/src/styles/_footer.scss             |  2 +-
 5 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/packages/docs/src/components/CodeBlock.tsx b/packages/docs/src/components/CodeBlock.tsx
index 82959d0d..d7fd2422 100644
--- a/packages/docs/src/components/CodeBlock.tsx
+++ b/packages/docs/src/components/CodeBlock.tsx
@@ -1,11 +1,15 @@
 import React, { FC } from 'react'
-import { Highlight } from 'prism-react-renderer'
+import { Highlight, Prism } from 'prism-react-renderer'
 
 interface CodeBlockProps {
   children: any // eslint-disable-line @typescript-eslint/no-explicit-any
 }
 
 const CodeBlock: FC<CodeBlockProps> = ({ children }) => {
+  ;(typeof global === 'undefined' ? window : global).Prism = Prism
+  // eslint-disable-next-line unicorn/prefer-module
+  require('prismjs/components/prism-bash')
+  require('prismjs/components/prism-scss')
   const _children = children && children.props.children
   const language = children.props.className
     ? children.props.className.replace(/language-/, '')
diff --git a/packages/docs/src/components/Sidebar.tsx b/packages/docs/src/components/Sidebar.tsx
index 4df70645..26326fcf 100644
--- a/packages/docs/src/components/Sidebar.tsx
+++ b/packages/docs/src/components/Sidebar.tsx
@@ -48,7 +48,7 @@ const Sidebar: FC<SidebarProps> = ({ ...props }) => {
               </g>
             </svg>
           </CSidebarBrand>
-          <div className="text-muted ms-3 me-5 mb-2 small fw-semibold">Framework:</div>
+          <div className="text-body-secondary ms-3 me-5 mb-2 small fw-semibold">Framework:</div>
           <CDropdown className="ms-3 me-5 mb-4">
             <CDropdownToggle color="primary" variant="outline">
               React.js
diff --git a/packages/docs/src/nav.tsx b/packages/docs/src/nav.tsx
index 4d5418ba..d9ea08ee 100644
--- a/packages/docs/src/nav.tsx
+++ b/packages/docs/src/nav.tsx
@@ -88,7 +88,7 @@ const nav = [
         to: '/layout/columns/',
       },
       {
-        name: 'Gutter',
+        name: 'Gutters',
         to: '/layout/gutters/',
       },
     ],
diff --git a/packages/docs/src/styles/_component-examples.scss b/packages/docs/src/styles/_component-examples.scss
index 32eff0d7..84abfc90 100644
--- a/packages/docs/src/styles/_component-examples.scss
+++ b/packages/docs/src/styles/_component-examples.scss
@@ -109,6 +109,14 @@
   .pagination {
     margin-bottom: 0;
   }
+
+  // Spinners
+  > .spinner-grow + .spinner-border,
+  > .spinner-border + .spinner-grow,
+  > .spinner-border + .spinner-border,
+  > .spinner-grow + .spinner-grow {
+    margin-left: .25rem;
+  }
 }
 
 //
@@ -385,7 +393,8 @@
   }
 
   .docs-example ~ .highlight {
-    border: 0;
+    border: solid var(--cui-border-color);
+    border-width: 1px 0 0;
     @include border-top-radius(0);
   }
 
@@ -411,10 +420,6 @@
   }
 }
 
-.docs-example {
-  border-bottom-width: 0;
-}
-
 .docs-example + .highlight {
   border-top-width: 0;
   @include border-top-radius(0);
diff --git a/packages/docs/src/styles/_footer.scss b/packages/docs/src/styles/_footer.scss
index 14e22108..7544a17b 100644
--- a/packages/docs/src/styles/_footer.scss
+++ b/packages/docs/src/styles/_footer.scss
@@ -7,7 +7,7 @@
   @include font-size(.875rem);
 
   a {
-    color: #768192;
+    color: var(--#{$prefix}tertiary-color);
     text-decoration: none;
 
     &:hover,

From ac45603515327441a6a9c007c8f2be8058c1d71e Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 2 Aug 2023 23:50:19 +0200
Subject: [PATCH 20/49] chore: update @coreui/coreui to v4.3.0

---
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index 0ebf909e..fc5222a0 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -60,7 +60,7 @@
     "typescript": "^4.9.5"
   },
   "peerDependencies": {
-    "@coreui/coreui": "4.2.6",
+    "@coreui/coreui": "4.3.0",
     "react": ">=17",
     "react-dom": ">=17"
   }
diff --git a/packages/docs/package.json b/packages/docs/package.json
index 543b2b6e..b520232d 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -25,7 +25,7 @@
   },
   "dependencies": {
     "@coreui/chartjs": "^3.1.2",
-    "@coreui/coreui": "4.2.6",
+    "@coreui/coreui": "4.3.0",
     "@coreui/icons": "^3.0.1",
     "@coreui/icons-react": "^2.2.0",
     "@coreui/react-chartjs": "^2.1.3",

From be617041b4a7d2ab01689b0db5215220b7e3b797 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 2 Aug 2023 23:54:16 +0200
Subject: [PATCH 21/49] docs: update content

---
 packages/docs/content/components/dropdown.mdx      |  2 +-
 packages/docs/content/components/navs-tabs.mdx     |  2 +-
 packages/docs/content/layout/containers.mdx        | 14 +++++++-------
 .../docs/content/templates/admin-dashboard.mdx     | 12 ++++++------
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/packages/docs/content/components/dropdown.mdx b/packages/docs/content/components/dropdown.mdx
index 88299603..d38c1fd8 100644
--- a/packages/docs/content/components/dropdown.mdx
+++ b/packages/docs/content/components/dropdown.mdx
@@ -518,7 +518,7 @@ In the following example we use `div` instead of `<CDropdownMenu>` to show `<CDr
 Place any freeform text within a dropdown menu with text. Note that you'll likely need additional sizing styles to constrain the menu width.
 
 ```jsx preview
-<CDropdownMenu className="p-4 text-muted" style={{ maxWidth: '200px' }}>
+<CDropdownMenu className="p-4 text-body-secondary" style={{ maxWidth: '200px' }}>
   <p>Some example text that's free-flowing within the dropdown menu.</p>
   <p className="mb-0">And this is more example text.</p>
 </CDropdownMenu>
diff --git a/packages/docs/content/components/navs-tabs.mdx b/packages/docs/content/components/navs-tabs.mdx
index c0c8e9a9..eb00cba8 100644
--- a/packages/docs/content/components/navs-tabs.mdx
+++ b/packages/docs/content/components/navs-tabs.mdx
@@ -172,7 +172,7 @@ Takes the basic nav from above and adds the `variant="tabs"` class to generate a
 
 ### Pills
 
-Take that same HTML, but use `variant="pills"` instead:
+Take that same code, but use `variant="pills"` instead:
 
 ```jsx preview
 <CNav variant="pills">
diff --git a/packages/docs/content/layout/containers.mdx b/packages/docs/content/layout/containers.mdx
index 76bb8d06..3e0fe2a7 100644
--- a/packages/docs/content/layout/containers.mdx
+++ b/packages/docs/content/layout/containers.mdx
@@ -22,13 +22,13 @@ The table below illustrates how each container's `max-width` compares to the ori
 
 |  | Extra small<div className="fw-normal">&lt;576px</div> | Small<div className="fw-normal">&ge;576px</div> | Medium<div className="fw-normal">&ge;768px</div> | Large<div className="fw-normal">&ge;992px</div> | X-Large<div className="fw-normal">&ge;1200px</div> | XX-Large<div className="fw-normal">&ge;1400px</div> |
 | --- | --- | --- | --- | --- | --- | --- |
-| `.container` | <span className="text-muted">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
-| `.container-sm` | <span className="text-muted">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
-| `.container-md` | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | 720px | 960px | 1140px | 1320px |
-| `.container-lg` | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | 960px | 1140px | 1320px |
-| `.container-xl` | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | 1140px | 1320px |
-| `.container-xxl` | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | 1320px |
-| `.container-fluid` | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> | <span className="text-muted">100%</span> |
+| `.container` | <span className="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
+| `.container-sm` | <span className="text-body-secondary">100%</span> | 540px | 720px | 960px | 1140px | 1320px |
+| `.container-md` | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | 720px | 960px | 1140px | 1320px |
+| `.container-lg` | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | 960px | 1140px | 1320px |
+| `.container-xl` | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | 1140px | 1320px |
+| `.container-xxl` | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | 1320px |
+| `.container-fluid` | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> | <span className="text-body-secondary">100%</span> |
 
 
 ## Default container
diff --git a/packages/docs/content/templates/admin-dashboard.mdx b/packages/docs/content/templates/admin-dashboard.mdx
index b99d6c0c..42153487 100644
--- a/packages/docs/content/templates/admin-dashboard.mdx
+++ b/packages/docs/content/templates/admin-dashboard.mdx
@@ -27,7 +27,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/react/#compare" target="_blank">
           <CCardTitle>Free React Admin Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Default Theme</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Default Theme</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_free_1440.webp" alt=""/>
         </CLink>
       </CCardBody>
@@ -38,7 +38,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/product/react-dashboard-template/?theme=default-v3" target="_blank">
           <CCardTitle>React Dashboard Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Default Theme v3</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Default Theme v3</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_pro_default_v3_1440.webp" alt=""/>
         </CLink>
       </CCardBody>
@@ -49,7 +49,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/product/react-dashboard-template/?theme=light-v3" target="_blank">
           <CCardTitle>React Dashboard Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Light Theme v3</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Light Theme v3</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_pro_light_v3_1440.webp" alt=""/>
         </CLink>
       </CCardBody>
@@ -60,7 +60,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/product/react-dashboard-template/?theme=default" target="_blank">
           <CCardTitle>React Dashboard Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Default Theme</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Default Theme</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_pro_default_1440.webp" alt=""/>
         </CLink>
       </CCardBody>
@@ -71,7 +71,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/product/react-dashboard-template/?theme=light" target="_blank">
           <CCardTitle>React Dashboard Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Light Theme</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Light Theme</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_pro_light_1440.webp" alt=""/>
         </CLink>
       </CCardBody>
@@ -82,7 +82,7 @@ Check out the fully-featured, ready-to-use admin dashboard templates built using
       <CCardBody>
         <CLink className="text-decoration-none text-reset" href="https://coreui.io/product/react-dashboard-template/?theme=dark" target="_blank">
           <CCardTitle>React Dashboard Template</CCardTitle>
-          <CCardSubtitle className="mb-3 text-muted">Dark Theme</CCardSubtitle>
+          <CCardSubtitle className="mb-3 text-body-secondary">Dark Theme</CCardSubtitle>
           <CImage className="rounded shadow-sm" fluid src="https://coreui.io/images/templates/coreui_pro_dark_1440.webp" alt=""/>
         </CLink>
       </CCardBody>

From 9cdb63b341b7469ec05f72c80a519e7f8a425655 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 2 Aug 2023 23:54:37 +0200
Subject: [PATCH 22/49] docs: udpate theme

---
 packages/docs/src/components/Toc.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/docs/src/components/Toc.tsx b/packages/docs/src/components/Toc.tsx
index 53905068..27cedff2 100644
--- a/packages/docs/src/components/Toc.tsx
+++ b/packages/docs/src/components/Toc.tsx
@@ -34,7 +34,7 @@ const Toc: FC<TocProps> = ({ items }) => {
   }
 
   return (
-    <div className="docs-toc mt-4 mb-5 my-md-0 ps-xl-5 mb-lg-5 text-muted">
+    <div className="docs-toc mt-4 mb-5 my-md-0 ps-xl-5 mb-lg-5 text-body-secondary">
       <strong className="d-block h6 mb-2 pb-2 border-bottom">On this page</strong>
       <CNav component="nav" className="flex-column">
         <ul>{toc(items)}</ul>

From 6b22795de6d6c1727e2d2bb8e0ae42ca1d65cbe5 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 3 Aug 2023 11:47:33 +0200
Subject: [PATCH 23/49] chore: update dependencies and devDendencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

@coreui/icons-react   ^2.2.0  →   ^2.2.1
react-imask           ^7.0.1  →   ^7.1.3
sass                 ^1.63.6  →  ^1.64.2
---
 packages/docs/package.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/docs/package.json b/packages/docs/package.json
index b520232d..fcbed987 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -27,7 +27,7 @@
     "@coreui/chartjs": "^3.1.2",
     "@coreui/coreui": "4.3.0",
     "@coreui/icons": "^3.0.1",
-    "@coreui/icons-react": "^2.2.0",
+    "@coreui/icons-react": "^2.2.1",
     "@coreui/react-chartjs": "^2.1.3",
     "@coreui/utils": "^2.0.2",
     "@docsearch/css": "^3.5.1",
@@ -57,9 +57,9 @@
     "react-docgen-typescript": "^2.2.2",
     "react-dom": "^18.2.0",
     "react-helmet": "^6.1.0",
-    "react-imask": "^7.0.1",
+    "react-imask": "^7.1.3",
     "rimraf": "^5.0.1",
-    "sass": "^1.63.6"
+    "sass": "^1.64.2"
   },
   "devDependencies": {
     "npm-run-all": "^4.1.5"

From 16d116ba6e5cb491670eac9c7da9d9c3b78e6e5f Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 3 Aug 2023 11:48:37 +0200
Subject: [PATCH 24/49] chore: update dependencies and devDependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

@rollup/plugin-commonjs    ^25.0.2  →  ^25.0.3
@testing-library/jest-dom  ^5.16.5  →  ^5.17.0
@types/react               18.2.14  →  18.2.18
@types/react-dom           ^18.2.6  →  ^18.2.7
jest                       ^29.6.1  →  ^29.6.2
jest-environment-jsdom     ^29.6.1  →  ^29.6.2
rollup                     ^3.26.2  →  ^3.27.0
tslib                       ^2.6.0  →   ^2.6.1
---
 packages/coreui-react/package.json | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index fc5222a0..7a1881e7 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -38,25 +38,25 @@
   },
   "devDependencies": {
     "@popperjs/core": "^2.11.8",
-    "@rollup/plugin-commonjs": "^25.0.2",
+    "@rollup/plugin-commonjs": "^25.0.3",
     "@rollup/plugin-node-resolve": "^15.1.0",
     "@rollup/plugin-typescript": "^11.1.2",
-    "@testing-library/jest-dom": "^5.16.5",
+    "@testing-library/jest-dom": "^5.17.0",
     "@testing-library/react": "^14.0.0",
-    "@types/react": "18.2.14",
-    "@types/react-dom": "^18.2.6",
+    "@types/react": "18.2.18",
+    "@types/react-dom": "^18.2.7",
     "@types/react-transition-group": "^4.4.6",
     "classnames": "^2.3.2",
-    "jest": "^29.6.1",
-    "jest-environment-jsdom": "^29.6.1",
+    "jest": "^29.6.2",
+    "jest-environment-jsdom": "^29.6.2",
     "prop-types": "^15.8.1",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-popper": "^2.3.0",
     "react-transition-group": "^4.4.5",
-    "rollup": "^3.26.2",
+    "rollup": "^3.27.0",
     "ts-jest": "^29.1.1",
-    "tslib": "^2.6.0",
+    "tslib": "^2.6.1",
     "typescript": "^4.9.5"
   },
   "peerDependencies": {

From b0d44183e545a067b95c80e3ccf1d4c996491d6f Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 3 Aug 2023 11:52:07 +0200
Subject: [PATCH 25/49] release: v4.9.2

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 469701f6..872140e9 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.1.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.2.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index 14405247..b9c77020 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.9.1",
+  "version": "4.9.2",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index f2a4a49a..4d4b7419 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.1.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.2.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index 7a1881e7..e7abd06d 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.9.1",
+  "version": "4.9.2",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index fcbed987..8525c51d 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.9.1",
+  "version": "4.9.2",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From 4e7daabba3561fb5a04275cb5bb5be0860d00e2a Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Wed, 9 Aug 2023 20:44:05 +0200
Subject: [PATCH 26/49] docs: update content

---
 .../docs/content/components/navs-tabs.mdx     | 216 ++++++++++++++----
 1 file changed, 170 insertions(+), 46 deletions(-)

diff --git a/packages/docs/content/components/navs-tabs.mdx b/packages/docs/content/components/navs-tabs.mdx
index eb00cba8..96a335ed 100644
--- a/packages/docs/content/components/navs-tabs.mdx
+++ b/packages/docs/content/components/navs-tabs.mdx
@@ -337,43 +337,65 @@ export const TabPanesExample = () => {
   return (
     <>
       <CNav variant="tabs" role="tablist">
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 1}
+            component="button"
+            role="tab"
+            aria-controls="home-tab-pane"
+            aria-selected={activeKey === 1}
             onClick={() => setActiveKey(1)}
           >
             Home
           </CNavLink>
         </CNavItem>
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 2}
+            component="button"
+            role="tab"
+            aria-controls="profile-tab-pane"
+            aria-selected={activeKey === 2}
             onClick={() => setActiveKey(2)}
           >
             Profile
           </CNavLink>
         </CNavItem>
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 3}
+            component="button"
+            role="tab"
+            aria-controls="contact-tab-pane"
+            aria-selected={activeKey === 3}
             onClick={() => setActiveKey(3)}
           >
             Contact
           </CNavLink>
         </CNavItem>
+        <CNavItem role="presentation">
+          <CNavLink
+            active={activeKey === 4}
+            component="button"
+            disabled
+            role="tab"
+            aria-controls="disabled-tab-pane"
+            aria-selected={activeKey === 4}
+            onClick={() => setActiveKey(4)}
+          >
+            Disabled
+          </CNavLink>
+        </CNavItem>
       </CNav>
       <CTabContent>
-        <CTabPane role="tabpanel" aria-labelledby="home-tab" visible={activeKey === 1}>
+        <CTabPane role="tabpanel" aria-labelledby="home-tab-pane" visible={activeKey === 1}>
           Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown
           aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan
           helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh
           mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan
           aliquip quis cardigan american apparel, butcher voluptate nisi qui.
         </CTabPane>
-        <CTabPane role="tabpanel" aria-labelledby="profile-tab" visible={activeKey === 2}>
+        <CTabPane role="tabpanel" aria-labelledby="profile-tab-pane" visible={activeKey === 2}>
           Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid.
           Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan
           four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft
@@ -383,7 +405,7 @@ export const TabPanesExample = () => {
           sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party
           scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
         </CTabPane>
-        <CTabPane role="tabpanel" aria-labelledby="contact-tab" visible={activeKey === 3}>
+        <CTabPane role="tabpanel" aria-labelledby="contact-tab-pane" visible={activeKey === 3}>
           Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
           lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
           tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie
@@ -392,6 +414,15 @@ export const TabPanesExample = () => {
           mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog
           stumptown. Pitchfork sustainable tofu synth chambray yr.
         </CTabPane>
+        <CTabPane role="tabpanel" aria-labelledby="disabled-tab-pane" visible={activeKey === 3}>
+          Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
+          lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
+          tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica.
+          DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh
+          mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog.
+          Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown.
+          Pitchfork sustainable tofu synth chambray yr.
+        </CTabPane>
       </CTabContent>
     </>
   )
@@ -406,53 +437,84 @@ const [activeKey, setActiveKey] = useState(1)
 return (
   <>
     <CNav variant="tabs" role="tablist">
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 1}
+          component="button"
+          role="tab"
+          aria-controls="home-tab-pane"
+          aria-selected={activeKey === 1}
           onClick={() => setActiveKey(1)}
         >
           Home
         </CNavLink>
       </CNavItem>
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 2}
+          component="button"
+          role="tab"
+          aria-controls="profile-tab-pane"
+          aria-selected={activeKey === 2}
           onClick={() => setActiveKey(2)}
         >
           Profile
         </CNavLink>
       </CNavItem>
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 3}
+          component="button"
+          role="tab"
+          aria-controls="contact-tab-pane"
+          aria-selected={activeKey === 3}
           onClick={() => setActiveKey(3)}
         >
           Contact
         </CNavLink>
       </CNavItem>
+      <CNavItem role="presentation">
+        <CNavLink
+          active={activeKey === 4}
+          component="button"
+          disabled
+          role="tab"
+          aria-controls="disabled-tab-pane"
+          aria-selected={activeKey === 4}
+          onClick={() => setActiveKey(4)}
+        >
+          Disabled
+        </CNavLink>
+      </CNavItem>
     </CNav>
     <CTabContent>
-      <CTabPane role="tabpanel" aria-labelledby="home-tab" visible={activeKey === 1}>
+      <CTabPane role="tabpanel" aria-labelledby="home-tab-pane" visible={activeKey === 1}>
         Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown
         aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan
         helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh
         mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan
         aliquip quis cardigan american apparel, butcher voluptate nisi qui.
       </CTabPane>
-      <CTabPane role="tabpanel" aria-labelledby="profile-tab" visible={activeKey === 2}>
+      <CTabPane role="tabpanel" aria-labelledby="profile-tab-pane" visible={activeKey === 2}>
         Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid.
         Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan
         four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft
-        beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda
-        labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit
-        sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean
-        shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown,
-        tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
+        beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic,
+        assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero
+        magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit,
+        sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party
+        scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
+      </CTabPane>
+      <CTabPane role="tabpanel" aria-labelledby="contact-tab-pane" visible={activeKey === 3}>
+        Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
+        lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
+        tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie
+        helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork.
+        Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro
+        mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog
+        stumptown. Pitchfork sustainable tofu synth chambray yr.
       </CTabPane>
-      <CTabPane role="tabpanel" aria-labelledby="contact-tab" visible={activeKey === 3}>
+      <CTabPane role="tabpanel" aria-labelledby="disabled-tab-pane" visible={activeKey === 3}>
         Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
         lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
         tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica.
@@ -473,43 +535,65 @@ export const TabPanesPillsExample = () => {
   return (
     <>
       <CNav variant="pills" role="tablist">
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 1}
+            component="button"
+            role="tab"
+            aria-controls="home-tab-pane"
+            aria-selected={activeKey === 1}
             onClick={() => setActiveKey(1)}
           >
             Home
           </CNavLink>
         </CNavItem>
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 2}
+            component="button"
+            role="tab"
+            aria-controls="profile-tab-pane"
+            aria-selected={activeKey === 2}
             onClick={() => setActiveKey(2)}
           >
             Profile
           </CNavLink>
         </CNavItem>
-        <CNavItem>
+        <CNavItem role="presentation">
           <CNavLink
-            href="#!"
             active={activeKey === 3}
+            component="button"
+            role="tab"
+            aria-controls="contact-tab-pane"
+            aria-selected={activeKey === 3}
             onClick={() => setActiveKey(3)}
           >
             Contact
           </CNavLink>
         </CNavItem>
+        <CNavItem role="presentation">
+          <CNavLink
+            active={activeKey === 4}
+            component="button"
+            disabled
+            role="tab"
+            aria-controls="disabled-tab-pane"
+            aria-selected={activeKey === 4}
+            onClick={() => setActiveKey(4)}
+          >
+            Disabled
+          </CNavLink>
+        </CNavItem>
       </CNav>
       <CTabContent>
-        <CTabPane role="tabpanel" aria-labelledby="home-tab" visible={activeKey === 1}>
+        <CTabPane role="tabpanel" aria-labelledby="home-tab-pane" visible={activeKey === 1}>
           Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown
           aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan
           helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh
           mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan
           aliquip quis cardigan american apparel, butcher voluptate nisi qui.
         </CTabPane>
-        <CTabPane role="tabpanel" aria-labelledby="profile-tab" visible={activeKey === 2}>
+        <CTabPane role="tabpanel" aria-labelledby="profile-tab-pane" visible={activeKey === 2}>
           Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid.
           Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan
           four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft
@@ -519,7 +603,7 @@ export const TabPanesPillsExample = () => {
           sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party
           scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
         </CTabPane>
-        <CTabPane role="tabpanel" aria-labelledby="contact-tab" visible={activeKey === 3}>
+        <CTabPane role="tabpanel" aria-labelledby="contact-tab-pane" visible={activeKey === 3}>
           Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
           lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
           tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie
@@ -528,6 +612,15 @@ export const TabPanesPillsExample = () => {
           mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog
           stumptown. Pitchfork sustainable tofu synth chambray yr.
         </CTabPane>
+        <CTabPane role="tabpanel" aria-labelledby="disabled-tab-pane" visible={activeKey === 3}>
+          Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
+          lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
+          tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica.
+          DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh
+          mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog.
+          Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown.
+          Pitchfork sustainable tofu synth chambray yr.
+        </CTabPane>
       </CTabContent>
     </>
   )
@@ -542,53 +635,84 @@ const [activeKey, setActiveKey] = useState(1)
 return (
   <>
     <CNav variant="pills" role="tablist">
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 1}
+          component="button"
+          role="tab"
+          aria-controls="home-tab-pane"
+          aria-selected={activeKey === 1}
           onClick={() => setActiveKey(1)}
         >
           Home
         </CNavLink>
       </CNavItem>
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 2}
+          component="button"
+          role="tab"
+          aria-controls="profile-tab-pane"
+          aria-selected={activeKey === 2}
           onClick={() => setActiveKey(2)}
         >
           Profile
         </CNavLink>
       </CNavItem>
-      <CNavItem>
+      <CNavItem role="presentation">
         <CNavLink
-          href="#!"
           active={activeKey === 3}
+          component="button"
+          role="tab"
+          aria-controls="contact-tab-pane"
+          aria-selected={activeKey === 3}
           onClick={() => setActiveKey(3)}
         >
           Contact
         </CNavLink>
       </CNavItem>
+      <CNavItem role="presentation">
+        <CNavLink
+          active={activeKey === 4}
+          component="button"
+          disabled
+          role="tab"
+          aria-controls="disabled-tab-pane"
+          aria-selected={activeKey === 4}
+          onClick={() => setActiveKey(4)}
+        >
+          Disabled
+        </CNavLink>
+      </CNavItem>
     </CNav>
     <CTabContent>
-      <CTabPane role="tabpanel" aria-labelledby="home-tab" visible={activeKey === 1}>
+      <CTabPane role="tabpanel" aria-labelledby="home-tab-pane" visible={activeKey === 1}>
         Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown
         aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan
         helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh
         mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan
         aliquip quis cardigan american apparel, butcher voluptate nisi qui.
       </CTabPane>
-      <CTabPane role="tabpanel" aria-labelledby="profile-tab" visible={activeKey === 2}>
+      <CTabPane role="tabpanel" aria-labelledby="profile-tab-pane" visible={activeKey === 2}>
         Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid.
         Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan
         four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft
-        beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda
-        labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit
-        sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean
-        shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown,
-        tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
+        beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic,
+        assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero
+        magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit,
+        sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party
+        scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.
+      </CTabPane>
+      <CTabPane role="tabpanel" aria-labelledby="contact-tab-pane" visible={activeKey === 3}>
+        Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
+        lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
+        tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie
+        helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork.
+        Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro
+        mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog
+        stumptown. Pitchfork sustainable tofu synth chambray yr.
       </CTabPane>
-      <CTabPane role="tabpanel" aria-labelledby="contact-tab" visible={activeKey === 3}>
+      <CTabPane role="tabpanel" aria-labelledby="disabled-tab-pane" visible={activeKey === 3}>
         Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic
         lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork
         tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica.

From de09cbecf3b40ef3696db2892d38d84c0a22436e Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 8 Sep 2023 15:52:53 +0200
Subject: [PATCH 27/49] fix(CPopover, CTooltip): prevent removing the popper
 style before the transition ends

---
 .../src/components/popover/CPopover.tsx       |  4 +-
 .../src/components/tooltip/CTooltip.tsx       |  4 +-
 packages/coreui-react/src/hooks/usePopper.ts  | 12 ++++-
 .../src/utils/executeAfterTransition.ts       | 46 +++++++++++++++++++
 .../utils/getTransitionDurationFromElement.ts | 24 ++++++++++
 packages/coreui-react/src/utils/index.ts      | 10 +++-
 6 files changed, 93 insertions(+), 7 deletions(-)
 create mode 100644 packages/coreui-react/src/utils/executeAfterTransition.ts
 create mode 100644 packages/coreui-react/src/utils/getTransitionDurationFromElement.ts

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index ecf8597b..8dbd48bc 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
 import { usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
-import { getRTLPlacement } from '../../utils'
+import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
 
 export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'content'> {
   /**
@@ -164,7 +164,7 @@ export const CPopover: FC<CPopoverProps> = ({
             onExit={onHide}
             timeout={{
               enter: 0,
-              exit: 200,
+              exit: popoverRef.current ? getTransitionDurationFromElement(popoverRef.current) + 50 : 200,
             }}
             unmountOnExit
           >
diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index ed44be0d..a59f4965 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
 import { usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
-import { getRTLPlacement } from '../../utils'
+import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
 
 export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {
   /**
@@ -158,7 +158,7 @@ export const CTooltip: FC<CTooltipProps> = ({
             onExit={onHide}
             timeout={{
               enter: 0,
-              exit: 200,
+              exit: tooltipRef.current ? getTransitionDurationFromElement(tooltipRef.current) + 50 : 200,
             }}
             unmountOnExit
           >
diff --git a/packages/coreui-react/src/hooks/usePopper.ts b/packages/coreui-react/src/hooks/usePopper.ts
index 051a2718..898a402e 100644
--- a/packages/coreui-react/src/hooks/usePopper.ts
+++ b/packages/coreui-react/src/hooks/usePopper.ts
@@ -2,6 +2,8 @@ import { useRef } from 'react'
 import { createPopper } from '@popperjs/core'
 import type { Instance, Options } from '@popperjs/core'
 
+import { executeAfterTransition } from '../utils'
+
 interface UsePopperOutput {
   popper: Instance | undefined
   initPopper: (reference: HTMLElement, popper: HTMLElement, options: Partial<Options>) => void
@@ -10,14 +12,20 @@ interface UsePopperOutput {
 
 export const usePopper = (): UsePopperOutput => {
   const _popper = useRef<Instance>()
+  const el = useRef<HTMLElement>()
 
   const initPopper = (reference: HTMLElement, popper: HTMLElement, options: Partial<Options>) => {
     _popper.current = createPopper(reference, popper, options)
+    el.current = popper
   }
 
   const destroyPopper = () => {
-    if (_popper.current) {
-      _popper.current.destroy()
+    const popperInstance = _popper.current
+
+    if (popperInstance && el.current) {
+      executeAfterTransition(() => {
+        popperInstance.destroy()
+      }, el.current)
     }
 
     _popper.current = undefined
diff --git a/packages/coreui-react/src/utils/executeAfterTransition.ts b/packages/coreui-react/src/utils/executeAfterTransition.ts
new file mode 100644
index 00000000..7b0bed80
--- /dev/null
+++ b/packages/coreui-react/src/utils/executeAfterTransition.ts
@@ -0,0 +1,46 @@
+import getTransitionDurationFromElement from './getTransitionDurationFromElement'
+
+const execute = (callback: () => void) => {
+  if (typeof callback === 'function') {
+    callback()
+  }
+}
+
+const triggerTransitionEnd = (element: HTMLElement) => {
+  element.dispatchEvent(new Event('transitionend'))
+}
+
+const executeAfterTransition = (
+  callback: () => void,
+  transitionElement: HTMLElement,
+  waitForTransition = true,
+) => {
+  if (!waitForTransition) {
+    execute(callback)
+    return
+  }
+
+  const durationPadding = 5
+  const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding
+
+  let called = false
+
+  const handler = ({ target }: { target: any }) => {
+    if (target !== transitionElement) {
+      return
+    }
+
+    called = true
+    transitionElement.removeEventListener('transitionend', handler)
+    execute(callback)
+  }
+
+  transitionElement.addEventListener('transitionend', handler)
+  setTimeout(() => {
+    if (!called) {
+      triggerTransitionEnd(transitionElement)
+    }
+  }, emulatedDuration)
+}
+
+export default executeAfterTransition
diff --git a/packages/coreui-react/src/utils/getTransitionDurationFromElement.ts b/packages/coreui-react/src/utils/getTransitionDurationFromElement.ts
new file mode 100644
index 00000000..ffaf546d
--- /dev/null
+++ b/packages/coreui-react/src/utils/getTransitionDurationFromElement.ts
@@ -0,0 +1,24 @@
+const getTransitionDurationFromElement = (element: HTMLElement) => {
+  if (!element) {
+    return 0
+  }
+
+  // Get transition-duration of the element
+  let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
+
+  const floatTransitionDuration = Number.parseFloat(transitionDuration)
+  const floatTransitionDelay = Number.parseFloat(transitionDelay)
+
+  // Return 0 if element or transition duration is not found
+  if (!floatTransitionDuration && !floatTransitionDelay) {
+    return 0
+  }
+
+  // If multiple durations are defined, take the first
+  transitionDuration = transitionDuration.split(',')[0]
+  transitionDelay = transitionDelay.split(',')[0]
+
+  return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * 1000
+}
+
+export default getTransitionDurationFromElement
\ No newline at end of file
diff --git a/packages/coreui-react/src/utils/index.ts b/packages/coreui-react/src/utils/index.ts
index d6f647f6..10dbd154 100644
--- a/packages/coreui-react/src/utils/index.ts
+++ b/packages/coreui-react/src/utils/index.ts
@@ -1,5 +1,13 @@
+import executeAfterTransition from './executeAfterTransition'
 import getRTLPlacement from './getRTLPlacement'
+import getTransitionDurationFromElement from './getTransitionDurationFromElement'
 import isInViewport from './isInViewport'
 import isRTL from './isRTL'
 
-export { getRTLPlacement, isInViewport, isRTL }
+export {
+  executeAfterTransition,
+  getRTLPlacement,
+  getTransitionDurationFromElement,
+  isInViewport,
+  isRTL,
+}

From e686c89832b165ef018bf55a2f4752f51d862b90 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 14:11:45 +0200
Subject: [PATCH 28/49] feat(CModal): restore focus to the previously focused
 element once the modal is hidden

---
 packages/coreui-react/src/components/modal/CModal.tsx | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 7a81b99f..9548d5c9 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -111,6 +111,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
     },
     ref,
   ) => {
+    const activeElementRef = useRef<HTMLElement | null>(null)
     const modalRef = useRef<HTMLDivElement>(null)
     const modalContentRef = useRef<HTMLDivElement>(null)
     const forkedRef = useForkedRef(ref, modalRef)
@@ -129,6 +130,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
 
     useEffect(() => {
       if (_visible) {
+        activeElementRef.current = document.activeElement as HTMLElement | null
         document.addEventListener('mouseup', handleClickOutside)
         document.addEventListener('keydown', handleKeyDown)
       }
@@ -145,6 +147,11 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
       }
 
       setVisible(false)
+
+      if (activeElementRef.current) {
+        activeElementRef.current.focus()
+      }
+
       return onClose && onClose()
     }
 

From 3294c5af470ad81e7ff3e0736627be9d31e53bb9 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 14:21:31 +0200
Subject: [PATCH 29/49] feat(CModal): restore focus to the previously focused
 element once the modal is hidden

---
 packages/coreui-react/src/components/modal/CModal.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 9548d5c9..64986540 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -133,6 +133,10 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
         activeElementRef.current = document.activeElement as HTMLElement | null
         document.addEventListener('mouseup', handleClickOutside)
         document.addEventListener('keydown', handleKeyDown)
+      } else {
+        if (activeElementRef.current) {
+          activeElementRef.current.focus()
+        }
       }
 
       return () => {
@@ -148,10 +152,6 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
 
       setVisible(false)
 
-      if (activeElementRef.current) {
-        activeElementRef.current.focus()
-      }
-
       return onClose && onClose()
     }
 

From cfd172b6747959e7c9cac8e30d3ea5a06278d2b2 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 14:51:41 +0200
Subject: [PATCH 30/49] add `focus` property to allow set if puts the focus on
 the modal when shown.

---
 .../coreui-react/src/components/modal/CModal.tsx   | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 64986540..18fc871d 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -35,6 +35,12 @@ export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
    * @ignore
    */
   duration?: number
+  /**
+   * Puts the focus on the modal when shown.
+   * 
+   * @since v4.10.0
+   */
+  focus?: boolean
   /**
    * Set modal to covers the entire user viewport.
    */
@@ -96,6 +102,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
       backdrop = true,
       className,
       duration = 150,
+      focus = true,
       fullscreen,
       keyboard = true,
       onClose,
@@ -134,9 +141,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
         document.addEventListener('mouseup', handleClickOutside)
         document.addEventListener('keydown', handleKeyDown)
       } else {
-        if (activeElementRef.current) {
-          activeElementRef.current.focus()
-        }
+        activeElementRef.current?.focus()
       }
 
       return () => {
@@ -172,7 +177,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
 
         setTimeout(
           () => {
-            modalRef.current?.focus()
+            focus && modalRef.current?.focus()
           },
           transition ? duration : 0,
         )
@@ -271,6 +276,7 @@ CModal.propTypes = {
   children: PropTypes.node,
   className: PropTypes.string,
   duration: PropTypes.number,
+  focus: PropTypes.bool,
   fullscreen: PropTypes.oneOfType([
     PropTypes.bool,
     PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']),

From a7318976d77aa330bd3507175db9fdb988a036f6 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 16:47:35 +0200
Subject: [PATCH 31/49] refactor(CModal): improve accessibility

---
 packages/coreui-react/src/components/modal/CModal.tsx | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 18fc871d..c249e30e 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -37,7 +37,7 @@ export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
   duration?: number
   /**
    * Puts the focus on the modal when shown.
-   * 
+   *
    * @since v4.10.0
    */
   focus?: boolean
@@ -239,10 +239,12 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
                     className,
                   )}
                   tabIndex={-1}
+                  {...(_visible ? { 'aria-modal': true } : { 'aria-hidden': 'true' })}
                   role="dialog"
                   style={{
                     ...(state !== 'exited' && { display: 'block' }),
                   }}
+                  {...rest}
                   ref={forkedRef}
                 >
                   <CModalDialog
@@ -251,7 +253,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
                     scrollable={scrollable}
                     size={size}
                   >
-                    <CModalContent {...rest} ref={modalContentRef}>
+                    <CModalContent ref={modalContentRef}>
                       {children}
                     </CModalContent>
                   </CModalDialog>

From db383a520f66896439dbcf2028e0935325d56344 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 16:48:11 +0200
Subject: [PATCH 32/49] docs(CModal): add new examples

---
 packages/docs/content/components/modal.mdx | 478 +++++++++++++++++----
 1 file changed, 392 insertions(+), 86 deletions(-)

diff --git a/packages/docs/content/components/modal.mdx b/packages/docs/content/components/modal.mdx
index 4665d7d5..4f496749 100644
--- a/packages/docs/content/components/modal.mdx
+++ b/packages/docs/content/components/modal.mdx
@@ -38,8 +38,12 @@ Below is a static react modal component example (meaning its `position` and `dis
           <p>React Modal body text goes here.</p>
         </div>
         <div className="modal-footer">
-          <button type="button" className="btn btn-secondary">Close</button>
-          <button type="button" className="btn btn-primary">Save changes</button>
+          <button type="button" className="btn btn-secondary">
+            Close
+          </button>
+          <button type="button" className="btn btn-primary">
+            Save changes
+          </button>
         </div>
       </div>
     </div>
@@ -69,9 +73,13 @@ export const LiveDemoExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-      <CModal visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="LiveDemoExampleLabel"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="LiveDemoExampleLabel">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           <p>Woohoo, you're reading this text in a modal!</p>
@@ -96,9 +104,13 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-    <CModal visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="LiveDemoExampleLabel"
+    >
       <CModalHeader onClose={() => setVisible(false)}>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="LiveDemoExampleLabel">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         <p>Woohoo, you're reading this text in a modal!</p>
@@ -123,9 +135,14 @@ export const StaticBackdropExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Launch static backdrop modal</CButton>
-      <CModal backdrop="static" visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        backdrop="static"
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="StaticBackdropExampleLabel"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="StaticBackdropExampleLabel">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           I will not close if you click outside me. Don't even try to press escape key.
@@ -150,9 +167,14 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Launch static backdrop modal</CButton>
-    <CModal backdrop="static" visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      backdrop="static"
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="StaticBackdropExampleLabel"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="StaticBackdropExampleLabel">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         I will not close if you click outside me. Don't even try to press escape key.
@@ -177,9 +199,13 @@ export const ScrollingLongContentExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-      <CModal visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="ScrollingLongContentExampleLabel"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="ScrollingLongContentExampleLabel">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           <p>
@@ -281,9 +307,13 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-    <CModal visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="ScrollingLongContentExampleLabel"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="ScrollingLongContentExampleLabel">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         <p>
@@ -383,9 +413,14 @@ export const ScrollingLongContentExample2 = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-      <CModal scrollable visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        scrollable
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="ScrollingLongContentExampleLabel2"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="ScrollingLongContentExampleLabel2">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           <p>
@@ -487,9 +522,14 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-    <CModal scrollable visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      scrollable
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="ScrollingLongContentExampleLabel2"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="ScrollingLongContentExampleLabel2">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         <p>
@@ -591,9 +631,14 @@ export const VerticallyCenteredExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Vertically centered modal</CButton>
-      <CModal alignment="center" visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        alignment="center"
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="VerticallyCenteredExample"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="VerticallyCenteredExample">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis
@@ -619,9 +664,14 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Vertically centered modal</CButton>
-    <CModal alignment="center" visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      alignment="center"
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="VerticallyCenteredExample"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="VerticallyCenteredExample">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in,
@@ -643,9 +693,15 @@ export const VerticallyCenteredScrollableExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Vertically centered scrollable modal</CButton>
-      <CModal alignment="center" scrollable visible={visible}  onClose={() => setVisible(false)}>
+      <CModal
+        alignment="center"
+        scrollable
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="VerticallyCenteredScrollableExample"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="VerticallyCenteredScrollableExample">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           <p>
@@ -690,9 +746,15 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Vertically centered scrollable modal</CButton>
-    <CModal alignment="center" scrollable visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      alignment="center"
+      scrollable
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="VerticallyCenteredScrollableExample"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="VerticallyCenteredScrollableExample">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         <p>
@@ -737,9 +799,14 @@ export const TooltipsAndPopoversExample = () => {
   return (
     <>
       <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-      <CModal alignment="center" visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        alignment="center"
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="TooltipsAndPopoverExample"
+      >
         <CModalHeader>
-          <CModalTitle>Modal title</CModalTitle>
+          <CModalTitle id="TooltipsAndPopoverExample">Modal title</CModalTitle>
         </CModalHeader>
         <CModalBody>
           <h5>Popover in a modal</h5>
@@ -781,9 +848,14 @@ const [visible, setVisible] = useState(false)
 return (
   <>
     <CButton onClick={() => setVisible(!visible)}>Launch demo modal</CButton>
-    <CModal alignment="center" visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      alignment="center"
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="TooltipsAndPopoverExample"
+    >
       <CModalHeader>
-        <CModalTitle>Modal title</CModalTitle>
+        <CModalTitle id="TooltipsAndPopoverExample">Modal title</CModalTitle>
       </CModalHeader>
       <CModalBody>
         <h5>Popover in a modal</h5>
@@ -816,16 +888,160 @@ return (
 )
 ```
 
+### Toggle between modals
+
+Toggle between multiple modals with some clever placement of the `visible` props. **Please note multiple modals cannot be opened at the same time** — this method simply toggles between two separate modals.
+
+export const ToggleBetweenModalsExample = () => {
+  const [visible, setVisible] = useState(false)
+  const [visible2, setVisible2] = useState(false)
+  return (
+    <>
+      <CButton onClick={() => setVisible(!visible)}>Open first modal</CButton>
+      <CModal
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="ToggleBetweenModalsExample1"
+      >
+        <CModalHeader>
+          <CModalTitle id="ToggleBetweenModalsExample1">Modal 1 title</CModalTitle>
+        </CModalHeader>
+        <CModalBody>
+          <p>Show a second modal and hide this one with the button below.</p>
+        </CModalBody>
+        <CModalFooter>
+          <CButton
+            color="primary"
+            onClick={() => {
+              setVisible(false)
+              setVisible2(true)
+            }}
+          >
+            Open second modal
+          </CButton>
+        </CModalFooter>
+      </CModal>
+      <CModal
+        visible={visible2}
+        onClick={() => {
+          setVisible(true)
+          setVisible2(false)
+        }}
+        aria-labelledby="ToggleBetweenModalsExample2"
+      >
+        <CModalHeader>
+          <CModalTitle id="ToggleBetweenModalsExample2">Modal 2 title</CModalTitle>
+        </CModalHeader>
+        <CModalBody>
+          <p>Hide this modal and show the first with the button below.</p>
+        </CModalBody>
+        <CModalFooter>
+          <CButton
+            color="primary"
+            onClick={() => {
+              setVisible(true)
+              setVisible2(false)
+            }}
+          >
+            Back to first
+          </CButton>
+        </CModalFooter>
+      </CModal>
+    </>
+  )
+}
+
+<Example>
+  <ToggleBetweenModalsExample />
+</Example>
+
+```jsx
+const [visible, setVisible] = useState(false)
+const [visible2, setVisible2] = useState(false)
+return (
+  <>
+    <CButton onClick={() => setVisible(!visible)}>Open first modal</CButton>
+    <CModal
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="ToggleBetweenModalsExample1"
+    >
+      <CModalHeader>
+        <CModalTitle id="ToggleBetweenModalsExample1">Modal 1 title</CModalTitle>
+      </CModalHeader>
+      <CModalBody>
+        <p>Show a second modal and hide this one with the button below.</p>
+      </CModalBody>
+      <CModalFooter>
+        <CButton
+          color="primary"
+          onClick={() => {
+            setVisible(false)
+            setVisible2(true)
+          }}
+        >
+          Open second modal
+        </CButton>
+      </CModalFooter>
+    </CModal>
+    <CModal
+      visible={visible2}
+      onClick={() => {
+        setVisible(true)
+        setVisible2(false)
+      }}
+      aria-labelledby="ToggleBetweenModalsExample2"
+    >
+      <CModalHeader>
+        <CModalTitle id="ToggleBetweenModalsExample2">Modal 2 title</CModalTitle>
+      </CModalHeader>
+      <CModalBody>
+        <p>Hide this modal and show the first with the button below.</p>
+      </CModalBody>
+      <CModalFooter>
+        <CButton
+          color="primary"
+          onClick={() => {
+            setVisible(true)
+            setVisible2(false)
+          }}
+        >
+          Back to first
+        </CButton>
+      </CModalFooter>
+    </CModal>
+  </>
+)
+```
+
+### Change animation
+
+The variable `$modal-fade-transform` determines the transform state of React Modal component before the modal fade-in animation, whereas the variable `$modal-show-transform` determines the transform state of Modal component after the modal fade-in animation.
+
+If you want a zoom-in animation, for example, set `$modal-fade-transform: scale(.8)`.
+
+### Remove animation
+
+For modals that simply appear rather than fade into view, set `transition` to `false`.
+
+```jsx
+<CModal transition={false}>...</CModal>
+```
+
+### Accessibility
+
+Be sure to add `aria-labelledby="..."`, referencing the modal title, to `<CModal />` Additionally, you may give a description of your modal dialog with `aria-describedby` on `<CModal>`. Note that you don’t need to add `role="dialog` since we already add it.
+
 ## Optional sizes
 
 Modals have three optional sizes, available via modifier classes to be placed on a `<CModal>`. These sizes kick in at certain breakpoints to avoid horizontal scrollbars on narrower viewports.
 
-| Size | Property size | Modal max-width |
-| --- | --- | --- |
-| Small | `'sm'` | `300px` |
-| Default | None | `500px` |
-| Large | `'lg'` | `800px` |
-| Extra large | `'xl'` | `1140px` |
+| Size        | Property size | Modal max-width |
+| ----------- | ------------- | --------------- |
+| Small       | `'sm'`        | `300px`         |
+| Default     | None          | `500px`         |
+| Large       | `'lg'`        | `800px`         |
+| Extra large | `'xl'`        | `1140px`        |
 
 export const OptionalSizesExample = () => {
   const [visibleXL, setVisibleXL] = useState(false)
@@ -836,21 +1052,36 @@ export const OptionalSizesExample = () => {
       <CButton onClick={() => setVisibleXL(!visibleXL)}>Extra large modal</CButton>
       <CButton onClick={() => setVisibleLg(!visibleLg)}>Large modal</CButton>
       <CButton onClick={() => setVisibleSm(!visibleSm)}>Small modal</CButton>
-      <CModal size="xl" visible={visibleXL} onClose={() => setVisibleXL(false)}>
+      <CModal
+        size="xl"
+        visible={visibleXL}
+        onClose={() => setVisibleXL(false)}
+        aria-labelledby="OptionalSizesExample1"
+      >
         <CModalHeader>
-          <CModalTitle>Extra large modal</CModalTitle>
+          <CModalTitle id="OptionalSizesExample1">Extra large modal</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal size="lg" visible={visibleLg} onClose={() => setVisibleLg(false)}>
+      <CModal
+        size="lg"
+        visible={visibleLg}
+        onClose={() => setVisibleLg(false)}
+        aria-labelledby="OptionalSizesExample2"
+      >
         <CModalHeader>
-          <CModalTitle>Large modal</CModalTitle>
+          <CModalTitle id="OptionalSizesExample2">Large modal</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal size="sm" visible={visibleSm} onClose={() => setVisibleSm(false)}>
+      <CModal
+        size="sm"
+        visible={visibleSm}
+        onClose={() => setVisibleSm(false)}
+        aria-labelledby="OptionalSizesExample3"
+      >
         <CModalHeader>
-          <CModalTitle>Small modal</CModalTitle>
+          <CModalTitle id="OptionalSizesExample3">Small modal</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
@@ -871,21 +1102,36 @@ return (
     <CButton onClick={() => setVisibleXL(!visibleXL)}>Extra large modal</CButton>
     <CButton onClick={() => setVisibleLg(!visibleLg)}>Large modal</CButton>
     <CButton onClick={() => setVisibleSm(!visibleSm)}>Small modal</CButton>
-    <CModal size="xl" visible={visibleXL} onClose={() => setVisibleXL(false)}>
+    <CModal
+      size="xl"
+      visible={visibleXL}
+      onClose={() => setVisibleXL(false)}
+      aria-labelledby="OptionalSizesExample1"
+    >
       <CModalHeader>
-        <CModalTitle>Extra large modal</CModalTitle>
+        <CModalTitle id="OptionalSizesExample1">Extra large modal</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal size="lg" visible={visibleLg} onClose={() => setVisibleLg(false)}>
+    <CModal
+      size="lg"
+      visible={visibleLg}
+      onClose={() => setVisibleLg(false)}
+      aria-labelledby="OptionalSizesExample2"
+    >
       <CModalHeader>
-        <CModalTitle>Large modal</CModalTitle>
+        <CModalTitle id="OptionalSizesExample2">Large modal</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal size="sm" visible={visibleSm} onClose={() => setVisibleSm(false)}>
+    <CModal
+      size="sm"
+      visible={visibleSm}
+      onClose={() => setVisibleSm(false)}
+      aria-labelledby="OptionalSizesExample3"
+    >
       <CModalHeader>
-        <CModalTitle>Small modal</CModalTitle>
+        <CModalTitle id="OptionalSizesExample3">Small modal</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
@@ -897,14 +1143,14 @@ return (
 
 Another override is the option to pop up a React modal component that covers the user viewport, available via property `fullscrean`.
 
-| Fullscrean | Availability |
-| --- | --- |
-| `true` | Always |
-| `'sm'` | Below `576px` |
-| `'md'` | Below `768px` |
-| `'lg'` | Below `992px` |
-| `'xl'` | Below `1200px` |
-| `'xxl'` | Below `1400px` |
+| Fullscrean | Availability   |
+| ---------- | -------------- |
+| `true`     | Always         |
+| `'sm'`     | Below `576px`  |
+| `'md'`     | Below `768px`  |
+| `'lg'`     | Below `992px`  |
+| `'xl'`     | Below `1200px` |
+| `'xxl'`    | Below `1400px` |
 
 export const FullscreenExample = () => {
   const [visible, setVisible] = useState(false)
@@ -921,39 +1167,69 @@ export const FullscreenExample = () => {
       <CButton onClick={() => setVisibleLg(!visibleLg)}>Full screen below lg</CButton>
       <CButton onClick={() => setVisibleXL(!visibleXL)}>Full screen below xl</CButton>
       <CButton onClick={() => setVisibleXXL(!visibleXXL)}>Full screen below xxl</CButton>
-      <CModal fullscreen visible={visible} onClose={() => setVisible(false)}>
+      <CModal
+        fullscreen
+        visible={visible}
+        onClose={() => setVisible(false)}
+        aria-labelledby="FullscreenExample1"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen</CModalTitle>
+          <CModalTitle id="FullscreenExample1">Full screen</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal fullscreen="sm" visible={visibleSm} onClose={() => setVisibleSm(false)}>
+      <CModal
+        fullscreen="sm"
+        visible={visibleSm}
+        onClose={() => setVisibleSm(false)}
+        aria-labelledby="FullscreenExample2"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen below sm</CModalTitle>
+          <CModalTitle id="FullscreenExample2">Full screen below sm</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal fullscreen="md" visible={visibleMd} onClose={() => setVisibleMd(false)}>
+      <CModal
+        fullscreen="md"
+        visible={visibleMd}
+        onClose={() => setVisibleMd(false)}
+        aria-labelledby="FullscreenExample3"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen below md</CModalTitle>
+          <CModalTitle id="FullscreenExample3">Full screen below md</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal fullscreen="lg" visible={visibleLg} onClose={() => setVisibleLg(false)}>
+      <CModal
+        fullscreen="lg"
+        visible={visibleLg}
+        onClose={() => setVisibleLg(false)}
+        aria-labelledby="FullscreenExample4"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen below lg</CModalTitle>
+          <CModalTitle id="FullscreenExample4">Full screen below lg</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal fullscreen="xl" visible={visibleXL} onClose={() => setVisibleXL(false)}>
+      <CModal
+        fullscreen="xl"
+        visible={visibleXL}
+        onClose={() => setVisibleXL(false)}
+        aria-labelledby="FullscreenExample5"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen below xl</CModalTitle>
+          <CModalTitle id="FullscreenExample5">Full screen below xl</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
-      <CModal fullscreen="xxl" visible={visibleXXL} onClose={() => setVisibleXXL(false)}>
+      <CModal
+        fullscreen="xxl"
+        visible={visibleXXL}
+        onClose={() => setVisibleXXL(false)}
+        aria-labelledby="FullscreenExample6"
+      >
         <CModalHeader>
-          <CModalTitle>Full screen below xxl</CModalTitle>
+          <CModalTitle id="FullscreenExample6">Full screen below xxl</CModalTitle>
         </CModalHeader>
         <CModalBody>...</CModalBody>
       </CModal>
@@ -980,39 +1256,69 @@ return (
     <CButton onClick={() => setVisibleLg(!visibleLg)}>Full screen below lg</CButton>
     <CButton onClick={() => setVisibleXL(!visibleXL)}>Full screen below xl</CButton>
     <CButton onClick={() => setVisibleXXL(!visibleXXL)}>Full screen below xxl</CButton>
-    <CModal fullscreen visible={visible} onClose={() => setVisible(false)}>
+    <CModal
+      fullscreen
+      visible={visible}
+      onClose={() => setVisible(false)}
+      aria-labelledby="FullscreenExample1"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen</CModalTitle>
+        <CModalTitle id="FullscreenExample1">Full screen</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal fullscreen="sm" visible={visibleSm} onClose={() => setVisibleSm(false)}>
+    <CModal
+      fullscreen="sm"
+      visible={visibleSm}
+      onClose={() => setVisibleSm(false)}
+      aria-labelledby="FullscreenExample2"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen below sm</CModalTitle>
+        <CModalTitle id="FullscreenExample2">Full screen below sm</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal fullscreen="md" visible={visibleMd} onClose={() => setVisibleMd(false)}>
+    <CModal
+      fullscreen="md"
+      visible={visibleMd}
+      onClose={() => setVisibleMd(false)}
+      aria-labelledby="FullscreenExample3"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen below md</CModalTitle>
+        <CModalTitle id="FullscreenExample3">Full screen below md</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal fullscreen="lg" visible={visibleLg} onClose={() => setVisibleLg(false)}>
+    <CModal
+      fullscreen="lg"
+      visible={visibleLg}
+      onClose={() => setVisibleLg(false)}
+      aria-labelledby="FullscreenExample4"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen below lg</CModalTitle>
+        <CModalTitle id="FullscreenExample4">Full screen below lg</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal fullscreen="xl" visible={visibleXL} onClose={() => setVisibleXL(false)}>
+    <CModal
+      fullscreen="xl"
+      visible={visibleXL}
+      onClose={() => setVisibleXL(false)}
+      aria-labelledby="FullscreenExample5"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen below xl</CModalTitle>
+        <CModalTitle id="FullscreenExample5">Full screen below xl</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
-    <CModal fullscreen="xxl" visible={visibleXXL} onClose={() => setVisibleXXL(false)}>
+    <CModal
+      fullscreen="xxl"
+      visible={visibleXXL}
+      onClose={() => setVisibleXXL(false)}
+      aria-labelledby="FullscreenExample6"
+    >
       <CModalHeader>
-        <CModalTitle>Full screen below xxl</CModalTitle>
+        <CModalTitle id="FullscreenExample6">Full screen below xxl</CModalTitle>
       </CModalHeader>
       <CModalBody>...</CModalBody>
     </CModal>
@@ -1026,29 +1332,29 @@ return (
 
 React modals use local CSS variables on `.modal` and `.modal-backdrop` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.
 
-<ScssDocs file="_modal.scss" capture="modal-css-vars"/>
+<ScssDocs file="_modal.scss" capture="modal-css-vars" />
 
-<ScssDocs file="_modal.scss" capture="modal-backdrop-css-vars"/>
+<ScssDocs file="_modal.scss" capture="modal-backdrop-css-vars" />
 
 #### How to use CSS variables
 
 ```jsx
-const vars = { 
+const vars = {
   '--my-css-var': 10,
-  '--my-another-css-var': "red" 
+  '--my-another-css-var': 'red',
 }
 return <CModal style={vars}>...</CModal>
 ```
 
 ### SASS variables
 
-<ScssDocs file="_variables.scss" capture="modal-variables"/>
+<ScssDocs file="_variables.scss" capture="modal-variables" />
 
 ### SASS loops
 
 [Responsive fullscreen modals](#fullscreen-modal) are generated via the `$breakpoints` map and a loop in `scss/_modal.scss`.
 
-<ScssDocs file="_modal.scss" capture="modal-fullscreen-loop"/>
+<ScssDocs file="_modal.scss" capture="modal-fullscreen-loop" />
 
 ## API
 

From d0fdf04519af0bc296616aac627504b2776995d4 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sat, 9 Sep 2023 18:52:59 +0200
Subject: [PATCH 33/49] docs(CModal): update content

---
 packages/docs/content/components/modal.mdx | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/packages/docs/content/components/modal.mdx b/packages/docs/content/components/modal.mdx
index 4f496749..f5256409 100644
--- a/packages/docs/content/components/modal.mdx
+++ b/packages/docs/content/components/modal.mdx
@@ -38,12 +38,8 @@ Below is a static react modal component example (meaning its `position` and `dis
           <p>React Modal body text goes here.</p>
         </div>
         <div className="modal-footer">
-          <button type="button" className="btn btn-secondary">
-            Close
-          </button>
-          <button type="button" className="btn btn-primary">
-            Save changes
-          </button>
+          <button type="button" className="btn btn-secondary">Close</button>
+          <button type="button" className="btn btn-primary">Save changes</button>
         </div>
       </div>
     </div>
@@ -1030,7 +1026,7 @@ For modals that simply appear rather than fade into view, set `transition` to `f
 
 ### Accessibility
 
-Be sure to add `aria-labelledby="..."`, referencing the modal title, to `<CModal />` Additionally, you may give a description of your modal dialog with `aria-describedby` on `<CModal>`. Note that you don’t need to add `role="dialog` since we already add it.
+Be sure to add `aria-labelledby="..."`, referencing the modal title, to `<CModal />` Additionally, you may give a description of your modal dialog with `aria-describedby` on `<CModal>`. Note that you don’t need to add `role="dialog`, `aria-hidden="true"`, and `aria-modal="true"` since we already add it.
 
 ## Optional sizes
 

From 74c6b24c8610efc722a708b51610d8d56b8351cc Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Sun, 10 Sep 2023 00:33:38 +0200
Subject: [PATCH 34/49] refactor(CModal): improve accessibility

---
 packages/coreui-react/src/components/modal/CModal.tsx | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index c249e30e..6c1da2c4 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -239,8 +239,9 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
                     className,
                   )}
                   tabIndex={-1}
-                  {...(_visible ? { 'aria-modal': true } : { 'aria-hidden': 'true' })}
-                  role="dialog"
+                  {...(_visible
+                    ? { 'aria-modal': true, role: 'dialog' }
+                    : { 'aria-hidden': 'true' })}
                   style={{
                     ...(state !== 'exited' && { display: 'block' }),
                   }}
@@ -253,9 +254,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
                     scrollable={scrollable}
                     size={size}
                   >
-                    <CModalContent ref={modalContentRef}>
-                      {children}
-                    </CModalContent>
+                    <CModalContent ref={modalContentRef}>{children}</CModalContent>
                   </CModalDialog>
                 </div>
               </CModalContext.Provider>

From 9e39bd31386f7624d8df1cdf8889d62b0f079930 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Mon, 11 Sep 2023 13:33:33 +0200
Subject: [PATCH 35/49] refactor: improve syntax

---
 packages/coreui-react/src/components/modal/CModal.tsx         | 2 +-
 packages/coreui-react/src/components/offcanvas/COffcanvas.tsx | 2 +-
 packages/coreui-react/src/components/sidebar/CSidebar.tsx     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 6c1da2c4..2c8ed10e 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types'
 import classNames from 'classnames'
 import { Transition } from 'react-transition-group'
 
-import { CBackdrop } from '../backdrop/CBackdrop'
+import { CBackdrop } from '../backdrop'
 import { CConditionalPortal } from '../conditional-portal'
 import { CModalContent } from './CModalContent'
 import { CModalDialog } from './CModalDialog'
diff --git a/packages/coreui-react/src/components/offcanvas/COffcanvas.tsx b/packages/coreui-react/src/components/offcanvas/COffcanvas.tsx
index 886a5a76..29caf739 100644
--- a/packages/coreui-react/src/components/offcanvas/COffcanvas.tsx
+++ b/packages/coreui-react/src/components/offcanvas/COffcanvas.tsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
 import classNames from 'classnames'
 import { Transition } from 'react-transition-group'
 
-import { CBackdrop } from '../backdrop/CBackdrop'
+import { CBackdrop } from '../backdrop'
 import { CConditionalPortal } from '../conditional-portal'
 
 import { useForkedRef } from '../../hooks'
diff --git a/packages/coreui-react/src/components/sidebar/CSidebar.tsx b/packages/coreui-react/src/components/sidebar/CSidebar.tsx
index 2eccb17c..509b3033 100644
--- a/packages/coreui-react/src/components/sidebar/CSidebar.tsx
+++ b/packages/coreui-react/src/components/sidebar/CSidebar.tsx
@@ -3,7 +3,7 @@ import { createPortal } from 'react-dom'
 import PropTypes from 'prop-types'
 import classNames from 'classnames'
 
-import { CBackdrop } from '../backdrop/CBackdrop'
+import { CBackdrop } from '../backdrop'
 
 import { isInViewport } from '../../utils'
 import { useForkedRef } from '../../hooks'

From 189b4a0e10657a7b0acacda2f847b6af9ff9192d Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Mon, 11 Sep 2023 18:35:14 +0200
Subject: [PATCH 36/49] release: v4.10.0

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 872140e9..c22a82e8 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.2.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index b9c77020..c5956f0e 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.9.2",
+  "version": "4.10.0",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index 4d4b7419..d353d8e0 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.9.2.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index e7abd06d..dfd32a74 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.9.2",
+  "version": "4.10.0",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index 8525c51d..e8ac08e0 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.9.2",
+  "version": "4.10.0",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From 317dc9290310a01ceb9314c3423a6aaa502c7ae3 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 22 Sep 2023 17:57:02 +0200
Subject: [PATCH 37/49] fix(CTooltip): findDOMNode is deprecated in StrictMode

---
 .../src/components/tooltip/CTooltip.tsx       | 245 ++++++++++--------
 1 file changed, 131 insertions(+), 114 deletions(-)

diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index a59f4965..68b805fc 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -1,10 +1,17 @@
-import React, { FC, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
+import React, {
+  forwardRef,
+  HTMLAttributes,
+  ReactNode,
+  useRef,
+  useEffect,
+  useState,
+} from 'react'
 import { createPortal } from 'react-dom'
 import classNames from 'classnames'
 import PropTypes from 'prop-types'
 import { Transition } from 'react-transition-group'
 
-import { usePopper } from '../../hooks'
+import { useForkedRef, usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
 import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
@@ -64,129 +71,139 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
   visible?: boolean
 }
 
-export const CTooltip: FC<CTooltipProps> = ({
-  children,
-  animation = true,
-  className,
-  content,
-  delay = 0,
-  fallbackPlacements = ['top', 'right', 'bottom', 'left'],
-  offset = [0, 6],
-  onHide,
-  onShow,
-  placement = 'top',
-  trigger = ['hover', 'focus'],
-  visible,
-  ...rest
-}) => {
-  const tooltipRef = useRef(null)
-  const togglerRef = useRef(null)
-  const { initPopper, destroyPopper } = usePopper()
-  const [_visible, setVisible] = useState(visible)
+export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
+  (
+    {
+      children,
+      animation = true,
+      className,
+      content,
+      delay = 0,
+      fallbackPlacements = ['top', 'right', 'bottom', 'left'],
+      offset = [0, 6],
+      onHide,
+      onShow,
+      placement = 'top',
+      trigger = ['hover', 'focus'],
+      visible,
+      ...rest
+    },
+    ref,
+  ) => {
+    const tooltipRef = useRef(null)
+    const togglerRef = useRef(null)
+    const forkedRef = useForkedRef(ref, tooltipRef)
 
-  const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
+    const { popper, initPopper, destroyPopper } = usePopper()
+    const [_visible, setVisible] = useState(visible)
 
-  const popperConfig = {
-    modifiers: [
-      {
-        name: 'arrow',
-        options: {
-          element: '.tooltip-arrow',
+    const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
+
+    const popperConfig = {
+      modifiers: [
+        {
+          name: 'arrow',
+          options: {
+            element: '.tooltip-arrow',
+          },
         },
-      },
-      {
-        name: 'flip',
-        options: {
-          fallbackPlacements: fallbackPlacements,
+        {
+          name: 'flip',
+          options: {
+            fallbackPlacements: fallbackPlacements,
+          },
         },
-      },
-      {
-        name: 'offset',
-        options: {
-          offset: offset,
+        {
+          name: 'offset',
+          options: {
+            offset: offset,
+          },
         },
-      },
-    ],
-    placement: getRTLPlacement(placement, togglerRef.current),
-  }
+      ],
+      placement: getRTLPlacement(placement, togglerRef.current),
+    }
 
-  useEffect(() => {
-    setVisible(visible)
-  }, [visible])
+    useEffect(() => {
+      setVisible(visible)
+    }, [visible])
 
-  useEffect(() => {
-    if (_visible && togglerRef.current && tooltipRef.current) {
-      initPopper(togglerRef.current, tooltipRef.current, popperConfig)
-    }
+    useEffect(() => {
+      if (_visible && togglerRef.current && tooltipRef.current) {
+        initPopper(togglerRef.current, tooltipRef.current, popperConfig)
+      }
 
-    return () => {
-      destroyPopper()
-    }
-  }, [_visible])
+      return () => {
+        destroyPopper()
+      }
+    }, [_visible])
 
-  const toggleVisible = (visible: boolean) => {
-    if (visible) {
-      setTimeout(() => setVisible(true), _delay.show)
-      return
-    }
+    const toggleVisible = (visible: boolean) => {
+      if (visible) {
+        setTimeout(() => setVisible(true), _delay.show)
+        return
+      }
 
-    setTimeout(() => setVisible(false), _delay.hide)
-  }
+      setTimeout(() => setVisible(false), _delay.hide)
+    }
 
-  return (
-    <>
-      {React.cloneElement(children as React.ReactElement<any>, {
-        ref: togglerRef,
-        ...((trigger === 'click' || trigger.includes('click')) && {
-          onClick: () => toggleVisible(!_visible),
-        }),
-        ...((trigger === 'focus' || trigger.includes('focus')) && {
-          onFocus: () => toggleVisible(true),
-          onBlur: () => toggleVisible(false),
-        }),
-        ...((trigger === 'hover' || trigger.includes('hover')) && {
-          onMouseEnter: () => toggleVisible(true),
-          onMouseLeave: () => toggleVisible(false),
-        }),
-      })}
-      {typeof window !== 'undefined' &&
-        createPortal(
-          <Transition
-            in={_visible}
-            mountOnEnter
-            onEnter={onShow}
-            onExit={onHide}
-            timeout={{
-              enter: 0,
-              exit: tooltipRef.current ? getTransitionDurationFromElement(tooltipRef.current) + 50 : 200,
-            }}
-            unmountOnExit
-          >
-            {(state) => (
-              <div
-                className={classNames(
-                  'tooltip',
-                  'bs-tooltip-auto',
-                  {
-                    fade: animation,
-                    show: state === 'entered',
-                  },
-                  className,
-                )}
-                ref={tooltipRef}
-                role="tooltip"
-                {...rest}
-              >
-                <div className="tooltip-arrow"></div>
-                <div className="tooltip-inner">{content}</div>
-              </div>
-            )}
-          </Transition>,
-          document.body,
-        )}
-    </>
-  )
-}
+    return (
+      <>
+        {React.cloneElement(children as React.ReactElement<any>, {
+          ref: togglerRef,
+          ...((trigger === 'click' || trigger.includes('click')) && {
+            onClick: () => toggleVisible(!_visible),
+          }),
+          ...((trigger === 'focus' || trigger.includes('focus')) && {
+            onFocus: () => toggleVisible(true),
+            onBlur: () => toggleVisible(false),
+          }),
+          ...((trigger === 'hover' || trigger.includes('hover')) && {
+            onMouseEnter: () => toggleVisible(true),
+            onMouseLeave: () => toggleVisible(false),
+          }),
+        })}
+        {typeof window !== 'undefined' &&
+          createPortal(
+            <Transition
+              in={_visible}
+              mountOnEnter
+              nodeRef={tooltipRef}
+              onEnter={onShow}
+              onExit={onHide}
+              timeout={{
+                enter: 0,
+                exit: tooltipRef.current
+                  ? getTransitionDurationFromElement(tooltipRef.current) + 50
+                  : 200,
+              }}
+              unmountOnExit
+            >
+              {(state) => (
+                <div
+                  className={classNames(
+                    'tooltip',
+                    'bs-tooltip-auto',
+                    {
+                      fade: animation,
+                      show: state === 'entered',
+                    },
+                    className,
+                  )}
+                  ref={forkedRef}
+                  role="tooltip"
+                  {...rest}
+                >
+                  <div className="tooltip-arrow"></div>
+                  <div className="tooltip-inner">{content}</div>
+                </div>
+              )}
+            </Transition>,
+            document.body,
+          )}
+      </>
+    )
+  },
+)
 
 CTooltip.propTypes = {
   animation: PropTypes.bool,

From e7fc7fea41a8b6108ed1e349f634b47201414eb3 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 22 Sep 2023 17:58:02 +0200
Subject: [PATCH 38/49] refactor(CPopover): move from `FC` to `forwardRef`

---
 .../src/components/popover/CPopover.tsx       | 243 +++++++++---------
 1 file changed, 126 insertions(+), 117 deletions(-)

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index 8dbd48bc..d2e7cfa0 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -1,10 +1,10 @@
-import React, { FC, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
+import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
 import { createPortal } from 'react-dom'
 import classNames from 'classnames'
 import PropTypes from 'prop-types'
 import { Transition } from 'react-transition-group'
 
-import { usePopper } from '../../hooks'
+import { useForkedRef, usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
 import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
@@ -68,132 +68,141 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
   visible?: boolean
 }
 
-export const CPopover: FC<CPopoverProps> = ({
-  children,
-  animation = true,
-  className,
-  content,
-  delay = 0,
-  fallbackPlacements = ['top', 'right', 'bottom', 'left'],
-  offset = [0, 8],
-  onHide,
-  onShow,
-  placement = 'top',
-  title,
-  trigger = 'click',
-  visible,
-  ...rest
-}) => {
-  const popoverRef = useRef(null)
-  const togglerRef = useRef(null)
-  const { initPopper, destroyPopper } = usePopper()
-  const [_visible, setVisible] = useState(visible)
+export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
+  (
+    {
+      children,
+      animation = true,
+      className,
+      content,
+      delay = 0,
+      fallbackPlacements = ['top', 'right', 'bottom', 'left'],
+      offset = [0, 8],
+      onHide,
+      onShow,
+      placement = 'top',
+      title,
+      trigger = 'click',
+      visible,
+      ...rest
+    },
+    ref,
+  ) => {
+    const popoverRef = useRef(null)
+    const togglerRef = useRef(null)
+    const forkedRef = useForkedRef(ref, popoverRef)
 
-  const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
+    const { initPopper, destroyPopper } = usePopper()
+    const [_visible, setVisible] = useState(visible)
 
-  const popperConfig = {
-    modifiers: [
-      {
-        name: 'arrow',
-        options: {
-          element: '.popover-arrow',
+    const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
+
+    const popperConfig = {
+      modifiers: [
+        {
+          name: 'arrow',
+          options: {
+            element: '.popover-arrow',
+          },
         },
-      },
-      {
-        name: 'flip',
-        options: {
-          fallbackPlacements: fallbackPlacements,
+        {
+          name: 'flip',
+          options: {
+            fallbackPlacements: fallbackPlacements,
+          },
         },
-      },
-      {
-        name: 'offset',
-        options: {
-          offset: offset,
+        {
+          name: 'offset',
+          options: {
+            offset: offset,
+          },
         },
-      },
-    ],
-    placement: getRTLPlacement(placement, togglerRef.current),
-  }
+      ],
+      placement: getRTLPlacement(placement, togglerRef.current),
+    }
 
-  useEffect(() => {
-    setVisible(visible)
-  }, [visible])
+    useEffect(() => {
+      setVisible(visible)
+    }, [visible])
 
-  useEffect(() => {
-    if (_visible && togglerRef.current && popoverRef.current) {
-      initPopper(togglerRef.current, popoverRef.current, popperConfig)
-    }
+    useEffect(() => {
+      if (_visible && togglerRef.current && popoverRef.current) {
+        initPopper(togglerRef.current, popoverRef.current, popperConfig)
+      }
 
-    return () => {
-      destroyPopper()
-    }
-  }, [_visible])
+      return () => {
+        destroyPopper()
+      }
+    }, [_visible])
 
-  const toggleVisible = (visible: boolean) => {
-    if (visible) {
-      setTimeout(() => setVisible(true), _delay.show)
-      return
-    }
+    const toggleVisible = (visible: boolean) => {
+      if (visible) {
+        setTimeout(() => setVisible(true), _delay.show)
+        return
+      }
 
-    setTimeout(() => setVisible(false), _delay.hide)
-  }
+      setTimeout(() => setVisible(false), _delay.hide)
+    }
 
-  return (
-    <>
-      {React.cloneElement(children as React.ReactElement<any>, {
-        ref: togglerRef,
-        ...((trigger === 'click' || trigger.includes('click')) && {
-          onClick: () => toggleVisible(!_visible),
-        }),
-        ...((trigger === 'focus' || trigger.includes('focus')) && {
-          onFocus: () => toggleVisible(true),
-          onBlur: () => toggleVisible(false),
-        }),
-        ...((trigger === 'hover' || trigger.includes('hover')) && {
-          onMouseEnter: () => toggleVisible(true),
-          onMouseLeave: () => toggleVisible(false),
-        }),
-      })}
-      {typeof window !== 'undefined' &&
-        createPortal(
-          <Transition
-            in={_visible}
-            mountOnEnter
-            nodeRef={popoverRef}
-            onEnter={onShow}
-            onExit={onHide}
-            timeout={{
-              enter: 0,
-              exit: popoverRef.current ? getTransitionDurationFromElement(popoverRef.current) + 50 : 200,
-            }}
-            unmountOnExit
-          >
-            {(state) => (
-              <div
-                className={classNames(
-                  'popover',
-                  'bs-popover-auto',
-                  {
-                    fade: animation,
-                    show: state === 'entered',
-                  },
-                  className,
-                )}
-                ref={popoverRef}
-                role="tooltip"
-                {...rest}
-              >
-                <div className="popover-arrow"></div>
-                <div className="popover-header">{title}</div>
-                <div className="popover-body">{content}</div>
-              </div>
-            )}
-          </Transition>,
-          document.body,
-        )}
-    </>
-  )
-}
+    return (
+      <>
+        {React.cloneElement(children as React.ReactElement<any>, {
+          ref: togglerRef,
+          ...((trigger === 'click' || trigger.includes('click')) && {
+            onClick: () => toggleVisible(!_visible),
+          }),
+          ...((trigger === 'focus' || trigger.includes('focus')) && {
+            onFocus: () => toggleVisible(true),
+            onBlur: () => toggleVisible(false),
+          }),
+          ...((trigger === 'hover' || trigger.includes('hover')) && {
+            onMouseEnter: () => toggleVisible(true),
+            onMouseLeave: () => toggleVisible(false),
+          }),
+        })}
+        {typeof window !== 'undefined' &&
+          createPortal(
+            <Transition
+              in={_visible}
+              mountOnEnter
+              nodeRef={popoverRef}
+              onEnter={onShow}
+              onExit={onHide}
+              timeout={{
+                enter: 0,
+                exit: popoverRef.current
+                  ? getTransitionDurationFromElement(popoverRef.current) + 50
+                  : 200,
+              }}
+              unmountOnExit
+            >
+              {(state) => (
+                <div
+                  className={classNames(
+                    'popover',
+                    'bs-popover-auto',
+                    {
+                      fade: animation,
+                      show: state === 'entered',
+                    },
+                    className,
+                  )}
+                  ref={forkedRef}
+                  role="tooltip"
+                  {...rest}
+                >
+                  <div className="popover-arrow"></div>
+                  <div className="popover-header">{title}</div>
+                  <div className="popover-body">{content}</div>
+                </div>
+              )}
+            </Transition>,
+            document.body,
+          )}
+      </>
+    )
+  },
+)
 
 CPopover.propTypes = {
   animation: PropTypes.bool,

From e3d995cea25bf32dd9cc757541b080734f99ec4e Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 22 Sep 2023 18:03:00 +0200
Subject: [PATCH 39/49] chore: clean-up

---
 packages/coreui-react/src/components/tooltip/CTooltip.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index 68b805fc..f056e345 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -94,7 +94,7 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
     const togglerRef = useRef(null)
     const forkedRef = useForkedRef(ref, tooltipRef)
 
-    const { popper, initPopper, destroyPopper } = usePopper()
+    const { initPopper, destroyPopper } = usePopper()
     const [_visible, setVisible] = useState(visible)
 
     const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay

From 15bf9ca45d8c2606ae29f638649eebbccd6e649a Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Fri, 22 Sep 2023 18:08:19 +0200
Subject: [PATCH 40/49] release: v4.10.1

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index c22a82e8..115ba202 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index c5956f0e..0e9e6c4c 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.10.0",
+  "version": "4.10.1",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index d353d8e0..f5f31069 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index dfd32a74..5f5675e2 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.10.0",
+  "version": "4.10.1",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index e8ac08e0..929b9f3b 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.10.0",
+  "version": "4.10.1",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From dd3106af3250b47fc604edeeb898677ecab7c380 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Tue, 24 Oct 2023 16:45:18 +0200
Subject: [PATCH 41/49] feat(CConditionalPortal, CDropdown, CPopover,
 CTooltip): allow to append component to the specific element

---
 .../conditional-portal/CConditionalPortal.tsx | 37 ++++++--
 .../src/components/dropdown/CDropdown.tsx     |  8 ++
 .../src/components/dropdown/CDropdownMenu.tsx |  4 +-
 .../src/components/popover/CPopover.tsx       | 87 +++++++++--------
 .../src/components/tooltip/CTooltip.tsx       | 93 +++++++++----------
 .../content/api/CConditionalPortal.api.mdx    |  3 +-
 packages/docs/content/api/CDropdown.api.mdx   |  1 +
 packages/docs/content/api/CModal.api.mdx      |  1 +
 packages/docs/content/api/CPopover.api.mdx    |  1 +
 packages/docs/content/api/CTooltip.api.mdx    |  1 +
 10 files changed, 140 insertions(+), 96 deletions(-)

diff --git a/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx b/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx
index aee4bc85..bbbe00cd 100644
--- a/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx
+++ b/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx
@@ -1,21 +1,45 @@
-import React, { FC, ReactNode } from 'react'
+import React, { FC, ReactNode, useEffect, useState } from 'react'
 import { createPortal } from 'react-dom'
 import PropTypes from 'prop-types'
 
+const getContainer = (container?: Element | (() => Element | null) | null) => {
+  if (container) {
+    return typeof container === 'function' ? container() : container
+  }
+
+  return document.body
+}
+
 export interface CConditionalPortalProps {
   /**
    * @ignore
    */
   children: ReactNode
+  /**
+   * An HTML element or function that returns a single element, with `document.body` as the default.
+   * 
+   * @since v4.11.0
+   */
+  container?: Element | (() => Element | null) | null
   /**
    * Render some children into a different part of the DOM
    */
-  portal: boolean
+  portal: boolean | any
 }
 
-export const CConditionalPortal: FC<CConditionalPortalProps> = ({ children, portal }) => {
-  return typeof window !== 'undefined' && portal ? (
-    createPortal(children, document.body)
+export const CConditionalPortal: FC<CConditionalPortalProps> = ({
+  children,
+  container,
+  portal,
+}) => {
+  const [_container, setContainer] = useState<ReturnType<typeof getContainer>>(null)
+
+  useEffect(() => {
+    portal && setContainer(getContainer(container) || document.body)
+  }, [container, portal])
+
+  return typeof window !== 'undefined' && portal && _container ? (
+    createPortal(children, _container)
   ) : (
     <>{children}</>
   )
@@ -23,7 +47,8 @@ export const CConditionalPortal: FC<CConditionalPortalProps> = ({ children, port
 
 CConditionalPortal.propTypes = {
   children: PropTypes.node,
-  portal: PropTypes.bool.isRequired,
+  container: PropTypes.any, // HTMLElement
+  portal: PropTypes.bool,
 }
 
 CConditionalPortal.displayName = 'CConditionalPortal'
diff --git a/packages/coreui-react/src/components/dropdown/CDropdown.tsx b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
index 59dfbdb9..bc7ab4e3 100644
--- a/packages/coreui-react/src/components/dropdown/CDropdown.tsx
+++ b/packages/coreui-react/src/components/dropdown/CDropdown.tsx
@@ -51,6 +51,12 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
    * Component used for the root node. Either a string to use a HTML element or a component.
    */
   component?: string | ElementType
+  /**
+   * Appends the react dropdown menu to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`.
+   *
+   * @since v4.11.0
+   */
+  container?: Element | (() => Element | null) | null
   /**
    * Sets a darker color scheme to match a dark navbar.
    */
@@ -147,6 +153,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
       alignment,
       autoClose = true,
       className,
+      container,
       dark,
       direction,
       offset = [0, 2],
@@ -179,6 +186,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
 
     const contextValues = {
       alignment,
+      container,
       dark,
       dropdownToggleRef,
       dropdownMenuRef,
diff --git a/packages/coreui-react/src/components/dropdown/CDropdownMenu.tsx b/packages/coreui-react/src/components/dropdown/CDropdownMenu.tsx
index ac9cfb61..efb2dbcd 100644
--- a/packages/coreui-react/src/components/dropdown/CDropdownMenu.tsx
+++ b/packages/coreui-react/src/components/dropdown/CDropdownMenu.tsx
@@ -35,13 +35,13 @@ const alignmentClassNames = (alignment: Alignments) => {
 
 export const CDropdownMenu = forwardRef<HTMLDivElement | HTMLUListElement, CDropdownMenuProps>(
   ({ children, className, component: Component = 'ul', ...rest }, ref) => {
-    const { alignment, dark, dropdownMenuRef, popper, portal, visible } =
+    const { alignment, container, dark, dropdownMenuRef, popper, portal, visible } =
       useContext(CDropdownContext)
 
     const forkedRef = useForkedRef(ref, dropdownMenuRef)
 
     return (
-      <CConditionalPortal portal={portal ?? false}>
+      <CConditionalPortal container={container} portal={portal ?? false}>
         <Component
           className={classNames(
             'dropdown-menu',
diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index d2e7cfa0..0c620304 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -1,9 +1,10 @@
 import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
-import { createPortal } from 'react-dom'
+// import { createPortal } from 'react-dom'
 import classNames from 'classnames'
 import PropTypes from 'prop-types'
 import { Transition } from 'react-transition-group'
 
+import { CConditionalPortal } from '../conditional-portal'
 import { useForkedRef, usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
@@ -20,6 +21,12 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
    * A string of all className you want applied to the component.
    */
   className?: string
+  /**
+   * Appends the react popover to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`.
+   *
+   * @since v4.11.0
+   */
+  container?: Element | (() => Element | null) | null
   /**
    * Content node for your component.
    */
@@ -74,6 +81,7 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
       children,
       animation = true,
       className,
+      container,
       content,
       delay = 0,
       fallbackPlacements = ['top', 'right', 'bottom', 'left'],
@@ -160,45 +168,43 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
             onMouseLeave: () => toggleVisible(false),
           }),
         })}
-        {typeof window !== 'undefined' &&
-          createPortal(
-            <Transition
-              in={_visible}
-              mountOnEnter
-              nodeRef={popoverRef}
-              onEnter={onShow}
-              onExit={onHide}
-              timeout={{
-                enter: 0,
-                exit: popoverRef.current
-                  ? getTransitionDurationFromElement(popoverRef.current) + 50
-                  : 200,
-              }}
-              unmountOnExit
-            >
-              {(state) => (
-                <div
-                  className={classNames(
-                    'popover',
-                    'bs-popover-auto',
-                    {
-                      fade: animation,
-                      show: state === 'entered',
-                    },
-                    className,
-                  )}
-                  ref={forkedRef}
-                  role="tooltip"
-                  {...rest}
-                >
-                  <div className="popover-arrow"></div>
-                  <div className="popover-header">{title}</div>
-                  <div className="popover-body">{content}</div>
-                </div>
-              )}
-            </Transition>,
-            document.body,
-          )}
+        <CConditionalPortal container={container} portal={true}>
+          <Transition
+            in={_visible}
+            mountOnEnter
+            nodeRef={popoverRef}
+            onEnter={onShow}
+            onExit={onHide}
+            timeout={{
+              enter: 0,
+              exit: popoverRef.current
+                ? getTransitionDurationFromElement(popoverRef.current) + 50
+                : 200,
+            }}
+            unmountOnExit
+          >
+            {(state) => (
+              <div
+                className={classNames(
+                  'popover',
+                  'bs-popover-auto',
+                  {
+                    fade: animation,
+                    show: state === 'entered',
+                  },
+                  className,
+                )}
+                ref={forkedRef}
+                role="tooltip"
+                {...rest}
+              >
+                <div className="popover-arrow"></div>
+                <div className="popover-header">{title}</div>
+                <div className="popover-body">{content}</div>
+              </div>
+            )}
+          </Transition>
+        </CConditionalPortal>
       </>
     )
   },
@@ -208,6 +214,7 @@ CPopover.propTypes = {
   animation: PropTypes.bool,
   children: PropTypes.node,
   className: PropTypes.string,
+  container: PropTypes.any,
   content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
   delay: PropTypes.oneOfType([
     PropTypes.number,
diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index f056e345..fd29fccc 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -1,16 +1,9 @@
-import React, {
-  forwardRef,
-  HTMLAttributes,
-  ReactNode,
-  useRef,
-  useEffect,
-  useState,
-} from 'react'
-import { createPortal } from 'react-dom'
+import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
 import classNames from 'classnames'
 import PropTypes from 'prop-types'
 import { Transition } from 'react-transition-group'
 
+import { CConditionalPortal } from '../conditional-portal'
 import { useForkedRef, usePopper } from '../../hooks'
 import { fallbackPlacementsPropType, triggerPropType } from '../../props'
 import type { Placements, Triggers } from '../../types'
@@ -27,6 +20,12 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
    * A string of all className you want applied to the component.
    */
   className?: string
+  /**
+   * Appends the react tooltip to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`.
+   *
+   * @since v4.11.0
+   */
+  container?: Element | (() => Element | null) | null
   /**
    * Content node for your component.
    */
@@ -77,6 +76,7 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
       children,
       animation = true,
       className,
+      container,
       content,
       delay = 0,
       fallbackPlacements = ['top', 'right', 'bottom', 'left'],
@@ -162,44 +162,42 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
             onMouseLeave: () => toggleVisible(false),
           }),
         })}
-        {typeof window !== 'undefined' &&
-          createPortal(
-            <Transition
-              in={_visible}
-              mountOnEnter
-              nodeRef={tooltipRef}
-              onEnter={onShow}
-              onExit={onHide}
-              timeout={{
-                enter: 0,
-                exit: tooltipRef.current
-                  ? getTransitionDurationFromElement(tooltipRef.current) + 50
-                  : 200,
-              }}
-              unmountOnExit
-            >
-              {(state) => (
-                <div
-                  className={classNames(
-                    'tooltip',
-                    'bs-tooltip-auto',
-                    {
-                      fade: animation,
-                      show: state === 'entered',
-                    },
-                    className,
-                  )}
-                  ref={forkedRef}
-                  role="tooltip"
-                  {...rest}
-                >
-                  <div className="tooltip-arrow"></div>
-                  <div className="tooltip-inner">{content}</div>
-                </div>
-              )}
-            </Transition>,
-            document.body,
-          )}
+        <CConditionalPortal container={container} portal={true}>
+          <Transition
+            in={_visible}
+            mountOnEnter
+            nodeRef={tooltipRef}
+            onEnter={onShow}
+            onExit={onHide}
+            timeout={{
+              enter: 0,
+              exit: tooltipRef.current
+                ? getTransitionDurationFromElement(tooltipRef.current) + 50
+                : 200,
+            }}
+            unmountOnExit
+          >
+            {(state) => (
+              <div
+                className={classNames(
+                  'tooltip',
+                  'bs-tooltip-auto',
+                  {
+                    fade: animation,
+                    show: state === 'entered',
+                  },
+                  className,
+                )}
+                ref={forkedRef}
+                role="tooltip"
+                {...rest}
+              >
+                <div className="tooltip-arrow"></div>
+                <div className="tooltip-inner">{content}</div>
+              </div>
+            )}
+          </Transition>
+        </CConditionalPortal>
       </>
     )
   },
@@ -208,6 +206,7 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
 CTooltip.propTypes = {
   animation: PropTypes.bool,
   children: PropTypes.node,
+  container: PropTypes.any,
   content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
   delay: PropTypes.oneOfType([
     PropTypes.number,
diff --git a/packages/docs/content/api/CConditionalPortal.api.mdx b/packages/docs/content/api/CConditionalPortal.api.mdx
index cb833359..4a269bf2 100644
--- a/packages/docs/content/api/CConditionalPortal.api.mdx
+++ b/packages/docs/content/api/CConditionalPortal.api.mdx
@@ -7,4 +7,5 @@ import CConditionalPortal from '@coreui/react/src/components/conditional-portal/
 
 | Property | Description | Type | Default |
 | --- | --- | --- | --- |
-| **portal** | Render some children into a different part of the DOM | `boolean` | - |
+| **container** **_v4.11.0+_** | An HTML element or function that returns a single element, with `document.body` as the default. | `Element` \| `(() => Element)` | - |
+| **portal** | Render some children into a different part of the DOM | `any` | - |
diff --git a/packages/docs/content/api/CDropdown.api.mdx b/packages/docs/content/api/CDropdown.api.mdx
index d1ebd44f..7e4c3d32 100644
--- a/packages/docs/content/api/CDropdown.api.mdx
+++ b/packages/docs/content/api/CDropdown.api.mdx
@@ -11,6 +11,7 @@ import CDropdown from '@coreui/react/src/components/dropdown/CDropdown'
 | **autoClose** | Configure the auto close behavior of the dropdown:<br/>- `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.<br/>- `false` - the dropdown will be closed by clicking the toggle button and manually calling hide or toggle method. (Also will not be closed by pressing esc key)<br/>- `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.<br/>- `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu. | `boolean` \| `'inside'` \| `'outside'` | true |
 | **className** | A string of all className you want applied to the base component. | `string` | - |
 | **component** | Component used for the root node. Either a string to use a HTML element or a component. | `string` \| `ComponentClass<any, any>` \| `FunctionComponent<any>` | div |
+| **container** **_v4.11.0+_** | Appends the react dropdown menu to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`. | `Element` \| `(() => Element)` | - |
 | **dark** | Sets a darker color scheme to match a dark navbar. | `boolean` | - |
 | **direction** | Sets a specified  direction and location of the dropdown menu. | `'center'` \| `'dropup'` \| `'dropup-center'` \| `'dropend'` \| `'dropstart'` | - |
 | **offset** | Offset of the dropdown menu relative to its target. | `[number, number]` | [0, 2] |
diff --git a/packages/docs/content/api/CModal.api.mdx b/packages/docs/content/api/CModal.api.mdx
index 7134c041..635c688e 100644
--- a/packages/docs/content/api/CModal.api.mdx
+++ b/packages/docs/content/api/CModal.api.mdx
@@ -10,6 +10,7 @@ import CModal from '@coreui/react/src/components/modal/CModal'
 | **alignment** | Align the modal in the center or top of the screen. | `'top'` \| `'center'` | - |
 | **backdrop** | Apply a backdrop on body while modal is open. | `boolean` \| `'static'` | true |
 | **className** | A string of all className you want applied to the base component. | `string` | - |
+| **focus** **_v4.10.0+_** | Puts the focus on the modal when shown. | `boolean` | true |
 | **fullscreen** | Set modal to covers the entire user viewport. | `boolean` \| `'sm'` \| `'md'` \| `'lg'` \| `'xl'` \| `'xxl'` | - |
 | **keyboard** | Closes the modal when escape key is pressed. | `boolean` | true |
 | **onClose** | Callback fired when the component requests to be closed. | `() => void` | - |
diff --git a/packages/docs/content/api/CPopover.api.mdx b/packages/docs/content/api/CPopover.api.mdx
index 3cad4f11..40ad6fb7 100644
--- a/packages/docs/content/api/CPopover.api.mdx
+++ b/packages/docs/content/api/CPopover.api.mdx
@@ -9,6 +9,7 @@ import CPopover from '@coreui/react/src/components/popover/CPopover'
 | --- | --- | --- | --- |
 | **animation** **_4.9.0+_** | Apply a CSS fade transition to the popover. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
+| **container** **_v4.11.0+_** | Appends the react popover to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`. | `Element` \| `(() => Element)` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
 | **delay** **_4.9.0+_** | The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
 | **fallbackPlacements** **_4.9.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |
diff --git a/packages/docs/content/api/CTooltip.api.mdx b/packages/docs/content/api/CTooltip.api.mdx
index 9aa3050d..047a8ff8 100644
--- a/packages/docs/content/api/CTooltip.api.mdx
+++ b/packages/docs/content/api/CTooltip.api.mdx
@@ -9,6 +9,7 @@ import CTooltip from '@coreui/react/src/components/tooltip/CTooltip'
 | --- | --- | --- | --- |
 | **animation** **_4.9.0+_** | Apply a CSS fade transition to the tooltip. | `boolean` | true |
 | **className** | A string of all className you want applied to the component. | `string` | - |
+| **container** **_v4.11.0+_** | Appends the react tooltip to a specific element. You can pass an HTML element or function that returns a single element. By default `document.body`. | `Element` \| `(() => Element)` | - |
 | **content** | Content node for your component. | `ReactNode` | - |
 | **delay** **_4.9.0+_** | The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`. | `number` \| `{ show: number; hide: number; }` | 0 |
 | **fallbackPlacements** **_4.9.0+_** | Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference. | `Placements` \| `Placements[]` | ['top', 'right', 'bottom', 'left'] |

From da34832f93b6a5e8ae9c014fdf0965859ba21ac7 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 2 Nov 2023 22:28:19 +0100
Subject: [PATCH 42/49] release: v4.11.0

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 115ba202..929b98ed 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.1.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index 0e9e6c4c..494b8b6f 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.10.1",
+  "version": "4.11.0",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index f5f31069..b970d6a7 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.10.1.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.0.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index 5f5675e2..2f37d62b 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.10.1",
+  "version": "4.11.0",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index 929b9f3b..b84aea76 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.10.1",
+  "version": "4.11.0",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",

From 011cbd83fb5cd4dba0e0c0f9dea1143a915c1bde Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 21 Dec 2023 15:23:32 +0100
Subject: [PATCH 43/49] refactor(CModal): improve the click outside listener

---
 packages/coreui-react/src/components/modal/CModal.tsx | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/packages/coreui-react/src/components/modal/CModal.tsx b/packages/coreui-react/src/components/modal/CModal.tsx
index 2c8ed10e..053e8162 100644
--- a/packages/coreui-react/src/components/modal/CModal.tsx
+++ b/packages/coreui-react/src/components/modal/CModal.tsx
@@ -200,10 +200,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
     }, [_visible])
 
     const handleClickOutside = (event: Event) => {
-      if (
-        modalContentRef.current &&
-        !modalContentRef.current.contains(event.target as HTMLElement)
-      ) {
+      if (modalRef.current && modalRef.current == event.target) {
         handleDismiss()
       }
     }

From 21fe7d03aa4863dc3390e4978c83297665318568 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 21 Dec 2023 15:47:32 +0100
Subject: [PATCH 44/49] refactor(CTooltip): improve accessibility

---
 packages/coreui-react/src/components/tooltip/CTooltip.tsx | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index fd29fccc..23bcf8b5 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -90,9 +90,10 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
     },
     ref,
   ) => {
-    const tooltipRef = useRef(null)
+    const tooltipRef = useRef<HTMLDivElement>(null)
     const togglerRef = useRef(null)
     const forkedRef = useForkedRef(ref, tooltipRef)
+    const uID = useRef(`tooltip${Math.floor(Math.random() * 1_000_000)}`)
 
     const { initPopper, destroyPopper } = usePopper()
     const [_visible, setVisible] = useState(visible)
@@ -149,6 +150,9 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
     return (
       <>
         {React.cloneElement(children as React.ReactElement<any>, {
+          ...(_visible && {
+            'aria-describedby': uID.current,
+          }),
           ref: togglerRef,
           ...((trigger === 'click' || trigger.includes('click')) && {
             onClick: () => toggleVisible(!_visible),
@@ -188,6 +192,7 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
                   },
                   className,
                 )}
+                id={uID.current}
                 ref={forkedRef}
                 role="tooltip"
                 {...rest}

From 14bb76af3ad99721f4ef0acb607d37645fac594f Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 21 Dec 2023 15:54:15 +0100
Subject: [PATCH 45/49] refactor(CPopover): improve accessibility

---
 packages/coreui-react/src/components/popover/CPopover.tsx | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index 0c620304..25e47399 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -99,7 +99,8 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
     const popoverRef = useRef(null)
     const togglerRef = useRef(null)
     const forkedRef = useForkedRef(ref, popoverRef)
-
+    const uID = useRef(`popover${Math.floor(Math.random() * 1_000_000)}`)
+    
     const { initPopper, destroyPopper } = usePopper()
     const [_visible, setVisible] = useState(visible)
 
@@ -155,6 +156,9 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
     return (
       <>
         {React.cloneElement(children as React.ReactElement<any>, {
+          ...(_visible && {
+            'aria-describedby': uID.current,
+          }),
           ref: togglerRef,
           ...((trigger === 'click' || trigger.includes('click')) && {
             onClick: () => toggleVisible(!_visible),
@@ -194,6 +198,7 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
                   },
                   className,
                 )}
+                id={uID.current}
                 ref={forkedRef}
                 role="tooltip"
                 {...rest}

From 85f7a659787250559302aec715aade8893ef4ff7 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Thu, 21 Dec 2023 16:37:48 +0100
Subject: [PATCH 46/49] refactor(CPopover): improve accessibility

---
 packages/coreui-react/src/components/popover/CPopover.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index 25e47399..ed694678 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -100,7 +100,7 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
     const togglerRef = useRef(null)
     const forkedRef = useForkedRef(ref, popoverRef)
     const uID = useRef(`popover${Math.floor(Math.random() * 1_000_000)}`)
-    
+
     const { initPopper, destroyPopper } = usePopper()
     const [_visible, setVisible] = useState(visible)
 

From 8d379a131954561988c8a54fbc0f7376cf075034 Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Mon, 25 Dec 2023 14:47:53 +0100
Subject: [PATCH 47/49] fix(CPopover, CTooltip): prevent body scrolling when
 the component is added and removed from the DOM

---
 .../src/components/popover/CPopover.tsx       | 31 ++++++++++++-------
 .../src/components/tooltip/CTooltip.tsx       | 29 ++++++++++-------
 2 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index ed694678..c4609b85 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -96,7 +96,7 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
     },
     ref,
   ) => {
-    const popoverRef = useRef(null)
+    const popoverRef = useRef<HTMLDivElement>(null)
     const togglerRef = useRef(null)
     const forkedRef = useForkedRef(ref, popoverRef)
     const uID = useRef(`popover${Math.floor(Math.random() * 1_000_000)}`)
@@ -134,16 +134,6 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
       setVisible(visible)
     }, [visible])
 
-    useEffect(() => {
-      if (_visible && togglerRef.current && popoverRef.current) {
-        initPopper(togglerRef.current, popoverRef.current, popperConfig)
-      }
-
-      return () => {
-        destroyPopper()
-      }
-    }, [_visible])
-
     const toggleVisible = (visible: boolean) => {
       if (visible) {
         setTimeout(() => setVisible(true), _delay.show)
@@ -177,8 +167,22 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
             in={_visible}
             mountOnEnter
             nodeRef={popoverRef}
-            onEnter={onShow}
+            onEnter={() => {
+              if (togglerRef.current && popoverRef.current) {
+                initPopper(togglerRef.current, popoverRef.current, popperConfig)
+              }
+
+              onShow
+            }}
+            onEntering={() => {
+              if (togglerRef.current && popoverRef.current) {
+                popoverRef.current.style.display = 'initial'
+              }
+            }}
             onExit={onHide}
+            onExited={() => {
+              destroyPopper()
+            }}
             timeout={{
               enter: 0,
               exit: popoverRef.current
@@ -201,6 +205,9 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
                 id={uID.current}
                 ref={forkedRef}
                 role="tooltip"
+                style={{
+                  display: 'none',
+                }}
                 {...rest}
               >
                 <div className="popover-arrow"></div>
diff --git a/packages/coreui-react/src/components/tooltip/CTooltip.tsx b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
index 23bcf8b5..07d88af6 100644
--- a/packages/coreui-react/src/components/tooltip/CTooltip.tsx
+++ b/packages/coreui-react/src/components/tooltip/CTooltip.tsx
@@ -128,16 +128,6 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
       setVisible(visible)
     }, [visible])
 
-    useEffect(() => {
-      if (_visible && togglerRef.current && tooltipRef.current) {
-        initPopper(togglerRef.current, tooltipRef.current, popperConfig)
-      }
-
-      return () => {
-        destroyPopper()
-      }
-    }, [_visible])
-
     const toggleVisible = (visible: boolean) => {
       if (visible) {
         setTimeout(() => setVisible(true), _delay.show)
@@ -171,8 +161,22 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
             in={_visible}
             mountOnEnter
             nodeRef={tooltipRef}
-            onEnter={onShow}
+            onEnter={() => {
+              if (togglerRef.current && tooltipRef.current) {
+                initPopper(togglerRef.current, tooltipRef.current, popperConfig)
+              }
+
+              onShow
+            }}
+            onEntering={() => {
+              if (togglerRef.current && tooltipRef.current) {
+                tooltipRef.current.style.display = 'initial'
+              }
+            }}
             onExit={onHide}
+            onExited={() => {
+              destroyPopper()
+            }}
             timeout={{
               enter: 0,
               exit: tooltipRef.current
@@ -195,6 +199,9 @@ export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
                 id={uID.current}
                 ref={forkedRef}
                 role="tooltip"
+                style={{
+                  display: 'none',
+                }}
                 {...rest}
               >
                 <div className="tooltip-arrow"></div>

From 8f98f151e6182f2253db7f0b88cfcefc6e97d75c Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Mon, 25 Dec 2023 15:54:46 +0100
Subject: [PATCH 48/49] chore: clean-up

---
 packages/coreui-react/src/components/popover/CPopover.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/coreui-react/src/components/popover/CPopover.tsx b/packages/coreui-react/src/components/popover/CPopover.tsx
index c4609b85..36b93afe 100644
--- a/packages/coreui-react/src/components/popover/CPopover.tsx
+++ b/packages/coreui-react/src/components/popover/CPopover.tsx
@@ -1,5 +1,4 @@
 import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
-// import { createPortal } from 'react-dom'
 import classNames from 'classnames'
 import PropTypes from 'prop-types'
 import { Transition } from 'react-transition-group'

From b70832de30e131a7b016006519a21d66c384c38c Mon Sep 17 00:00:00 2001
From: mrholek <lukasz@holeczek.pl>
Date: Mon, 25 Dec 2023 15:57:31 +0100
Subject: [PATCH 49/49] release: v4.11.1

---
 README.md                          | 2 +-
 lerna.json                         | 2 +-
 packages/coreui-react/README.md    | 2 +-
 packages/coreui-react/package.json | 2 +-
 packages/docs/package.json         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 929b98ed..e7c25be4 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/lerna.json b/lerna.json
index 494b8b6f..45bfb26a 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "npmClient": "yarn",
   "packages": ["packages/*"],
-  "version": "4.11.0",
+  "version": "4.11.1",
   "$schema": "node_modules/lerna/schemas/lerna-schema.json"
 }
diff --git a/packages/coreui-react/README.md b/packages/coreui-react/README.md
index b970d6a7..f94ece62 100644
--- a/packages/coreui-react/README.md
+++ b/packages/coreui-react/README.md
@@ -46,7 +46,7 @@
 
 Several quick start options are available:
 
-- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.0.zip)
+- [Download the latest release](https://github.com/coreui/coreui-react/archive/v4.11.1.zip)
 - Clone the repo: `git clone https://github.com/coreui/coreui-react.git`
 - Install with [npm](https://www.npmjs.com/): `npm install @coreui/react`
 - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/react`
diff --git a/packages/coreui-react/package.json b/packages/coreui-react/package.json
index 2f37d62b..f523e69a 100644
--- a/packages/coreui-react/package.json
+++ b/packages/coreui-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react",
-  "version": "4.11.0",
+  "version": "4.11.1",
   "description": "UI Components Library for React.js",
   "keywords": [
     "react",
diff --git a/packages/docs/package.json b/packages/docs/package.json
index b84aea76..5a6d2ae5 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@coreui/react-docs",
-  "version": "4.11.0",
+  "version": "4.11.1",
   "private": true,
   "description": "",
   "homepage": "https://coreui.io/react/",