diff --git a/packages/eslint-plugin-react/src/rules/no-namespace.md b/packages/eslint-plugin-react/src/rules/no-namespace.md
new file mode 100644
index 000000000..b0912fa39
--- /dev/null
+++ b/packages/eslint-plugin-react/src/rules/no-namespace.md
@@ -0,0 +1,19 @@
+# @eslint-react/no-namespace
+
+Enforces the absence of a namespace in React elements, such as with `svg:circle`, as they are not supported in React.
+
+## Rule Details
+
+### ❌ Incorrect
+
+```jsx
+;
+;
+```
+
+### ✅ Correct
+
+```jsx
+;
+;
+```
diff --git a/packages/eslint-plugin-react/src/rules/no-namespace.spec.ts b/packages/eslint-plugin-react/src/rules/no-namespace.spec.ts
new file mode 100644
index 000000000..1d45db20c
--- /dev/null
+++ b/packages/eslint-plugin-react/src/rules/no-namespace.spec.ts
@@ -0,0 +1,151 @@
+import { allValid } from "@eslint-react/shared";
+
+import RuleTester, { getFixturesRootDir } from "../../../../test/rule-tester";
+import rule, { RULE_NAME } from "./no-namespace";
+
+const rootDir = getFixturesRootDir();
+
+const ruleTester = new RuleTester({
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ ecmaVersion: 2021,
+ sourceType: "module",
+ project: "./tsconfig.json",
+ tsconfigRootDir: rootDir,
+ },
+});
+
+ruleTester.run(RULE_NAME, rule, {
+ valid: [
+ ...allValid,
+ "",
+ 'React.createElement("testcomponent")',
+ "",
+ 'React.createElement("testComponent")',
+ "",
+ 'React.createElement("test_component")',
+ "",
+ 'React.createElement("TestComponent")',
+ "",
+ 'React.createElement("object.testcomponent")',
+ "",
+ 'React.createElement("object.testComponent")',
+ "",
+ 'React.createElement("object.test_component")',
+ "",
+ 'React.createElement("object.TestComponent")',
+ "",
+ 'React.createElement("Object.testcomponent")',
+ "",
+ 'React.createElement("Object.testComponent")',
+ "",
+ 'React.createElement("Object.test_component")',
+ "",
+ 'React.createElement("Object.TestComponent")',
+ "React.createElement(null)",
+ "React.createElement(true)",
+ "React.createElement({})",
+ ],
+
+ invalid: [
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("ns:testcomponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("ns:testComponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("ns:test_component")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("ns:TestComponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("Ns:testcomponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("Ns:testComponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("Ns:test_component")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: "",
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ {
+ code: 'React.createElement("Ns:TestComponent")',
+ errors: [{
+ messageId: "NO_NAMESPACE",
+ }],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin-react/src/rules/no-namespace.ts b/packages/eslint-plugin-react/src/rules/no-namespace.ts
new file mode 100644
index 000000000..630e3a5b7
--- /dev/null
+++ b/packages/eslint-plugin-react/src/rules/no-namespace.ts
@@ -0,0 +1,58 @@
+import { isCreateElement } from "@eslint-react/create-element";
+import { elementType } from "@eslint-react/jsx";
+import { createRule } from "@eslint-react/shared";
+import { AST_NODE_TYPES } from "@typescript-eslint/types";
+
+export const RULE_NAME = "no-namespace";
+
+type MessageID = "NO_NAMESPACE";
+
+export default createRule<[], MessageID>({
+ name: RULE_NAME,
+ meta: {
+ type: "problem",
+ docs: {
+ description: "enforce that namespaces are not used in React elements",
+ },
+ schema: [],
+ messages: {
+ NO_NAMESPACE: "React component {{name}} must not be in a namespace, as React does not support them",
+ },
+ },
+ defaultOptions: [],
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (
+ isCreateElement(node, context) && node.arguments.length > 0
+ && node.arguments[0]?.type === AST_NODE_TYPES.Literal
+ ) {
+ const name = node.arguments[0].value;
+ if (typeof name !== "string" || !name.includes(":")) {
+ return;
+ }
+ context.report({
+ data: {
+ name,
+ },
+ messageId: "NO_NAMESPACE",
+ node,
+ });
+ }
+ },
+ JSXOpeningElement(node) {
+ const name = elementType(node);
+ if (typeof name !== "string" || !name.includes(":")) {
+ return;
+ }
+ context.report({
+ data: {
+ name,
+ },
+ messageId: "NO_NAMESPACE",
+ node,
+ });
+ },
+ };
+ },
+});
diff --git a/packages/eslint-react-jsx/src/element-type.ts b/packages/eslint-react-jsx/src/element-type.ts
new file mode 100644
index 000000000..44be33432
--- /dev/null
+++ b/packages/eslint-react-jsx/src/element-type.ts
@@ -0,0 +1,37 @@
+import { AST_NODE_TYPES, type TSESTree } from "@typescript-eslint/types";
+
+function resolveMemberExpressions(object: TSESTree.JSXTagNameExpression, property: TSESTree.JSXIdentifier): string {
+ if (object.type === AST_NODE_TYPES.JSXMemberExpression) {
+ return `${resolveMemberExpressions(object.object, object.property)}.${property.name}`;
+ }
+ if (object.type === AST_NODE_TYPES.JSXNamespacedName) {
+ return `${object.namespace.name}:${object.name.name}.${property.name}`;
+ }
+
+ return `${object.name}.${property.name}`;
+}
+
+/**
+ * Returns the tag name associated with a JSXOpeningElement.
+ * @param node The visited JSXOpeningElement node object.
+ * @returns The element's tag name.
+ */
+export function elementType(node: TSESTree.JSXOpeningElement | TSESTree.JSXOpeningFragment): string {
+ if (node.type === AST_NODE_TYPES.JSXOpeningFragment) {
+ return "<>";
+ }
+
+ const { name } = node;
+
+ if (name.type === AST_NODE_TYPES.JSXMemberExpression) {
+ const { object, property } = name;
+
+ return resolveMemberExpressions(object, property);
+ }
+
+ if (name.type === AST_NODE_TYPES.JSXNamespacedName) {
+ return `${name.namespace.name}:${name.name.name}`;
+ }
+
+ return name.name;
+}
diff --git a/packages/eslint-react-jsx/src/index.ts b/packages/eslint-react-jsx/src/index.ts
index 10ded7dfe..4e4296423 100644
--- a/packages/eslint-react-jsx/src/index.ts
+++ b/packages/eslint-react-jsx/src/index.ts
@@ -1,4 +1,5 @@
export * from "./children";
+export * from "./element-type";
export * from "./event-handler";
export * from "./misc";
export * from "./prop";