{
props.class,
)}
classList={{
+ // eslint-disable-next-line tailwindcss/no-custom-classname
[cx("!border !border-semantic-1 !outline-semantic-1")]: !!props.error,
}}
aria-invalid={props.error}
diff --git a/pkgs/clan-app/ui/src/components/v2/Button/Button.css b/pkgs/clan-app/ui/src/components/v2/Button/Button.css
new file mode 100644
index 000000000..7e60712c5
--- /dev/null
+++ b/pkgs/clan-app/ui/src/components/v2/Button/Button.css
@@ -0,0 +1,134 @@
+.button {
+ @apply flex gap-2 shrink-0 items-center justify-center;
+ @apply px-4 py-2;
+
+ height: theme(height.9);
+ border-radius: 3px;
+
+ /* Add transition for smooth width animation */
+ transition: width 0.5s ease 0.1s;
+
+ &.s {
+ @apply px-3 py-1.5;
+ height: theme(height.7);
+ border-radius: 2px;
+
+ &:has(> .icon-start):has(> .label) {
+ @apply pl-2;
+ }
+
+ &:has(> .icon-end):has(> .label) {
+ @apply pr-2;
+ }
+ }
+
+ &.primary {
+ @apply bg-inv-acc-4 fg-inv-1;
+ @apply border border-solid border-inv-4;
+ @apply shadow-button-primary;
+
+ &.ghost {
+ @apply bg-transparent border-none shadow-none;
+ }
+
+ &:hover {
+ @apply bg-inv-acc-3 border-solid shadow-button-primary-hover;
+ border-color: theme(backgroundColor.secondary.700);
+ }
+
+ &:active {
+ @apply bg-inv-acc-4 border-solid border-inv-3 shadow-button-primary-active;
+ }
+
+ &:focus-visible {
+ @apply bg-inv-acc-4 border-solid border-inv-3 shadow-button-primary-focus;
+ }
+
+ &:disabled {
+ @apply bg-def-acc-3 border-solid border-def-3 fg-def-3 shadow-none;
+ }
+
+ & > .icon {
+ @apply fg-inv-1;
+ }
+ }
+
+ &.secondary {
+ @apply bg-def-acc-2 fg-def-1;
+ @apply border border-solid border-inv-2;
+ @apply shadow-button-secondary;
+
+ &.ghost {
+ @apply bg-transparent border-none shadow-none;
+ }
+
+ &:hover {
+ @apply bg-def-acc-3 border-solid shadow-button-secondary-hover;
+ border-color: theme(backgroundColor.secondary.700);
+ }
+
+ &:focus-visible {
+ @apply bg-def-acc-3 border-solid border-inv-3 shadow-button-secondary-focus;
+ }
+
+ &:active {
+ @apply bg-def-acc-3 border-solid border-inv-4 shadow-button-secondary-active;
+ }
+
+ &:disabled {
+ @apply bg-def-2 border-solid border-def-2 fg-def-3 shadow-none;
+ }
+
+ & > .icon {
+ @apply fg-def-1;
+
+ &.icon-loading {
+ color: #0051ff;
+ }
+ }
+ }
+
+ &.icon {
+ @apply p-2;
+ }
+
+ &:has(> .icon-start):has(> .label) {
+ @apply pl-3.5;
+ }
+
+ &:has(> .icon-end):has(> .label) {
+ @apply pr-3.5;
+ }
+
+ & > div.loader {
+ @apply w-0 opacity-0;
+ @apply top-0 left-0 -mr-2;
+ transition: all 0.5s ease;
+ }
+
+ &.loading {
+ @apply cursor-wait;
+
+ & > div.loader {
+ @apply w-4 opacity-100;
+ margin-right: revert;
+ transition: all 0.5s ease;
+ }
+ }
+}
+
+/* button group */
+.button-group .button:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.button-group .button:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.button-group .button:last-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
diff --git a/pkgs/clan-app/ui/src/components/v2/Button/Button.mdx b/pkgs/clan-app/ui/src/components/v2/Button/Button.mdx
new file mode 100644
index 000000000..9ecbb35a7
--- /dev/null
+++ b/pkgs/clan-app/ui/src/components/v2/Button/Button.mdx
@@ -0,0 +1,43 @@
+import { DocsStory, Meta, Canvas } from "@storybook/blocks";
+
+import * as ButtonStories from "./Button.stories";
+
+
+
+# Button
+
+Buttons have a simple hierarchy, `primary` or `secondary`, and two sizes, `default` and `s`.
+
+A `Button` can also have a label with a `startIcon`, an `endIcon` or both:
+
+```tsx
+