diff --git a/packages/c-live-region/README.md b/packages/c-live-region/README.md
new file mode 100644
index 00000000..63355f8a
--- /dev/null
+++ b/packages/c-live-region/README.md
@@ -0,0 +1,11 @@
+# @chakra-ui/c-live-region
+
+Live region
+
+## Installation
+
+```sh
+yarn add @chakra-ui/c-live-region
+# or
+npm i @chakra-ui/c-live-region
+```
\ No newline at end of file
diff --git a/packages/c-live-region/examples/base-live-region.vue b/packages/c-live-region/examples/base-live-region.vue
new file mode 100644
index 00000000..1f1493c3
--- /dev/null
+++ b/packages/c-live-region/examples/base-live-region.vue
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/packages/c-live-region/index.tsx b/packages/c-live-region/index.tsx
new file mode 100644
index 00000000..46e72b16
--- /dev/null
+++ b/packages/c-live-region/index.tsx
@@ -0,0 +1 @@
+export * from "./src"
diff --git a/packages/c-live-region/package.json b/packages/c-live-region/package.json
new file mode 100644
index 00000000..d5d8cb66
--- /dev/null
+++ b/packages/c-live-region/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@chakra-ui/c-live-region",
+ "description": "Chakra UI Vue | Live region component",
+ "version": "0.0.0-alpha.0",
+ "main": "dist/chakra-ui-c-live-region.cjs.js",
+ "module": "dist/chakra-ui-c-live-region.esm.js",
+ "author": "Jonathan Bakebwa ",
+ "homepage": "https://github.com/chakra-ui/chakra-ui-vue-next#readme",
+ "license": "MIT",
+ "files": [
+ "dist"
+ ],
+ "exports": {
+ ".": {
+ "require": "./dist/chakra-ui-c-live-region.cjs.js",
+ "default": "./dist/chakra-ui-c-live-region.esm.js"
+ }
+ },
+ "repository": "https://github.com/chakra-ui/chakra-ui-vue-next/tree/master/packages/c-live-region",
+ "bugs": {
+ "url": "https://github.com/chakra-ui/chakra-ui-vue-next/issues"
+ },
+ "sideEffects": false,
+ "scripts": {
+ "clean": "rimraf dist"
+ },
+ "dependencies": {
+ "@chakra-ui/vue-system": "0.1.0-alpha.10"
+ },
+ "devDependencies": {
+ "vue": "^3.2.37"
+ },
+ "peerDependencies": {
+ "vue": "^3.1.4"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/c-live-region/src/index.tsx b/packages/c-live-region/src/index.tsx
new file mode 100644
index 00000000..2f32d288
--- /dev/null
+++ b/packages/c-live-region/src/index.tsx
@@ -0,0 +1 @@
+export * from "./live-region"
diff --git a/packages/c-live-region/src/live-region.ts b/packages/c-live-region/src/live-region.ts
new file mode 100644
index 00000000..5dc330ff
--- /dev/null
+++ b/packages/c-live-region/src/live-region.ts
@@ -0,0 +1,139 @@
+import { HTMLAttributes } from "vue"
+
+function isDom() {
+ return Boolean(globalThis?.document)
+}
+const isBrowser = isDom()
+export interface LiveRegionOptions {
+ /**
+ * A unique id for the created live region element
+ */
+ id?: string
+ /**
+ * Used to mark a part of the page as "live" so that updates will
+ * be communicated to users by screen readers.
+ *
+ * - If set to `polite`: tells assistive technology to alert the user
+ * to this change when it has finished whatever it is currently doing
+ *
+ * - If set to `assertive`: tells assistive technology to interrupt whatever
+ * it is doing and alert the user to this change immediately
+ *
+ * @default "polite".
+ */
+ "aria-live"?: "polite" | "assertive"
+ /**
+ * The desired value of the role attribute
+ * @default "status"
+ */
+ role?: "status" | "alert" | "log"
+ /**
+ * Indicates what types of changes should be presented to the user.
+ * @default "all"
+ */
+ "aria-relevant"?: HTMLAttributes["aria-relevant"]
+ /**
+ * Indicates whether the entire region should be
+ * considered as a whole when communicating updates
+ *
+ * @default true
+ */
+ "aria-atomic"?: HTMLAttributes["aria-atomic"]
+ /**
+ * The node to append the live region node to
+ */
+ parentNode?: HTMLElement
+}
+
+export class LiveRegion {
+ region: HTMLElement | null
+ options: Required
+ parentNode: HTMLElement
+
+ constructor(options?: LiveRegionOptions) {
+ this.options = getOptions(options) as any
+ this.region = getRegion(this.options)
+ this.parentNode = this.options.parentNode
+ if (this.region) {
+ this.parentNode.appendChild(this.region)
+ }
+ }
+
+ /**
+ * Message provided to the region to be read out by the Screen Reader.
+ *
+ * Message can be supplied on trigger of some event (i.e. button click)
+ */
+ public speak(message: string) {
+ this.clear()
+ if (this.region) {
+ this.region.innerText = message
+ }
+ }
+
+ /**
+ * Removes the region.
+ */
+ public destroy() {
+ if (this.region) {
+ this.region.parentNode?.removeChild(this.region)
+ }
+ }
+
+ /**
+ * Clears the inner text of the region
+ */
+ public clear() {
+ if (this.region) {
+ this.region.innerText = ""
+ }
+ }
+}
+
+function getOptions(options?: LiveRegionOptions) {
+ const defaultOptions: LiveRegionOptions = {
+ "aria-live": "polite",
+ "aria-atomic": "true",
+ "aria-relevant": "all",
+ role: "status",
+ id: "chakra-a11y-live-region",
+ parentNode: isBrowser ? document.body : undefined,
+ }
+ if (options) {
+ return Object.assign(defaultOptions, options)
+ }
+ return defaultOptions
+}
+
+function getRegion(options: Required) {
+ let region = isBrowser ? document.getElementById(options.id) : null
+
+ if (region) return region
+
+ if (isBrowser) {
+ region = document.createElement("div")
+ setup(region, options)
+ }
+
+ return region
+}
+
+function setup(region: HTMLElement, options: Required) {
+ region.id = options.id || "chakra-live-region"
+ region.className = "__chakra-live-region"
+ region.setAttribute("aria-live", options["aria-live"])
+ region.setAttribute("role", options.role)
+ region.setAttribute("aria-relevant", options["aria-relevant"])
+ region.setAttribute("aria-atomic", String(options["aria-atomic"]))
+ Object.assign(region.style, {
+ border: "0px",
+ clip: "rect(0px, 0px, 0px, 0px)",
+ height: "1px",
+ width: "1px",
+ margin: "-1px",
+ padding: "0px",
+ overflow: "hidden",
+ whiteSpace: "nowrap",
+ position: "absolute",
+ })
+}
diff --git a/packages/c-live-region/src/use-live-region.ts b/packages/c-live-region/src/use-live-region.ts
new file mode 100644
index 00000000..c6c46763
--- /dev/null
+++ b/packages/c-live-region/src/use-live-region.ts
@@ -0,0 +1,14 @@
+import { reactive, watchEffect } from "vue"
+import { LiveRegion, LiveRegionOptions } from "./live-region"
+
+/**
+ * Creates a hidden live region with dynamic content based on triggered events
+ * to be read out by the screen reader on change of the content.
+ */
+export function useLiveRegion(options?: LiveRegionOptions) {
+ const liveRegion = reactive(() => new LiveRegion(options))
+
+ watchEffect((cleanup) => cleanup(() => liveRegion().destroy()))
+
+ return liveRegion()
+}
diff --git a/packages/c-live-region/tests/c-live-region.test.ts b/packages/c-live-region/tests/c-live-region.test.ts
new file mode 100644
index 00000000..d9d924a9
--- /dev/null
+++ b/packages/c-live-region/tests/c-live-region.test.ts
@@ -0,0 +1,54 @@
+import { render } from "@chakra-ui/vue-test-utils"
+import { LiveRegion, LiveRegionOptions } from "../index"
+
+const renderDiv = () =>
+ render({
+ template: ``,
+ })
+
+describe("LiveRegion", () => {
+ it("creates a container and has the proper aria and role attributes", () => {
+ renderDiv()
+
+ new LiveRegion()
+ const region = document.getElementById("chakra-a11y-live-region")
+
+ expect(region).toHaveAttribute("aria-atomic", "true")
+ expect(region).toHaveAttribute("aria-live", "polite")
+ expect(region).toHaveAttribute("aria-relevant", "all")
+ expect(region).toHaveAttribute("role", "status")
+ })
+
+ it("creates a container using the provided options", () => {
+ renderDiv()
+
+ const options: LiveRegionOptions = {
+ id: "some-id",
+ role: "alert",
+ "aria-live": "assertive",
+ "aria-relevant": "removals",
+ "aria-atomic": "false",
+ }
+
+ // eslint-disable-next-line no-new
+ new LiveRegion(options)
+ const region = document.getElementById("some-id")
+
+ expect(region).toHaveAttribute("aria-atomic", "false")
+ expect(region).toHaveAttribute("aria-live", "assertive")
+ expect(region).toHaveAttribute("aria-relevant", "removals")
+ expect(region).toHaveAttribute("role", "alert")
+ })
+
+ it("can 'speak' by setting its text content", () => {
+ renderDiv()
+
+ const liveRegion = new LiveRegion()
+ const region = document.getElementById(
+ "chakra-a11y-live-region"
+ ) as HTMLElement
+
+ liveRegion.speak("Hello World")
+ expect(region.innerText).toEqual("Hello World")
+ })
+})
diff --git a/packages/c-live-region/tsconfig.json b/packages/c-live-region/tsconfig.json
new file mode 100644
index 00000000..fc56401d
--- /dev/null
+++ b/packages/c-live-region/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["src", "./index.tsx", "./index.ts"]
+}
\ No newline at end of file
diff --git a/packages/core/package.json b/packages/core/package.json
index 81fc8caf..6d92b556 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -34,6 +34,7 @@
"@chakra-ui/c-form-control": "0.0.0-alpha.5",
"@chakra-ui/c-icon": "1.0.0-alpha.10",
"@chakra-ui/c-input": "0.0.0-alpha.5",
+ "@chakra-ui/c-live-region": "0.0.0-alpha.0",
"@chakra-ui/c-modal": "1.1.0-alpha.10",
"@chakra-ui/c-motion": "0.1.0-alpha.9",
"@chakra-ui/c-pin-input": "0.0.0-alpha.0",
@@ -47,7 +48,7 @@
"@chakra-ui/c-theme-provider": "1.0.0-alpha.10",
"@chakra-ui/c-visually-hidden": "1.0.0-alpha.10",
"@chakra-ui/styled-system": "^2.2.2",
- "@chakra-ui/utils": "^2.0.3",
+ "@chakra-ui/utils": "2.0.11",
"@chakra-ui/vue-a11y": "0.1.0-alpha.9",
"@chakra-ui/vue-composables": "0.1.0-alpha.9",
"@chakra-ui/vue-layout": "0.1.0-alpha.11",
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 6a1b8041..42295d98 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -147,6 +147,7 @@ export * from "@chakra-ui/c-input"
// L
export * from "@chakra-ui/vue-layout"
+export * from "@chakra-ui/c-live-region"
// M
export * from "@chakra-ui/c-modal"