diff --git a/js/index.esm.js b/js/index.esm.js
index 51a9ff8ea2624fc1e186c90712d66e1299652965..5d9a1655c1569d6bc1dca38f193a7e783b000957 100644
--- a/js/index.esm.js
+++ b/js/index.esm.js
@@ -6,10 +6,12 @@
  */
 
 export { default as Alert } from './src/alert'
+export { default as Badge } from './src/badge'
 export { default as Button } from './src/button'
 export { default as Carousel } from './src/carousel'
 export { default as Collapse } from './src/collapse'
 export { default as Dropdown } from './src/dropdown'
+export { default as InputBadges } from './src/input-badges'
 export { default as Modal } from './src/modal'
 export { default as Offcanvas } from './src/offcanvas'
 export { default as Popover } from './src/popover'
diff --git a/js/index.umd.js b/js/index.umd.js
index d6e587fb1d5443b233329148dbb6f3d9fc1cd7b9..fbb7381c92f4bd058c03d69c842a52b87bfddea0 100644
--- a/js/index.umd.js
+++ b/js/index.umd.js
@@ -6,10 +6,12 @@
  */
 
 import Alert from './src/alert'
+import Badge from './src/badge'
 import Button from './src/button'
 import Carousel from './src/carousel'
 import Collapse from './src/collapse'
 import Dropdown from './src/dropdown'
+import InputBadges from './src/input-badges'
 import Modal from './src/modal'
 import Offcanvas from './src/offcanvas'
 import Popover from './src/popover'
