feat: tabs component

This commit is contained in:
Alexandr
2022-07-05 19:55:18 +03:00
parent 3c342e4473
commit 702088f165
7 changed files with 212 additions and 19 deletions

View File

@@ -1,24 +1,23 @@
<template> <template>
<div class="vp-raw"> <div class="vp-raw">
<tabs v-model="activeTab"> <tabs v-model="activeTab" class="p-5">
<tab name="first" title="Проверка"> <tab name="first" title="First">
Проверка Lorem ipsum dolor sit amet, consectetur adipisicing elit. Explicabo, id, nisi? Enim excepturi id minus molestias quaerat qui rem repudiandae sed tempore ullam voluptate, voluptatum. Consequuntur illum possimus tempora totam.
</tab> </tab>
<tab name="second" title="Проверка1"> <tab name="second" title="Second">
Проверка 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda consectetur expedita explicabo facere facilis fugit illo laboriosam minus molestias nulla placeat porro quaerat, quo repellat sapiente similique temporibus voluptate. Nemo!
</tab> </tab>
<tab name="third" title="Проверка2"> <tab name="third" title="Third">
Проверка 3 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias assumenda consequatur, dicta eius eos excepturi hic magnam maxime molestias nisi perferendis provident quia. Aliquam consequatur esse ex sit velit.
</tab> </tab>
<tab name="fourth" title="Проверка3" :disabled="true"> <tab name="fourth" title="Fourth" :disabled="true">
Проверка 4 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi deleniti dolores ea eligendi quis, ratione repellat temporibus veniam veritatis voluptates. Distinctio enim eos illo incidunt ipsam provident, quaerat quia vel!
</tab> </tab>
</tabs> </tabs>
current tab: {{ activeTab }}
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { Tabs, Tab } from '../../../../src/index' import { Tabs, Tab } from '../../../../src/index'
const activeTab = ref('') const activeTab = ref('first')
</script> </script>

View File

@@ -0,0 +1,23 @@
<template>
<div class="vp-raw">
<tabs variant="pills" v-model="activeTab" class="p-5">
<tab name="first" title="First">
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?
</tab>
<tab name="second" title="Second">
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.
</tab>
<tab name="third" title="Third">
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.
</tab>
<tab name="fourth" title="Fourth" :disabled="true">
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.
</tab>
</tabs>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Tabs, Tab } from '../../../../src/index'
const activeTab = ref('first')
</script>

View File

@@ -0,0 +1,23 @@
<template>
<div class="vp-raw">
<tabs variant="underline" v-model="activeTab" class="p-5">
<tab name="first" title="First">
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?
</tab>
<tab name="second" title="Second">
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.
</tab>
<tab name="third" title="Third">
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.
</tab>
<tab name="fourth" title="Fourth" :disabled="true">
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.
</tab>
</tabs>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Tabs, Tab } from '../../../../src/index'
const activeTab = ref('first')
</script>

View File

