diff --git a/apps/docs/src/examples/chip.module.css b/apps/docs/src/examples/chip.module.css
new file mode 100644
index 00000000..403f423b
--- /dev/null
+++ b/apps/docs/src/examples/chip.module.css
@@ -0,0 +1,53 @@
+.section {
+ display: flex;
+ flex-direction: row;
+ column-gap: 10px;
+}
+
+.chip {
+ display: flex;
+ column-gap: 2px;
+ border: 1px solid black;
+ width: max-content;
+ padding: 5px 10px;
+ border-radius: 30px;
+ cursor: pointer;
+ background-color: #0369a0;
+}
+
+.chip:hover {
+ background-color: #0092e0;
+}
+
+.chip__label {
+ color: #fff;
+}
+
+.chip[aria-disabled="true"] {
+ background-color: #0369a0;
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.chip__deletable {
+ display: flex;
+ column-gap: 10px;
+ border: 1px solid black;
+ background-color: aliceblue;
+ width: max-content;
+ padding: 5px 10px;
+ border-radius: 30px;
+ cursor: pointer;
+ background-color: #0369a0;
+}
+
+.chip__deletable:hover {
+ background-color: #0092e0;
+}
+
+
+.delete {
+ color: black;
+ font-weight: 500;
+ font-size: 16px;
+}
diff --git a/apps/docs/src/examples/chip.tsx b/apps/docs/src/examples/chip.tsx
new file mode 100644
index 00000000..d141496f
--- /dev/null
+++ b/apps/docs/src/examples/chip.tsx
@@ -0,0 +1,25 @@
+import { Chip } from "@kobalte/core/chip";
+
+import style from "./chip.module.css";
+
+console.log('style', style);
+
+export function BasicExample() {
+ return (
+
` with `role="button"` for accessibility but can easily be wrapped in other elements if needed.
+- **ARIA Attributes**: Implements necessary ARIA roles for accessibility (`role="button"`, `aria-disabled`).
+- **Composable Subcomponents**: Includes a `Chip.Label` component to separate label content from other chip elements.
+
+## Anatomy
+
+The Chip consists of:
+
+- **Chip** - The root container for the chip.
+- **Chip.Label** - The label that is highly configurable which gives information to the user.
+
+```tsx
+
+
+
+```
+
+## Example
+
+
+
+
+
+
+
+ index.tsx
+ style.css
+
+ {/* */}
+
+ ```tsx
+import { Chip } from "@kobalte/core/chip";
+import "./style.css";
+
+function App() {
+ return (
+
+ console.log('onClickHandler - Chip A')} class={chip}>
+ Chip A
+
+ console.log('onClickHandler - Chip B')} class={chip}>
+ Chip B
+
+ console.log('this is a disabled chip')} class={chip} disabled={true}>
+ Disabled Chip C
+
+ console.log('delete me on click!!!')} class={chip__deletable}>
+ Deletable Chip D
+ X
+
+
+ );
+ }
+ ```
+
+
+
+ ```css
+ .section {
+ display: flex;
+ flex-direction: row;
+ column-gap: 10px;
+ }
+
+ .chip {
+ display: flex;
+ column-gap: 2px;
+ border: 1px solid black;
+ width: max-content;
+ padding: 5px 10px;
+ border-radius: 30px;
+ cursor: pointer;
+ background-color: #0369a0;
+ }
+
+ .chip:hover {
+ background-color: #0092e0;
+ }
+
+ .chip__label {
+ color: #fff;
+ }
+
+ .chip[aria-disabled="true"] {
+ background-color: #0369a0;
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+
+ .chip__deletable {
+ display: flex;
+ column-gap: 10px;
+ border: 1px solid black;
+ background-color: aliceblue;
+ width: max-content;
+ padding: 5px 10px;
+ border-radius: 30px;
+ cursor: pointer;
+ background-color: #0369a0;
+ }
+
+ .chip__deletable:hover {
+ background-color: #0092e0;
+ }
+
+ .delete {
+ color: black;
+ font-weight: 500;
+ font-size: 16px;
+ }
+ ```
+
+
+ {/* */}
+
+
+## API Reference
+
+### Chip
+
+`Chip` is equivalent to the `Root` import from `@kobalte/core/chip` (and deprecated `Chip.Root`).
+
+| Prop | Description |
+| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| disabled | `boolean`
If true, the component is disabled. |
+| onClick | Callback function to handle onClick events. Keyboard events for enter and space would also trigger this callback on pressing `Enter` or `Space`. |
+
+### Chip.Label
+
+| Prop | Description |
+| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| label | `string`
Uses label, if no children is provided |
+
+## Accessibility
+
+### Keyboard Interactions
+
+| Key | Description |
+| :--------------- | :------------------------------- |
+|
Enter | Triggers the onClick handler when pressed. |
+|
Space | Triggers the onClick handler when pressed. |
diff --git a/packages/core/src/chip/chip-delete.tsx b/packages/core/src/chip/chip-delete.tsx
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/core/src/chip/chip-label.tsx b/packages/core/src/chip/chip-label.tsx
new file mode 100644
index 00000000..9050b631
--- /dev/null
+++ b/packages/core/src/chip/chip-label.tsx
@@ -0,0 +1,22 @@
+import { type ValidComponent, type JSX, splitProps } from "solid-js";
+import { type ElementOf, Polymorphic, type PolymorphicProps } from "../polymorphic";
+
+export interface LabelOptions {
+ label?: string;
+ children?: JSX.Element;
+}
+
+export interface LabelCommonProps
{
+ id?: string;
+ style?: JSX.CSSProperties | string;
+}
+
+export type LabelProps<
+ T extends ValidComponent | HTMLElement = HTMLElement,
+> = LabelOptions & Partial>>;
+
+export function Label(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props, ["label", "children"]);
+
+ return {local.label || local.children}
+}
diff --git a/packages/core/src/chip/chip-root.tsx b/packages/core/src/chip/chip-root.tsx
new file mode 100644
index 00000000..0c38a8ed
--- /dev/null
+++ b/packages/core/src/chip/chip-root.tsx
@@ -0,0 +1,61 @@
+import { createSignal, mergeProps, splitProps, type JSX, type ValidComponent } from "solid-js";
+import { type ElementOf, Polymorphic, type PolymorphicProps } from "../polymorphic";
+import { mergeDefaultProps } from "@kobalte/utils";
+
+export interface ChipRootOptions {
+ /** Event handler called when the chip is clicked. */
+ onClick?: () => void;
+ /** Whether to disable the chip or not... */
+ disabled?: boolean;
+ /** The children of the chip. */
+ children?: JSX.Element;
+}
+
+export interface ChipCommonProps {
+ id?: string;
+ style?: JSX.CSSProperties | string;
+}
+
+export type ChipRootProps<
+ T extends ValidComponent | HTMLElement = HTMLElement,
+> = ChipRootOptions & Partial>>;
+
+export function Chip(
+ props: PolymorphicProps>,
+) {
+ // Merging default values
+ const mergedProps = mergeDefaultProps(
+ { disabled: false },
+ props as ChipRootProps,
+ );
+
+ const [local, others] = splitProps(mergedProps, ["disabled", "onClick"]);
+
+ const handleSelect = () => {
+ if (!local.disabled) {
+ local.onClick?.();
+ }
+ };
+
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (!local.disabled && (event.key === "Enter" || event.key === " ")) {
+ event.preventDefault(); // Prevents scrolling when using the Space key
+ handleSelect();
+ }
+ };
+
+ return (
+
+ {props.children}
+
+ );
+}
diff --git a/packages/core/src/chip/chip.test.tsx b/packages/core/src/chip/chip.test.tsx
new file mode 100644
index 00000000..27a35cf7
--- /dev/null
+++ b/packages/core/src/chip/chip.test.tsx
@@ -0,0 +1,68 @@
+import { fireEvent, render } from "@solidjs/testing-library";
+import { afterAll, describe, expect, it, vi } from "vitest";
+
+import * as Chip from ".";
+
+describe("Chip", () => {
+ const consoleMock = vi
+ .spyOn(console, "log")
+ .mockImplementation(() => undefined);
+
+ afterEach(() => {
+ consoleMock.mockClear();
+ });
+
+ afterAll(() => {
+ consoleMock.mockReset();
+ });
+
+ it("should show Chip and it should be clickable", () => {
+ const { getByRole } = render(() => (
+ console.log("hello world from chip A")}>
+ Chip A
+
+ ));
+
+ const button = getByRole("button", { name: /chip a/i });
+ fireEvent.click(button);
+ expect(consoleMock).toHaveBeenLastCalledWith("hello world from chip A");
+ });
+
+ it("should show disabled Chip and it should not be clickable", () => {
+ const { getByRole } = render(() => (
+ console.log("not called")} disabled>
+ Disabled Chip A
+
+ ));
+
+ const button = getByRole("button", { name: /disabled chip a/i });
+ fireEvent.click(button);
+ expect(consoleMock).not.toHaveBeenCalled();
+ });
+
+ describe("keyboard accessible", () => {
+ it("should show Chip and it should be clickable via keyboard enter", () => {
+ const { getByRole } = render(() => (
+ console.log("hello world from chip A")}>
+ Chip A
+
+ ));
+
+ const button = getByRole("button", { name: /chip a/i });
+ fireEvent.keyDown(button, { key: "Enter", code: "Enter", charCode: 13 });
+ expect(consoleMock).toHaveBeenCalledWith("hello world from chip A");
+ });
+
+ it("should show Chip and it should be clickable via keyboard space", () => {
+ const { getByRole } = render(() => (
+ console.log("hello world from chip B")}>
+ Chip B
+
+ ));
+
+ const button = getByRole("button", { name: /chip b/i });
+ fireEvent.keyDown(button, { key: " ", code: "Space", charCode: 32 });
+ expect(consoleMock).toHaveBeenCalledWith("hello world from chip B");
+ });
+ });
+});
diff --git a/packages/core/src/chip/index.tsx b/packages/core/src/chip/index.tsx
new file mode 100644
index 00000000..5811f7b9
--- /dev/null
+++ b/packages/core/src/chip/index.tsx
@@ -0,0 +1,30 @@
+
+
+import {
+ Label,
+ type LabelCommonProps,
+ type LabelOptions,
+ type LabelProps,
+} from "./chip-label";
+
+import {
+ type ChipCommonProps,
+ type ChipRootOptions,
+ type ChipRootProps,
+ Chip as Root,
+} from "./chip-root";
+
+export type {
+ LabelCommonProps,
+ LabelOptions,
+ LabelProps,
+ ChipCommonProps,
+ ChipRootOptions,
+ ChipRootProps,
+};
+
+export { Root, Label };
+
+export const Chip = Object.assign(Root, {
+ Label,
+});
diff --git a/packages/core/src/index.tsx b/packages/core/src/index.tsx
index 4a72a633..b1fd520b 100644
--- a/packages/core/src/index.tsx
+++ b/packages/core/src/index.tsx
@@ -16,6 +16,7 @@ export * as AlertDialog from "./alert-dialog";
export * as Breadcrumbs from "./breadcrumbs";
export * as Button from "./button";
//export * as Calendar from "./calendar";
+export * as Chip from "./chip";
export * as Checkbox from "./checkbox";
export * as Collapsible from "./collapsible";
export * as Combobox from "./combobox";