@@ -20,10 +22,12 @@ import Tooltip from './src/tooltip'
 
 export default {
   Alert,
+  Badge,
   Button,
   Carousel,
   Collapse,
   Dropdown,
+  InputBadges,
   Modal,
   Offcanvas,
   Popover,
diff --git a/js/src/badge.js b/js/src/badge.js
new file mode 100644
index 0000000000000000000000000000000000000000..38fa88b24b9c6e1c5067bbda0361ecce171258cc
--- /dev/null
+++ b/js/src/badge.js
@@ -0,0 +1,98 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.1.3): badge.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import { defineJQueryPlugin } from './util/index'
+import EventHandler from './dom/event-handler'
+import BaseComponent from './base-component'
+import { enableDismissTrigger } from './util/component-functions'
+
+/**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+const NAME = 'badge'
+const DATA_KEY = 'bs.badge'
+const EVENT_KEY = `.${DATA_KEY}`
+const EVENT_CLOSE = `close${EVENT_KEY}`
+const EVENT_CLOSED = `closed${EVENT_KEY}`
+
+/**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+class Badge extends BaseComponent {
+  constructor(element) {
+    super(element)
+
+    this.badge = null
+  }
+
+  // Getters
+
+  static get NAME() {
+    return NAME
+  }
+
+  // Private
+
+  _destroyElement() {
+    this._element.remove()
+    EventHandler.trigger(this._element, EVENT_CLOSED)
+    this.dispose()
+  }
+
+  // Public
+
+  close() {
+    const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)
+
+    if (closeEvent.defaultPrevented) {
+      return
+    }
+
+    this._queueCallback(() => this._destroyElement(), this._element, false)
+  }
+
+  // Static
+
+  static jQueryInterface(config) {
+    return this.each(function () {
+      const data = Badge.getOrCreateInstance(this, config)
+
+      if (typeof config === 'string') {
+        if (typeof data[config] === 'undefined') {
+          throw new TypeError(`No method named "${config}"`)
+        }
+
+        data[config]()
+      }
+    })
+  }
+}
+
+/**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+enableDismissTrigger(Badge, 'close')
+
+/**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ * add .badge to jQuery only if jQuery is present
+ */
+
+defineJQueryPlugin(Badge)
+
+export default Badge
diff --git a/js/src/input-badges.js b/js/src/input-badges.js
new file mode 100644
index 0000000000000000000000000000000000000000..0be317b977164daa86706f00e00b4c67b19fdf43
--- /dev/null
+++ b/js/src/input-badges.js
@@ -0,0 +1,204 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.1.3): input-badges.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import {
+  defineJQueryPlugin,
+  typeCheckConfig
+} from './util/index'
+import Manipulator from './dom/manipulator'
+import EventHandler from './dom/event-handler'
+import BaseComponent from './base-component'
+import Badge from './badge'
+
+/**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+const NAME = 'input-badges'
+const DefaultType = {
+  rounded: 'boolean',
+  colour: 'string'
+}
+
+const Default = {
+  rounded: false,
+  colour: 'primary'
+}
+
+const COLOUR_VALUES = [
+  'primary',
+  'secondary',
+  'success',
+  'danger',
+  'warning',
+  'info',
+  'light',
+  'dark'
+]
+
+const DATA_KEY = 'bs.input-badges'
+const EVENT_KEY = `.${DATA_KEY}`
+
+const EVENT_BADGE_ADD = `add${EVENT_KEY}`
+const EVENT_BADGE_ADDED = `added${EVENT_KEY}`
+const EVENT_BADGE_REMOVED = `removed${EVENT_KEY}`
+
+/**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+class InputBadges extends BaseComponent {
+  constructor(element, config) {
+    super(element)
+
+    // Protected
+    this._config = this._getConfig(config)
+
+    const wrapperDiv = document.createElement('div')
+    for (let i = 0; i < this._element.classList.length; i++) {
+      const className = this._element.classList[i]
+      wrapperDiv.classList.add(className)
+    }
+
+    this._element.parentNode.insertBefore(wrapperDiv, this._element)
+    wrapperDiv.append(this._element)
+    this._element.classList.add('d-none')
+
+    const visibleInput = document.createElement('INPUT')
+    visibleInput.setAttribute('type', 'text')
+    visibleInput.classList.add('border-0', 'w-25', 'form-control-plaintext', 'py-0', 'd-inline')
+    wrapperDiv.append(visibleInput)
+
+    wrapperDiv.style.cursor = 'text'
+
+    wrapperDiv.addEventListener('click', () => {
+      visibleInput.focus()
+    })
+
+    visibleInput.addEventListener('keyup', event => {
+      if (event.key !== 'Backspace' || visibleInput.value !== '') {
+        return
+      }
+
+      const existingBadges = Array.from(wrapperDiv.childNodes).filter(item => {
+        return item.nodeName === 'SPAN'
+      })
+
+      if (existingBadges.length > 0) {
+        Badge.getOrCreateInstance(existingBadges[existingBadges.length - 1]).close()
+        EventHandler.trigger(this._element, EVENT_BADGE_REMOVED)
+      }
+    })
+
+    visibleInput.addEventListener('keyup', event => {
+      if (event.key !== 'Enter') {
+        return
+      }
+
+      if (visibleInput.value === '') {
+        return
+      }
+
+      const existingValue = this._element.value.split(',').find(value => value === encodeURIComponent(visibleInput.value))
+      if (existingValue) {
+        return
+      }
+
+      const addBadgeEvent = EventHandler.trigger(this._element, EVENT_BADGE_ADD)
+
+      if (addBadgeEvent.defaultPrevented) {
+        return
+      }
+
+      const newBadge = document.createElement('span')
+      newBadge.classList.add('badge', `bg-${this._config.colour}`, 'badge-dismissable')
+      if (this._config.rounded) {
+        newBadge.classList.add('rounded-pill')
+      }
+
+      this._element.value += `${encodeURIComponent(visibleInput.value)},`
+      newBadge.textContent = visibleInput.value
+      const closeButton = document.createElement('button')
+      closeButton.setAttribute('type', 'button')
+      closeButton.classList.add('btn-close')
+      closeButton.setAttribute('data-bs-dismiss', 'badge')
+      closeButton.setAttribute('aria-label', 'Close')
+      newBadge.append(closeButton)
+      Badge.getOrCreateInstance(newBadge)
+      newBadge.addEventListener('closed.bs.badge', () => {
+        this._element.value = this._element.value.replace(`${encodeURIComponent(newBadge.textContent)},`, '')
+        EventHandler.trigger(this._element, EVENT_BADGE_REMOVED)
+      })
+      visibleInput.value = ''
+      visibleInput.before(newBadge)
+      EventHandler.trigger(this._element, EVENT_BADGE_ADDED)
+    })
+  }
+
+  // Getters
+
+  static get NAME() {
+    return NAME
+  }
+
+  static get Default() {
+    return Default
+  }
+
+  static get DefaultType() {
+    return DefaultType
+  }
+
+  // Private
+
+  _getConfig(config) {
+    const dataAttributes = Manipulator.getDataAttributes(this._element)
+
+    config = {
+      ...this.constructor.Default,
+      ...dataAttributes,
+      ...(typeof config === 'object' && config ? config : {})
+    }
+
+    typeCheckConfig(NAME, config, this.constructor.DefaultType)
+
+    config.colour = COLOUR_VALUES.find(col => col === config.colour) || Default.colour
+
+    return config
+  }
+
+  // Static
+
+  static jQueryInterface(config) {
+    return this.each(function () {
+      const data = InputBadges.getOrCreateInstance(this, config)
+
+      if (typeof config === 'string') {
+        if (typeof data[config] === 'undefined') {
+          throw new TypeError(`No method named "${config}"`)
+        }
+
+        data[config]()
+      }
+    })
+  }
+}
+
+/**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ * add .input-badges to jQuery only if jQuery is present
+ */
+
+defineJQueryPlugin(InputBadges)
+
+export default InputBadges
diff --git a/js/tests/unit/badge.spec.js b/js/tests/unit/badge.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e65d2fddaf14703e374f159df06d2e47ac1d7fc
--- /dev/null
+++ b/js/tests/unit/badge.spec.js
@@ -0,0 +1,232 @@
+import Badge from '../../src/badge'
+import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture'
+
+describe('Badge', () => {
+  let fixtureEl
+
+  beforeAll(() => {
+    fixtureEl = getFixture()
+  })
+
+  afterEach(() => {
+    clearFixture()
+  })
+
+  it('should take care of element either passed as a CSS selector or DOM element', () => {
+    fixtureEl.innerHTML = '<div class="badge"></div>'
+
+    const badgeEl = fixtureEl.querySelector('.badge')
+    const badgeBySelector = new Badge('.badge')
+    const badgeByElement = new Badge(badgeEl)
+
+    expect(badgeBySelector._element).toEqual(badgeEl)
+    expect(badgeByElement._element).toEqual(badgeEl)
+  })
+
+  it('should return version', () => {
+    expect(Badge.VERSION).toEqual(jasmine.any(String))
+  })
+
+  describe('DATA_KEY', () => {
+    it('should return plugin data key', () => {
+      expect(Badge.DATA_KEY).toEqual('bs.badge')
+    })
+  })
+
+  describe('data-api', () => {
+    it('should close a badge without instantiating it manually', () => {
+      fixtureEl.innerHTML = [
+        '<div class="badge">',
+        '  <button type="button" data-bs-dismiss="badge">x</button>',
+        '</div>'
+      ].join('')
+
+      const button = document.querySelector('button')
+
+      button.click()
+      expect(document.querySelectorAll('.badge')).toHaveSize(0)
+    })
+
+    it('should close a badge without instantiating it manually with the parent selector', () => {
+      fixtureEl.innerHTML = [
+        '<div class="badge">',
+        '  <button type="button" data-bs-target=".badge" data-bs-dismiss="badge">x</button>',
+        '</div>'
+      ].join('')
+
+      const button = document.querySelector('button')
+
+      button.click()
+      expect(document.querySelectorAll('.badge')).toHaveSize(0)
+    })
+  })
+
+  describe('close', () => {
+    it('should close a badge', done => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const badgeEl = document.querySelector('.badge')
+      const badge = new Badge(badgeEl)
+
+      badgeEl.addEventListener('closed.bs.badge', () => {
+        expect(document.querySelectorAll('.badge')).toHaveSize(0)
+        done()
+      })
+
+      badge.close()
+    })
+
+    it('should not remove badge if close event is prevented', done => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const getBadge = () => document.querySelector('.badge')
+      const badgeEl = getBadge()
+      const badge = new Badge(badgeEl)
+
+      badgeEl.addEventListener('close.bs.badge', event => {
+        event.preventDefault()
+        setTimeout(() => {
+          expect(getBadge()).not.toBeNull()
+          done()
+        }, 10)
+      })
+
+      badgeEl.addEventListener('closed.bs.badge', () => {
+        throw new Error('should not fire closed event')
+      })
+
+      badge.close()
+    })
+  })
+
+  describe('dispose', () => {
+    it('should dispose a badge', () => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const badgeEl = document.querySelector('.badge')
+      const badge = new Badge(badgeEl)
+
+      expect(Badge.getInstance(badgeEl)).not.toBeNull()
+
+      badge.dispose()
+
+      expect(Badge.getInstance(badgeEl)).toBeNull()
+    })
+  })
+
+  describe('jQueryInterface', () => {
+    it('should handle config passed and toggle existing badge', () => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const badgeEl = fixtureEl.querySelector('.badge')
+      const badge = new Badge(badgeEl)
+
+      spyOn(badge, 'close')
+
+      jQueryMock.fn.badge = Badge.jQueryInterface
+      jQueryMock.elements = [badgeEl]
+
+      jQueryMock.fn.badge.call(jQueryMock, 'close')
+
+      expect(badge.close).toHaveBeenCalled()
+    })
+
+    it('should create new badge instance and call close', () => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const badgeEl = fixtureEl.querySelector('.badge')
+
+      jQueryMock.fn.badge = Badge.jQueryInterface
+      jQueryMock.elements = [badgeEl]
+
+      expect(Badge.getInstance(badgeEl)).toBeNull()
+      jQueryMock.fn.badge.call(jQueryMock, 'close')
+
+      expect(fixtureEl.querySelector('.badge')).toBeNull()
+    })
+
+    it('should just create a badge instance without calling close', () => {
+      fixtureEl.innerHTML = '<div class="badge"></div>'
+
+      const badgeEl = fixtureEl.querySelector('.badge')
+
+      jQueryMock.fn.badge = Badge.jQueryInterface
+      jQueryMock.elements = [badgeEl]
+
+      jQueryMock.fn.badge.call(jQueryMock)
+
+      expect(Badge.getInstance(badgeEl)).not.toBeNull()
+      expect(fixtureEl.querySelector('.badge')).not.toBeNull()
+    })
+
+    it('should throw an error on undefined method', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const action = 'undefinedMethod'
+
+      jQueryMock.fn.badge = Badge.jQueryInterface
+      jQueryMock.elements = [div]
+
+      expect(() => {
+        jQueryMock.fn.badge.call(jQueryMock, action)
+      }).toThrowError(TypeError, `No method named "${action}"`)
+    })
+
+    it('should throw an error on protected method', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const action = '_getConfig'
+
+      jQueryMock.fn.badge = Badge.jQueryInterface
+      jQueryMock.elements = [div]
+
+      expect(() => {
+        jQueryMock.fn.badge.call(jQueryMock, action)
+      }).toThrowError(TypeError, `No method named "${action}"`)
+    })
+  })
+
+  describe('getInstance', () => {
+    it('should return badge instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const badge = new Badge(div)
+
+      expect(Badge.getInstance(div)).toEqual(badge)
+      expect(Badge.getInstance(div)).toBeInstanceOf(Badge)
+    })
+
+    it('should return null when there is no badge instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Badge.getInstance(div)).toBeNull()
+    })
+  })
+
+  describe('getOrCreateInstance', () => {
+    it('should return badge instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const badge = new Badge(div)
+
+      expect(Badge.getOrCreateInstance(div)).toEqual(badge)
+      expect(Badge.getInstance(div)).toEqual(Badge.getOrCreateInstance(div, {}))
+      expect(Badge.getOrCreateInstance(div)).toBeInstanceOf(Badge)
+    })
+
+    it('should return new instance when there is no badge instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Badge.getInstance(div)).toBeNull()
+      expect(Badge.getOrCreateInstance(div)).toBeInstanceOf(Badge)
+    })
+  })
+})
diff --git a/js/tests/visual/badge.html b/js/tests/visual/badge.html
new file mode 100644
index 0000000000000000000000000000000000000000..a3793d46052300fcd85e8c964d7db5a7ede528fc
--- /dev/null
+++ b/js/tests/visual/badge.html
@@ -0,0 +1,152 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link href="../../../dist/css/bootstrap.min.css" rel="stylesheet">
+    <title>Badge</title>
+  </head>
+  <body>
+    <div class="container">
+      <h1>Badge <small>Bootstrap Visual Test</small></h1>
+
+      <span class="badge bg-primary badge-dismissable" role="badge">
+        Primary
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-secondary badge-dismissable" role="badge">
+        Secondary
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-success badge-dismissable" role="badge">
+        Success
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-danger badge-dismissable" role="badge">
+        Danger
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-warning text-dark badge-dismissable" role="badge">
+        Warning
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-info text-dark badge-dismissable" role="badge">
+        Info
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-light text-dark badge-dismissable" role="badge">
+        Light
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge bg-dark badge-dismissable" role="badge">
+        Dark
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+
+      <span class="badge rounded-pill  badge-dismissable bg-primary" role="badge">
+        Primary
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-secondary" role="badge">
+        Secondary
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-success" role="badge">
+        Success
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-danger" role="badge">
+        Danger
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-warning text-dark" role="badge">
+        Warning
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-info text-dark" role="badge">
+        Info
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-light text-dark" role="badge">
+        Light
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-dark" role="badge">
+        Dark
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+      </span>
+
+      <span class="badge bg-primary badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Primary
+      </span>
+      <span class="badge bg-secondary badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Secondary
+      </span>
+      <span class="badge bg-success badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Success
+      </span>
+      <span class="badge bg-danger badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Danger
+      </span>
+      <span class="badge bg-warning text-dark badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Warning
+      </span>
+      <span class="badge bg-info text-dark badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Info
+      </span>
+      <span class="badge bg-light text-dark badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Light
+      </span>
+      <span class="badge bg-dark badge-dismissable" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Dark
+      </span>
+
+      <span class="badge rounded-pill  badge-dismissable bg-primary" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Primary
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-secondary" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Secondary
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-success" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Success
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-danger" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Danger
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-warning text-dark" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Warning
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-info text-dark" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Info
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-light text-dark" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Light
+      </span>
+      <span class="badge rounded-pill  badge-dismissable bg-dark" role="badge">
+        <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+        Dark
+      </span>
+    </div>
+
+    <script src="../../dist/dom/event-handler.js"></script>
+    <script src="../../dist/dom/selector-engine.js"></script>
+    <script src="../../dist/dom/data.js"></script>
+    <script src="../../dist/base-component.js"></script>
+    <script src="../../dist/badge.js"></script>
+  </body>
+</html>
diff --git a/scss/_badge.scss b/scss/_badge.scss
index 08df1b84a7e625d4f0995d111ff179da692df20a..0f338275b072e50810fd3c778fafdf12451f0b85 100644
--- a/scss/_badge.scss
+++ b/scss/_badge.scss
@@ -4,6 +4,7 @@
 // `background-color`.
 
 .badge {
+  position: relative;
   display: inline-block;
   padding: $badge-padding-y $badge-padding-x;
   @include font-size($badge-font-size);
@@ -22,6 +23,19 @@
   }
 }
 
