diff --git a/docs/guide/buttonGroup/examples/ButtonGroupBasicExample.vue b/docs/guide/buttonGroup/examples/ButtonGroupBasicExample.vue
index cfb19d0..5c01da9 100644
--- a/docs/guide/buttonGroup/examples/ButtonGroupBasicExample.vue
+++ b/docs/guide/buttonGroup/examples/ButtonGroupBasicExample.vue
@@ -1,10 +1,12 @@
-
- hello world
- hello world
- hello world
- hello world
-
+
+
+ hello world
+ hello world
+ hello world
+ hello world
+
+
diff --git a/docs/guide/tabs/examples/TabsPillsExample.vue b/docs/guide/tabs/examples/TabsPillsExample.vue
new file mode 100644
index 0000000..9ed000e
--- /dev/null
+++ b/docs/guide/tabs/examples/TabsPillsExample.vue
@@ -0,0 +1,23 @@
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aspernatur debitis iste libero molestiae mollitia, optio sunt? A, consectetur distinctio, eaque harum iusto laudantium, molestiae nam odio officia pariatur vitae?
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores autem cupiditate, deleniti eligendi exercitationem magnam maiores, minus pariatur provident quasi qui quidem recusandae rem reprehenderit sapiente sequi sint soluta.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam animi aperiam assumenda consectetur, dolorem, dolores, ea eos ipsum itaque iure laudantium nostrum nulla numquam perspiciatis provident qui quod totam voluptatem.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto blanditiis cupiditate ea error eveniet hic impedit in labore maxime, minima mollitia nam sapiente sint tempora tempore vel velit veniam, voluptatem.
+
+
+
+
+
diff --git a/docs/guide/tabs/examples/TabsUnderlineExample.vue b/docs/guide/tabs/examples/TabsUnderlineExample.vue
new file mode 100644
index 0000000..942f0ae
--- /dev/null
+++ b/docs/guide/tabs/examples/TabsUnderlineExample.vue
@@ -0,0 +1,23 @@
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aspernatur debitis iste libero molestiae mollitia, optio sunt? A, consectetur distinctio, eaque harum iusto laudantium, molestiae nam odio officia pariatur vitae?
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores autem cupiditate, deleniti eligendi exercitationem magnam maiores, minus pariatur provident quasi qui quidem recusandae rem reprehenderit sapiente sequi sint soluta.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam animi aperiam assumenda consectetur, dolorem, dolores, ea eos ipsum itaque iure laudantium nostrum nulla numquam perspiciatis provident qui quod totam voluptatem.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto blanditiis cupiditate ea error eveniet hic impedit in labore maxime, minima mollitia nam sapiente sint tempora tempore vel velit veniam, voluptatem.
+
+
+
+
+
diff --git a/docs/guide/tabs/tabs.md b/docs/guide/tabs/tabs.md
new file mode 100644
index 0000000..f5ebd6f
--- /dev/null
+++ b/docs/guide/tabs/tabs.md
@@ -0,0 +1,116 @@
+
+
+## Prop - variant (default)
+
+```typescript
+export type TabsVariant = 'default' | 'underline' | 'pills'
+
+defineProps({
+ variant: {
+ type: String as PropType,
+ default: 'default',
+ },
+})
+```
+
+
+
+
+```vue
+
+
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+
+```
+
+## Prop - variant (underline)
+
+
+
+```vue
+
+
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+
+```
+
+## Prop - variant (pills)
+
+
+
+```vue
+
+
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+ Lorem...
+
+
+
+```
+
+## Prop - directive
+
+Use this props if you want to control which directive to use for rendering every tab content
+
+```typescript
+export type TabsVariant = 'default' | 'underline' | 'pills'
+
+defineProps({
+ directive: {
+ type: String as PropType<'if' | 'show'>,
+ default: 'if',
+ },
+})
+```
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 07c740f..cda5ba2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2357,6 +2357,12 @@
"postcss-selector-parser": "^6.0.6"
}
},
+ "postcss-prefix-selector": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.0.tgz",
+ "integrity": "sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==",
+ "dev": true
+ },
"postcss-selector-parser": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
diff --git a/package.json b/package.json
index 53ef14b..a7a7857 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,8 @@
"eslint-plugin-vue": "^9.1.1",
"flowbite": "^1.4.2",
"jsdom": "^20.0.0",
- "postcss": "^8.4.6",
+ "postcss": "^8.4.14",
+ "postcss-prefix-selector": "^1.16.0",
"prettier": "^2.3.2",
"tailwindcss": "^3.1.4",
"typescript": "^4.7.3",
@@ -53,10 +54,5 @@
"vitest": "^0.16.0",
"vue-eslint-parser": "^9.0.3",
"vue-tsc": "^0.38.2"
- },
- "postcss": {
- "plugins": {
- "tailwindcss": {}
- }
}
}
diff --git a/src/components/Alert/Alert.vue b/src/components/Alert/Alert.vue
new file mode 100644
index 0000000..7921ba5
--- /dev/null
+++ b/src/components/Alert/Alert.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+ {{ title }}
+
+
+ Dismiss
+
+
+
+
+
+
+
+
+
+
+ Dismiss
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/Alert/useAlertClasses.ts b/src/components/Alert/useAlertClasses.ts
new file mode 100644
index 0000000..d087acb
--- /dev/null
+++ b/src/components/Alert/useAlertClasses.ts
@@ -0,0 +1,106 @@
+import type { AlertType } from './Alert.vue'
+import { computed } from 'vue'
+import type { Ref } from 'vue'
+import classNames from 'classnames'
+
+const defaultAlertClasses = 'p-4 text-sm'
+
+const alertTextClasses: Record = {
+ danger: 'text-red-700 dark:text-red-800',
+ dark: 'text-gray-700 dark:text-gray-300',
+ info: 'text-blue-700 dark:text-blue-800',
+ success: 'text-green-700 dark:text-green-800',
+ warning: 'text-yellow-700 dark:text-yellow-800',
+}
+
+const alertTypeClasses: Record = {
+ danger: 'bg-red-100 dark:bg-red-200',
+ dark: 'bg-gray-100 dark:bg-gray-700',
+ info: 'bg-blue-100 dark:bg-blue-200',
+ success: 'bg-green-100 dark:bg-green-200',
+ warning: 'bg-yellow-100 dark:bg-yellow-200',
+}
+
+const alertBorderClasses: Record = {
+ danger: 'border-t-4 border-red-500',
+ dark: 'border-t-4 border-gray-500',
+ info: 'border-t-4 border-blue-500',
+ success: 'border-t-4 border-green-500',
+ warning: 'border-t-4 border-yellow-500',
+}
+
+
+const defaultCloseButtonClasses = 'ml-auto -mx-1.5 -my-1.5 rounded-lg focus:ring-2 p-1.5 inline-flex h-8 w-8'
+
+const closeButtonClasses: Record = {
+ danger: 'hover:bg-red-200 dark:hover:bg-red-300 focus:ring-red-400 bg-red-100 dark:bg-red-200 text-red-500',
+ dark: 'dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-white hover:bg-gray-200 focus:ring-gray-400 bg-gray-100 text-gray-500',
+ info: 'hover:bg-blue-200 dark:hover:bg-blue-300 focus:ring-blue-400 bg-blue-100 dark:bg-blue-200 text-blue-500',
+ success: 'bg-green-100 dark:bg-green-200 text-green-500 focus:ring-green-400 hover:bg-green-200 dark:hover:bg-green-300',
+ warning: 'focus:ring-yellow-400 hover:bg-yellow-200 dark:hover:bg-yellow-300 bg-yellow-100 dark:bg-yellow-200 text-yellow-500',
+}
+
+export type UseAlertClassesProps = {
+ type: Ref
+ border: Ref
+ icon: Ref
+ inline: Ref
+ title: Ref
+}
+
+export function useAlertClasses(props: UseAlertClassesProps): {
+ alertClasses: Ref,
+ textClasses: Ref,
+ closeClasses: Ref,
+ contentClasses: Ref,
+ titleClasses: Ref,
+} {
+
+ const alertClasses = computed(() => {
+ return classNames(
+ defaultAlertClasses,
+ alertTypeClasses[props.type.value],
+ textClasses.value,
+ props.border.value ? alertBorderClasses[props.type.value] : 'rounded-lg', // rounded only if no border
+ props.inline.value ? 'flex' : '',
+ )
+ })
+
+ const textClasses = computed(() => {
+ return classNames(
+ alertTextClasses[props.type.value],
+ )
+ })
+
+ const closeClasses = computed(() => {
+ return classNames(
+ defaultCloseButtonClasses,
+ closeButtonClasses[props.type.value],
+ )
+ })
+
+ const contentClasses = computed(() => {
+ if(!props.inline.value) return classNames('mt-2 mb-4')
+ if(!props.icon.value && !props.title.value) return ''
+ return classNames(!props.title.value ? 'ml-3' : 'ml-1')
+ })
+
+ const titleClasses = computed(() => {
+ if(!props.icon.value || !props.inline.value) return classNames(
+ 'font-medium',
+ !props.inline.value ? 'text-lg ml-2' : '',
+ )
+ return classNames(
+ 'font-medium ml-3',
+ !props.inline.value ? 'text-lg' : '',
+ )
+ })
+
+ return {
+ alertClasses,
+ textClasses,
+ closeClasses,
+ contentClasses,
+ titleClasses,
+ }
+}
\ No newline at end of file
diff --git a/src/components/Button/Button.vue b/src/components/Button/Button.vue
index fd743f2..bb85e4a 100644
--- a/src/components/Button/Button.vue
+++ b/src/components/Button/Button.vue
@@ -28,7 +28,7 @@