@@ -1,5 +1,116 @@
<script setup> <script setup>
import TabsDefaultExample from './examples/TabsDefaultExample.vue'; import TabsDefaultExample from './examples/TabsDefaultExample.vue';
import TabsPillsExample from './examples/TabsPillsExample.vue';
import TabsUnderlineExample from './examples/TabsUnderlineExample.vue';
</script> </script>
<TabsDefaultExample /> ## Prop - variant (default)
```typescript
export type TabsVariant = 'default' | 'underline' | 'pills'
defineProps({
variant: {
type: String as PropType<TabsVariant>,
default: 'default',
},
})
```
<TabsDefaultExample />
```vue
<script setup>
import { ref } from 'vue'
import { Tabs, Tab } from 'flowbite-vue'
const activeTab = ref('first')
</script>
<template>
<tabs v-model="activeTab" class="p-5"> <!-- class appends to content DIV for all tabs -->
<tab name="first" title="First">
Lorem...
</tab>
<tab name="second" title="Second">
Lorem...
</tab>
<tab name="third" title="Third">
Lorem...
</tab>
<tab name="fourth" title="Fourth" :disabled="true">
Lorem...
</tab>
</tabs>
</template>
```
## Prop - variant (underline)
<TabsUnderlineExample />
```vue
<script setup>
import { ref } from 'vue'
import { Tabs, Tab } from 'flowbite-vue'
const activeTab = ref('first')
</script>
<template>
<tabs variant="underline" v-model="activeTab" class="p-5"> <!-- class appends to content DIV for all tabs -->
<tab name="first" title="First">
Lorem...
</tab>
<tab name="second" title="Second">
Lorem...
</tab>
<tab name="third" title="Third">
Lorem...
</tab>
<tab name="fourth" title="Fourth" :disabled="true">
Lorem...
</tab>
</tabs>
</template>
```
## Prop - variant (pills)
<TabsPillsExample />
```vue
<script setup>
import { ref } from 'vue'
import { Tabs, Tab } from 'flowbite-vue'
const activeTab = ref('first')
</script>
<template>
<tabs variant="pills" v-model="activeTab" class="p-5"> <!-- class appends to content DIV for all tabs -->
<tab name="first" title="First">
Lorem...
</tab>
<tab name="second" title="Second">
Lorem...
</tab>
<tab name="third" title="Third">
Lorem...
</tab>
<tab name="fourth" title="Fourth" :disabled="true">
Lorem...
</tab>
</tabs>
</template>
```
## 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',
},
})
```

View File

@@ -12,19 +12,24 @@
/> />
</ul> </ul>
</div> </div>
<slot/> <div v-bind="$attrs">
<slot />
</div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { TAB_ACTIVATE_INJECTION_KEY, TAB_STYLE_INJECTION_KEY } from './config' import {
TAB_ACTIVATE_INJECTION_KEY,
TAB_ACTIVE_NAME_INJECTION_KEY,
TAB_STYLE_INJECTION_KEY,
TAB_VISIBILITY_DIRECTIVE_INJECTION_KEY,
} from './config'
import { useTabsClasses } from './useTabsClasses' import { useTabsClasses } from './useTabsClasses'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { computed, provide, useSlots } from 'vue' import { computed, provide, toRef, useSlots } from 'vue'
import { flatten } from '../../utils/flatten' import { flatten } from '../../utils/flatten'
import TabPane from './components/TabPane/TabPane.vue' import TabPane from './components/TabPane/TabPane.vue'
export type TabsVariant = 'default' | 'underline' | 'pills'
const props = defineProps({ const props = defineProps({
variant: { variant: {
type: String as PropType<TabsVariant>, type: String as PropType<TabsVariant>,
@@ -34,9 +39,12 @@ const props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
directive: {
type: String as PropType<'if' | 'show'>,
default: 'if',
},
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { ulClasses, divClasses } = useTabsClasses(props) const { ulClasses, divClasses } = useTabsClasses(props)
@@ -59,9 +67,21 @@ const modelValueRef = computed({
set: (value: string) => emit('update:modelValue', value), set: (value: string) => emit('update:modelValue', value),
}) })
provide(TAB_ACTIVE_NAME_INJECTION_KEY, modelValueRef)
provide(TAB_VISIBILITY_DIRECTIVE_INJECTION_KEY, toRef(props, 'directive'))
const onActivate = (value: string) => { const onActivate = (value: string) => {
modelValueRef.value = value modelValueRef.value = value
} }
provide(TAB_ACTIVATE_INJECTION_KEY, onActivate) provide(TAB_ACTIVATE_INJECTION_KEY, onActivate)
</script> </script>
<script lang="ts">
export default {
inheritAttrs: false,
}
export type TabsVariant = 'default' | 'underline' | 'pills'
</script>

View File

@@ -1,9 +1,21 @@
<template> <template>
<div> <div>
<slot /> <template v-if="directive === 'if'">
<div v-if="activeTab === name">
<slot/>
</div>
</template>
<template v-else-if="directive === 'show'">
<div v-show="activeTab === name">
<slot/>
</div>
</template>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { inject } from 'vue'
import { TAB_ACTIVE_NAME_INJECTION_KEY, TAB_VISIBILITY_DIRECTIVE_INJECTION_KEY } from '../../config'
defineProps({ defineProps({
name: { name: {
type: String, type: String,
@@ -18,6 +30,9 @@ defineProps({
default: false, default: false,
}, },
}) })
const activeTab = inject(TAB_ACTIVE_NAME_INJECTION_KEY, '')
const directive = inject(TAB_VISIBILITY_DIRECTIVE_INJECTION_KEY, 'if')
</script> </script>
<script lang="ts"> <script lang="ts">

View File

@@ -1,2 +1,4 @@
export const TAB_STYLE_INJECTION_KEY = 'flowbite-tab-style-injection' export const TAB_STYLE_INJECTION_KEY = 'flowbite-tab-style-injection'
export const TAB_ACTIVE_NAME_INJECTION_KEY = 'flowbite-tab-active-name-injection'
export const TAB_VISIBILITY_DIRECTIVE_INJECTION_KEY = 'flowbite-tab-visibility-directive-injection'
export const TAB_ACTIVATE_INJECTION_KEY = 'flowbite-tab-activate-func-injection' export const TAB_ACTIVATE_INJECTION_KEY = 'flowbite-tab-activate-func-injection'