+.badge-dismissable {
+  padding-right: $badge-dismissible-padding-r;
+
+  // Adjust close link position
+  .btn-close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    z-index: $stretched-link-z-index + 1;
+    padding: $badge-padding-y $badge-padding-x * .77;
+  }
+}
+
 // Quick fix for badges in buttons
 .btn .badge {
   position: relative;
diff --git a/scss/_variables.scss b/scss/_variables.scss
index 9db64ae7228b1a6ee4a6018ba0aa985d735aafbe..6a490d10f0c43bee0576b4abe6264095c97f1f1d 100644
--- a/scss/_variables.scss
+++ b/scss/_variables.scss
@@ -1356,6 +1356,7 @@ $badge-color:                       $white !default;
 $badge-padding-y:                   .35em !default;
 $badge-padding-x:                   .65em !default;
 $badge-border-radius:               $border-radius !default;
+$badge-dismissible-padding-r:       $badge-padding-x * 3 !default; // 3x covers width of x plus default padding on either side
 // scss-docs-end badge-variables
 
 
diff --git a/scss/forms/_form-control.scss b/scss/forms/_form-control.scss
index 51b3baa838603ee1b1af1f7cce6cbb36be5bbd4a..eaa9ed16aadc059b339d19b572e2f63658c5329f 100644
--- a/scss/forms/_form-control.scss
+++ b/scss/forms/_form-control.scss
@@ -186,3 +186,9 @@ textarea {
     @include border-radius($input-border-radius);
   }
 }
+
+.form-control .badge {
+  margin-top: 2px;
+  margin-right: 2px;
+  vertical-align: top;
+}
diff --git a/site/assets/js/application.js b/site/assets/js/application.js
index 2c57906c9fbd34906a14c8d83f6ab162794f8050..731e76f63e373471fd09e82e1bb825d2ff24d2ce 100644
--- a/site/assets/js/application.js
+++ b/site/assets/js/application.js
@@ -23,6 +23,16 @@
       })
     })
 
+  document.querySelectorAll('input[type="text"][data-bs-badges="input-badges"]')
+    .forEach(function (inputBadge) {
+      new bootstrap.InputBadges(inputBadge)
+    })
+
+  document.querySelectorAll('.badge')
+    .forEach(function (badge) {
+      new bootstrap.Badge(badge)
+    })
+
   document.querySelectorAll('[data-bs-toggle="popover"]')
     .forEach(function (popover) {
       new bootstrap.Popover(popover)
diff --git a/site/content/docs/5.1/components/badge.md b/site/content/docs/5.1/components/badge.md
index de80d3b27a59cbde392250644308742829587d6c..4298827fc0f6c31bfb8cce5f46d61853275d8982 100644
--- a/site/content/docs/5.1/components/badge.md
+++ b/site/content/docs/5.1/components/badge.md
@@ -60,6 +60,27 @@ You can also replace the `.badge` class with a few more utilities without a coun
 </button>
 {{< /example >}}
 
+### Dismissing
+
+Using the badge JavaScript plugin, it's possible to dismiss any badge inline. Here's how:
+
+- Be sure you've loaded the badge plugin, or the compiled Bootstrap JavaScript.
+- Add a [close button]({{< docsref "/components/close-button" >}}) and the `.badge-dismissible` class, which adds extra padding to the right of the badge and positions the close button.
+- On the close button, add the `data-bs-dismiss="badge"` attribute, which triggers the JavaScript functionality. Be sure to use the `<button>` element with it for proper behavior across all devices.
+
+You can see this in action with a live demo:
+
+{{< example >}}
+<span class="badge bg-primary badge-dismissable" role="badge">
+  Primary
+  <button type="button" class="btn-close" data-bs-dismiss="badge" aria-label="Close"></button>
+</span>
+{{< /example >}}
+
+{{< callout warning >}}
+When an badge is dismissed, the element is completely removed from the page structure. If a keyboard user dismisses the badge using the close button, their focus will suddenly be lost and, depending on the browser, reset to the start of the page/document. For this reason, we recommend including additional JavaScript that listens for the `closed.bs.badge` event and programmatically sets `focus()` to the most appropriate location in the page. If you're planning to move focus to a non-interactive element that normally does not receive focus, make sure to add `tabindex="-1"` to the element.
+{{< /callout >}}
+
 ## Background colors
 
 Use our background utility classes to quickly change the appearance of a badge. Please note that when using Bootstrap's default `.bg-light`, you'll likely need a text color utility like `.text-dark` for proper styling. This is because background utilities do not set anything but `background-color`.
@@ -91,3 +112,116 @@ Use the `.rounded-pill` utility class to make badges more rounded with a larger
 ### Variables
 
 {{< scss-docs name="badge-variables" file="scss/_variables.scss" >}}
+
+## JavaScript behavior
+
+### Initialize
+
+Initialize elements as badges
+
+```js
+var badgeList = document.querySelectorAll('.badge')
+var badges = Array.prototype.slice.call(badgeList).map(function (element) {
+  return new bootstrap.Badge(element)
+})
+```
+
+{{< callout info >}}
+For the sole purpose of dismissing a badge, it isn't necessary to initialize the component manually via the JS API. By making use of `data-bs-dismiss="badge"`, the component will be initialized automatically and properly dismissed.
+
+See the [triggers](#triggers) section for more details.
+{{< /callout >}}
+
+### Triggers
+
+{{% js-dismiss "badge" %}}
+
+**Note that closing an badge will remove it from the DOM.**
+
+### Methods
+
+<table class="table">
+  <thead>
+    <tr>
+      <th>Method</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>
+        <code>close</code>
+      </td>
+      <td>
+        Closes an badge by removing it from the DOM. If the <code>.fade</code> and <code>.show</code> classes are present on the element, the badge will fade out before it is removed.
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>dispose</code>
+      </td>
+      <td>
+        Destroys an element's badge. (Removes stored data on the DOM element)
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the badge instance associated to a DOM element, you can use it like this: <code>bootstrap.Badge.getInstance(badge)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns an badge instance associated to a DOM element or create a new one in case it wasn't initialized.
+        You can use it like this: <code>bootstrap.Badge.getOrCreateInstance(element)</code>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+```js
+var badgeNode = document.querySelector('.badge')
+var badge = bootstrap.Badge.getInstance(badgeNode)
+badge.close()
+```
+
+### Events
+
+Bootstrap's badge plugin exposes a few events for hooking into badge functionality.
+
+<table class="table">
+  <thead>
+    <tr>
+      <th>Event</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td><code>close.bs.badge</code></td>
+      <td>
+        Fires immediately when the <code>close</code> instance method is called.
+      </td>
+    </tr>
+    <tr>
+      <td><code>closed.bs.badge</code></td>
+      <td>
+        Fired when the badge has been closed and CSS transitions have completed.
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+```js
+var myBadge = document.getElementById('myBadge')
+myBadge.addEventListener('closed.bs.badge', function () {
+  // do something, for instance, explicitly move focus to the most appropriate element,
+  // so it doesn't get lost/reset to the start of the page
+  // document.getElementById('...').focus()
+})
+```
diff --git a/site/content/docs/5.1/components/input-badges.md b/site/content/docs/5.1/components/input-badges.md
new file mode 100644
index 0000000000000000000000000000000000000000..e58130abb273be74eed2e1bbd82949d81b70f34b
--- /dev/null
+++ b/site/content/docs/5.1/components/input-badges.md
@@ -0,0 +1,117 @@
+---
+layout: docs
+title: Input Badges
+description: Input badges can be used to represent small blocks of information.
+group: components
+toc: true
+---
+
+## How it works
+
+The input badges uses dismissable [badge]({{< docsref "/components/badge" >}}) internally to provide the functionality.
+
+## Example
+
+Add tags below by pressing "Enter" and click on the cross button to remove them.
+
+{{< example >}}
+<input class="form-control" type="text" data-bs-badges="input-badges" data-bs-colour="secondary" data-bs-rounded="false">
+{{< /example >}}
+
+## JavaScript behavior
+
+### Initialize
+
+Initialize elements as input badges
+
+```js
+var inputBadgesList = document.querySelectorAll('input[type="text"][data-bs-badges="input-badges"]')
+var inputBadges = Array.prototype.slice.call(inputBadgesList).map(function (element) {
+  return new bootstrap.InputBadges(element)
+})
+```
+
+### Methods
+
+<table class="table">
+  <thead>
+    <tr>
+      <th>Method</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>
+        <code>dispose</code>
+      </td>
+      <td>
+        Destroys an element's badge. (Removes stored data on the DOM element)
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the badge instance associated to a DOM element, you can use it like this: <code>bootstrap.Badge.getInstance(badge)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns an badge instance associated to a DOM element or create a new one in case it wasn't initialized.
+        You can use it like this: <code>bootstrap.Badge.getOrCreateInstance(element)</code>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+```js
+var inputBadgesNode = document.querySelector('input[type="text"][data-bs-badges="input-badges"]')
+var inputBadge = bootstrap.InputBadges.getInstance(inputBadgesNode)
+inputBadge.dispose()
+```
+
+### Events
+
+Bootstrap's input badges plugin exposes a few events for hooking into input badges functionality.
+
+<table class="table">
+  <thead>
+    <tr>
+      <th>Event</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td><code>add.bs.input-badges</code></td>
+      <td>
+        Fires immediately 'Enter' is pressed and the input value is new and not empty.
+      </td>
+    </tr>
+    <tr>
+      <td><code>added.bs.input-badges</code></td>
+      <td>
+        Fires immediately after a new badge is added to the list.
+      </td>
+    </tr>
+    <tr>
+      <td><code>removed.bs.input-badges</code></td>
+      <td>
+        Fired after a badge is removed from the list.
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+```js
+var inputBadges = document.getElementById('inputBadges')
+inputBadges.addEventListener('add.bs.input-badges', function () {
+  // do something, for instance, check the value to be added is valid
+  // so it doesn't get to the field
+})
+```
diff --git a/site/data/sidebar.yml b/site/data/sidebar.yml
index df95692afa3894b4404a427b98da4d4b1d04219e..9b6ef8dc05550810e07d4529604bc89e49b35bbe 100644
--- a/site/data/sidebar.yml
+++ b/site/data/sidebar.yml
@@ -69,6 +69,7 @@
     - title: Close button
     - title: Collapse
     - title: Dropdowns
+    - title: Input Badges
     - title: List group
     - title: Modal
     - title: Navs & tabs