Fixed #5621 - New Component: Tabs

pull/5677/head
mertsincan 2024-04-19 14:51:57 +01:00
parent 53168665d4
commit c80c3ad0ea
57 changed files with 3934 additions and 35 deletions

View File

@ -273,6 +273,10 @@
"name": "Stepper", "name": "Stepper",
"to": "/stepper" "to": "/stepper"
}, },
{
"name": "Tabs",
"to": "/tabs"
},
{ {
"name": "TabView", "name": "TabView",
"to": "/tabview" "to": "/tabview"

View File

@ -0,0 +1,33 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import TabStyle from 'primevue/tab/style';
export default {
name: 'BaseTab',
extends: BaseComponent,
props: {
value: {
type: String,
default: undefined
},
disabled: {
type: Boolean,
default: false
},
as: {
type: String,
default: 'BUTTON'
},
asChild: {
type: Boolean,
default: false
}
},
style: TabStyle,
provide() {
return {
$parentInstance: this
};
}
};
</script>

148
components/lib/tab/Tab.d.ts vendored Executable file
View File

@ -0,0 +1,148 @@
/**
*
* Tab is a helper component for Tabs component.
*
* [Live Demo](https://www.primevue.org/tabs/)
*
* @module tab
*
*/
import { VNode } from 'vue';
import { ComponentHooks } from '../basecomponent';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type TabPassThroughOptionType = TabPassThroughAttributes | ((options: TabPassThroughMethodOptions) => TabPassThroughAttributes | string) | string | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface TabPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: TabProps;
/**
* Defines current options.
*/
context: TabContext;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
/**
* Custom passthrough(pt) options.
* @see {@link TabProps.pt}
*/
export interface TabPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: TabPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
export interface TabPassThroughAttributes {
[key: string]: any;
}
/**
* Defines valid properties in Tab component.
*/
export interface TabProps {
/**
* Value of tab.
*/
value: string;
/**
* Whether the tab is disabled.
* @defaultValue false
*/
disabled?: boolean | undefined;
/**
* Use to change the HTML tag of root element.
* @defaultValue BUTTON
*/
as?: string | undefined;
/**
* When enabled, it changes the default rendered element for the one passed as a child element.
* @defaultValue false
*/
asChild?: boolean | undefined;
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {TabPassThroughOptions}
*/
pt?: PassThrough<TabPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
}
/**
* Defines current options in Tab component.
*/
export interface TabContext {
/**
* Whether the tab is active.
*/
active: boolean;
}
/**
* Defines valid slots in Tab slots.
*/
export interface TabSlots {
/**
* Custom content template.
*/
default(): VNode[];
}
export interface TabEmits {}
/**
* **PrimeVue - Tab**
*
* _Tab is a helper component for Tabs component._
*
* [Live Demo](https://www.primevue.org/tabs/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*
* @group Component
*
*/
declare class Tab extends ClassComponent<TabProps, TabSlots, TabEmits> {}
declare module 'vue' {
export interface GlobalComponents {
Tab: GlobalComponentConstructor<Tab>;
}
}
export default Tab;

166
components/lib/tab/Tab.vue Normal file
View File

@ -0,0 +1,166 @@
<template>
<component v-if="!asChild" :is="as" v-ripple :class="cx('root')" @click="onClick" v-bind="attrs">
<slot></slot>
</component>
<slot v-else :class="cx('root')" :active="active" :a11yAttrs="a11yAttrs" :onClick="onClick"></slot>
</template>
<script>
import Ripple from 'primevue/ripple';
import { DomHandler, ObjectUtils } from 'primevue/utils';
import { mergeProps } from 'vue';
import BaseTab from './BaseTab.vue';
export default {
name: 'Tab',
extends: BaseTab,
inheritAttrs: false,
inject: ['$pcTabs', '$pcTabList'],
methods: {
onFocus() {
this.$pcTabs.selectOnFocus && this.changeActiveValue();
},
onClick() {
this.changeActiveValue();
},
onKeydown(event) {
switch (event.code) {
case 'ArrowRight':
this.onArrowRightKey(event);
break;
case 'ArrowLeft':
this.onArrowLeftKey(event);
break;
case 'Home':
this.onHomeKey(event);
break;
case 'End':
this.onEndKey(event);
break;
case 'PageDown':
this.onPageDownKey(event);
break;
case 'PageUp':
this.onPageUpKey(event);
break;
case 'Enter':
case 'NumpadEnter':
case 'Space':
this.onEnterKey(event);
break;
default:
break;
}
},
onArrowRightKey(event) {
const nextTab = this.findNextTab(event.currentTarget);
nextTab ? this.changeFocusedTab(event, nextTab) : this.onHomeKey(event);
event.preventDefault();
},
onArrowLeftKey(event) {
const prevTab = this.findPrevTab(event.currentTarget);
prevTab ? this.changeFocusedTab(event, prevTab) : this.onEndKey(event);
event.preventDefault();
},
onHomeKey(event) {
const firstTab = this.findFirstTab();
this.changeFocusedTab(event, firstTab);
event.preventDefault();
},
onEndKey(event) {
const lastTab = this.findLastTab();
this.changeFocusedTab(event, lastTab);
event.preventDefault();
},
onPageDownKey(event) {
this.scrollInView(this.findLastTab());
event.preventDefault();
},
onPageUpKey(event) {
this.scrollInView(this.findFirstTab());
event.preventDefault();
},
onEnterKey() {
this.changeActiveValue();
},
findNextTab(tabElement, selfCheck = false) {
const element = selfCheck ? tabElement : tabElement.nextElementSibling;
return element ? (DomHandler.getAttribute(element, 'data-p-disabled') || DomHandler.getAttribute(element, 'data-pc-section') === 'inkbar' ? this.findNextTab(element) : DomHandler.findSingle(element, '[data-pc-name="tab"]')) : null;
},
findPrevTab(tabElement, selfCheck = false) {
const element = selfCheck ? tabElement : tabElement.previousElementSibling;
return element ? (DomHandler.getAttribute(element, 'data-p-disabled') || DomHandler.getAttribute(element, 'data-pc-section') === 'inkbar' ? this.findPrevTab(element) : DomHandler.findSingle(element, '[data-pc-name="tab"]')) : null;
},
findFirstTab() {
return this.findNextTab(this.$pcTabList.$refs.content.firstElementChild, true);
},
findLastTab() {
return this.findPrevTab(this.$pcTabList.$refs.content.lastElementChild, true);
},
changeActiveValue() {
this.$pcTabs.updateValue(this.value);
},
changeFocusedTab(event, element) {
DomHandler.focus(element);
this.scrollInView(element);
},
scrollInView(element) {
element?.scrollIntoView?.({ block: 'nearest' });
}
},
computed: {
active() {
return ObjectUtils.equals(this.$pcTabs?.d_value, this.value);
},
id() {
return `${this.$pcTabs?.id}_tab_${this.value}`;
},
ariaControls() {
return `${this.$pcTabs?.id}_tabpanel_${this.value}`;
},
attrs() {
return mergeProps(this.asAttrs, this.a11yAttrs, this.ptmi('root', this.ptParams));
},
asAttrs() {
return this.as === 'BUTTON' ? { type: 'button', disabled: this.disabled } : undefined;
},
a11yAttrs() {
return {
id: this.id,
tabindex: this.active ? this.$pcTabs.tabindex : -1,
role: 'tab',
'aria-selected': this.active,
'aria-controls': this.ariaControls,
'data-pc-name': 'tab',
'data-p-disabled': this.disabled,
'data-p-active': this.active,
onFocus: this.onFocus,
onKeydown: this.onKeydown
};
},
ptParams() {
return {
context: {
active: this.active
}
};
}
},
directives: {
ripple: Ripple
}
};
</script>

View File

@ -0,0 +1,9 @@
{
"main": "./tab.cjs.js",
"module": "./tab.esm.js",
"unpkg": "./tab.min.js",
"types": "./Tab.d.ts",
"browser": {
"./sfc": "./Tab.vue"
}
}

View File

@ -0,0 +1,3 @@
import { BaseStyle } from '../../base/style';
export interface TabStyle extends BaseStyle {}

View File

@ -0,0 +1,16 @@
import BaseStyle from 'primevue/base/style';
const classes = {
root: ({ instance, props }) => [
'p-tab',
{
'p-active': instance.active,
'p-disabled': props.disabled
}
]
};
export default BaseStyle.extend({
name: 'tab',
classes
});

View File

@ -0,0 +1,6 @@
{
"main": "./tabstyle.cjs.js",
"module": "./tabstyle.esm.js",
"unpkg": "./tabstyle.min.js",
"types": "./TabStyle.d.ts"
}

View File

@ -0,0 +1,17 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import TabListStyle from 'primevue/tablist/style';
export default {
name: 'BaseTabList',
extends: BaseComponent,
props: {},
style: TabListStyle,
provide() {
return {
$pcTabList: this,
$parentInstance: this
};
}
};
</script>

142
components/lib/tablist/TabList.d.ts vendored Executable file
View File

@ -0,0 +1,142 @@
/**
*
* TabList is a helper component for Tabs component.
*
* [Live Demo](https://www.primevue.org/tabs/)
*
* @module tablist
*
*/
import { VNode } from 'vue';
import { ComponentHooks } from '../basecomponent';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type TabListPassThroughOptionType = TabListPassThroughAttributes | ((options: TabListPassThroughMethodOptions) => TabListPassThroughAttributes | string) | string | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface TabListPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: TabListProps;
/**
* Defines current options.
*/
context: TabListContext;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
/**
* Custom passthrough(pt) options.
* @see {@link TabListProps.pt}
*/
export interface TabListPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: TabListPassThroughOptionType;
/**
* Used to pass attributes to the previous button component.
*/
previousButton?: TabListPassThroughOptionType;
/**
* Used to pass attributes to the next button component.
*/
nextButton?: TabListPassThroughOptionType;
/**
* Used to pass attributes to the list's DOM element.
*/
content?: TabListPassThroughOptionType;
/**
* Used to pass attributes to the inkbar's DOM element.
*/
inkbar?: TabListPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
export interface TabListPassThroughAttributes {
[key: string]: any;
}
/**
* Defines valid properties in TabList component.
*/
export interface TabListProps {
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {TabListPassThroughOptions}
*/
pt?: PassThrough<TabListPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
}
/**
* Defines current options in TabList component.
*/
export interface TabListContext {
[key: string]: any;
}
/**
* Defines valid slots in TabList slots.
*/
export interface TabListSlots {
/**
* Custom content template.
*/
default(): VNode[];
}
export interface TabListEmits {}
/**
* **PrimeVue - TabList**
*
* _TabList is a helper component for Tabs component._
*
* [Live Demo](https://www.primevue.org/tabs/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*
* @group Component
*
*/
declare class TabList extends ClassComponent<TabListProps, TabListSlots, TabListEmits> {}
declare module 'vue' {
export interface GlobalComponents {
TabList: GlobalComponentConstructor<TabList>;
}
}
export default TabList;

View File

@ -0,0 +1,159 @@
<template>
<div ref="list" :class="cx('root')" v-bind="ptmi('root')">
<Button
v-if="showNavigators && isPrevButtonEnabled"
ref="prevButton"
:class="cx('previousButton')"
:aria-label="prevButtonAriaLabel"
:unstyled="$pcTabs.unstyled"
:tabindex="$pcTabs.tabindex"
@click="onPrevButtonClick"
v-bind="$pcTabs.previousButtonProps"
:pt="ptm('previousButton')"
data-pc-group-section="navigator"
>
<template #icon="slotProps">
<component :is="templates.previousicon || 'ChevronLeftIcon'" aria-hidden="true" :class="slotProps.icon" v-bind="ptm('previousButton.icon')" />
</template>
</Button>
<div ref="content" :class="cx('content')" role="tablist" :aria-orientation="$pcTabs.orientation" @scroll="onScroll" v-bind="ptm('content')">
<slot></slot>
<span ref="inkbar" :class="cx('inkbar')" role="presentation" aria-hidden="true" v-bind="ptm('inkbar')"></span>
</div>
<Button
v-if="showNavigators && isNextButtonEnabled"
ref="nextButton"
:class="cx('nextButton')"
:aria-label="nextButtonAriaLabel"
:unstyled="$pcTabs.unstyled"
:tabindex="$pcTabs.tabindex"
@click="onNextButtonClick"
v-bind="$pcTabs.nextButtonProps"
:pt="ptm('nextButton')"
data-pc-group-section="navigator"
>
<template #icon="slotProps">
<component :is="templates.nexticon || 'ChevronRightIcon'" aria-hidden="true" :class="slotProps.icon" v-bind="ptm('nextButton.icon')" />
</template>
</Button>
</div>
</template>
<script>
import Button from 'primevue/button';
import ChevronLeftIcon from 'primevue/icons/chevronleft';
import ChevronRightIcon from 'primevue/icons/chevronright';
import { DomHandler } from 'primevue/utils';
import BaseTabList from './BaseTabList.vue';
export default {
name: 'TabList',
extends: BaseTabList,
inheritAttrs: false,
inject: ['$pcTabs'],
data() {
return {
isPrevButtonEnabled: false,
isNextButtonEnabled: true
};
},
resizeObserver: undefined,
watch: {
showNavigators(newValue) {
newValue ? this.bindResizeObserver() : this.unbindResizeObserver();
},
activeValue: {
flush: 'post',
handler() {
this.updateInkBar();
}
}
},
mounted() {
this.updateInkBar();
if (this.showNavigators) {
this.updateButtonState();
this.bindResizeObserver();
}
},
updated() {
this.showNavigators && this.updateButtonState();
},
beforeUnmount() {
this.unbindResizeObserver();
},
methods: {
onScroll(event) {
this.showNavigators && this.updateButtonState();
event.preventDefault();
},
onPrevButtonClick() {
const content = this.$refs.content;
const width = DomHandler.getWidth(content);
const pos = content.scrollLeft - width;
content.scrollLeft = pos <= 0 ? 0 : pos;
},
onNextButtonClick() {
const content = this.$refs.content;
const width = DomHandler.getWidth(content) - this.getVisibleButtonWidths();
const pos = content.scrollLeft + width;
const lastPos = content.scrollWidth - width;
content.scrollLeft = pos >= lastPos ? lastPos : pos;
},
bindResizeObserver() {
this.resizeObserver = new ResizeObserver(() => this.updateButtonState());
this.resizeObserver.observe(this.$refs.list);
},
unbindResizeObserver() {
this.resizeObserver?.unobserve(this.$refs.list);
this.resizeObserver = undefined;
},
updateInkBar() {
const { content, inkbar } = this.$refs;
const activeTab = DomHandler.findSingle(content, '[data-pc-name="tab"][data-p-active="true"]');
inkbar.style.width = DomHandler.getOuterWidth(activeTab) + 'px';
inkbar.style.left = DomHandler.getOffset(activeTab).left - DomHandler.getOffset(content).left + 'px';
},
updateButtonState() {
const { list, content } = this.$refs;
const { scrollLeft, scrollWidth, offsetWidth } = content;
const width = DomHandler.getWidth(content);
this.isPrevButtonEnabled = scrollLeft !== 0;
this.isNextButtonEnabled = list.offsetWidth >= offsetWidth && parseInt(scrollLeft) !== scrollWidth - width;
},
getVisibleButtonWidths() {
const { prevBtn, nextBtn } = this.$refs;
return [prevBtn, nextBtn].reduce((acc, el) => (el ? acc + DomHandler.getWidth(el) : acc), 0);
}
},
computed: {
templates() {
return this.$pcTabs.$slots;
},
activeValue() {
return this.$pcTabs.d_value;
},
showNavigators() {
return this.$pcTabs.scrollable && this.$pcTabs.showNavigators;
},
prevButtonAriaLabel() {
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.previous : undefined;
},
nextButtonAriaLabel() {
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.next : undefined;
}
},
components: {
Button,
ChevronLeftIcon,
ChevronRightIcon
}
};
</script>

View File

@ -0,0 +1,9 @@
{
"main": "./tab.cjs.js",
"module": "./tab.esm.js",
"unpkg": "./tab.min.js",
"types": "./Tab.d.ts",
"browser": {
"./sfc": "./Tab.vue"
}
}

View File

@ -0,0 +1,3 @@
import { BaseStyle } from '../../base/style';
export interface TabListStyle extends BaseStyle {}

View File

@ -0,0 +1,19 @@
import BaseStyle from 'primevue/base/style';
const classes = {
root: 'p-tablist',
content: ({ instance }) => [
'p-tablist-content',
{
'p-tablist-scroll-container': instance.$pcTabs.scrollable
}
],
inkbar: 'p-tablist-ink-bar',
previousButton: 'p-tablist-prev-button p-tablist-navigator',
nextButton: 'p-tablist-next-button p-tablist-navigator'
};
export default BaseStyle.extend({
name: 'tablist',
classes
});

View File

@ -0,0 +1,6 @@
{
"main": "./tabliststyle.cjs.js",
"module": "./tabliststyle.esm.js",
"unpkg": "./tabliststyle.min.js",
"types": "./TabListStyle.d.ts"
}

View File

@ -6,6 +6,20 @@ export default {
name: 'BaseTabPanel', name: 'BaseTabPanel',
extends: BaseComponent, extends: BaseComponent,
props: { props: {
// in Tabs
value: {
type: String,
default: undefined
},
as: {
type: String,
default: 'DIV'
},
asChild: {
type: Boolean,
default: false
},
// in TabView
header: null, header: null,
headerStyle: null, headerStyle: null,
headerClass: null, headerClass: null,

View File

@ -1,8 +1,8 @@
/** /**
* *
* TabPanel is a helper component for TabPanel component. * TabPanel is a helper component for Tabs component.
* *
* [Live Demo](https://www.primevue.org/tabview/) * [Live Demo](https://www.primevue.org/tabs/)
* *
* @module tabpanel * @module tabpanel
* *
@ -55,18 +55,22 @@ export interface TabPanelPassThroughOptions {
root?: TabPanelPassThroughOptionType; root?: TabPanelPassThroughOptionType;
/** /**
* Used to pass attributes to the header's DOM element. * Used to pass attributes to the header's DOM element.
* @deprecated since v4. Only supported by TabView.
*/ */
header?: TabPanelPassThroughOptionType; header?: TabPanelPassThroughOptionType;
/** /**
* Used to pass attributes to the header action's DOM element. * Used to pass attributes to the header action's DOM element.
* @deprecated since v4. Only supported by TabView.
*/ */
headerAction?: TabPanelPassThroughOptionType; headerAction?: TabPanelPassThroughOptionType;
/** /**
* Used to pass attributes to the title's DOM element. * Used to pass attributes to the title's DOM element.
* @deprecated since v4. Only supported by TabView.
*/ */
headerTitle?: TabPanelPassThroughOptionType; headerTitle?: TabPanelPassThroughOptionType;
/** /**
* Used to pass attributes to the list's DOM element. * Used to pass attributes to the list's DOM element.
* @deprecated since v4. Only supported by TabView.
*/ */
content?: TabPanelPassThroughOptionType; content?: TabPanelPassThroughOptionType;
/** /**
@ -84,44 +88,64 @@ export interface TabPanelPassThroughAttributes {
* Defines valid properties in TabPanel component. * Defines valid properties in TabPanel component.
*/ */
export interface TabPanelProps { export interface TabPanelProps {
/**
* Value of tabpanel.
*/
value: string;
/**
* Use to change the HTML tag of root element.
* @defaultValue DIV
*/
as?: string | undefined;
/**
* When enabled, it changes the default rendered element for the one passed as a child element.
* @defaultValue false
*/
asChild?: boolean | undefined;
/** /**
* Orientation of tab headers. * Orientation of tab headers.
* @deprecated since v4. Only supported by TabView.
*/ */
header?: string | undefined; header?: string | undefined;
/** /**
* Inline style of the tab header. * Inline style of the tab header.
* @deprecated since v4. Only supported by TabView.
*/ */
headerStyle?: any; headerStyle?: any;
/** /**
* Style class of the tab header. * Style class of the tab header.
* @deprecated since v4. Only supported by TabView.
*/ */
headerClass?: any; headerClass?: any;
/** /**
* Used to pass all properties of the HTMLLiElement to the tab header. * Used to pass all properties of the HTMLLiElement to the tab header.
* @deprecated since v3.26.0. Use 'pt' property instead. * @deprecated since v4. Only supported by TabView.
*/ */
headerProps?: LiHTMLAttributes | undefined; headerProps?: LiHTMLAttributes | undefined;
/** /**
* Used to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header. * Used to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header.
* @deprecated since v3.26.0. Use 'pt' property instead. * @deprecated since v4. Only supported by TabView.
*/ */
headerActionProps?: AnchorHTMLAttributes | undefined; headerActionProps?: AnchorHTMLAttributes | undefined;
/** /**
* Inline style of the tab content. * Inline style of the tab content.
* @deprecated since v4. Only supported by TabView.
*/ */
contentStyle?: any; contentStyle?: any;
/** /**
* Style class of the tab content. * Style class of the tab content.
* @deprecated since v4. Only supported by TabView.
*/ */
contentClass?: any; contentClass?: any;
/** /**
* Used to pass all properties of the HTMLDivElement to the tab content. * Used to pass all properties of the HTMLDivElement to the tab content.
* @deprecated since v3.26.0. Use 'pt' property instead. * @deprecated since v4. Only supported by TabView.
*/ */
contentProps?: HTMLAttributes | undefined; contentProps?: HTMLAttributes | undefined;
/** /**
* Whether the tab is disabled. * Whether the tab is disabled.
* @defaultValue false * @defaultValue false
* @deprecated since v4. Only supported by TabView.
*/ */
disabled?: boolean | undefined; disabled?: boolean | undefined;
/** /**
@ -146,18 +170,22 @@ export interface TabPanelProps {
export interface TabPanelContext { export interface TabPanelContext {
/** /**
* Current index of the tab. * Current index of the tab.
* @deprecated since v4. Only supported by TabView.
*/ */
index: number; index: number;
/** /**
* Count of tabs * Count of tabs
* @deprecated since v4. Only supported by TabView.
*/ */
count: number; count: number;
/** /**
* Whether the tab is first. * Whether the tab is first.
* @deprecated since v4. Only supported by TabView.
*/ */
first: boolean; first: boolean;
/** /**
* Whether the tab is last. * Whether the tab is last.
* @deprecated since v4. Only supported by TabView.
*/ */
last: boolean; last: boolean;
/** /**
@ -176,6 +204,7 @@ export interface TabPanelSlots {
default(): VNode[]; default(): VNode[];
/** /**
* Custom header template. * Custom header template.
* @deprecated since v4. Only supported by TabView.
*/ */
header(): VNode[]; header(): VNode[];
} }
@ -185,9 +214,9 @@ export interface TabPanelEmits {}
/** /**
* **PrimeVue - TabPanel** * **PrimeVue - TabPanel**
* *
* _TabPanel is a helper component for TabView component._ * _TabPanel is a helper component for Tabs component._
* *
* [Live Demo](https://www.primevue.org/tabview/) * [Live Demo](https://www.primevue.org/tabs/)
* --- --- * --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png) * ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
* *

View File

@ -1,12 +1,56 @@
<template> <template>
<slot v-if="!$pcTabs"></slot>
<template v-else>
<template v-if="!asChild">
<component v-if="$pcTabs?.lazy ? active : true" v-show="$pcTabs?.lazy ? true : active" :is="as" :class="cx('root')" v-bind="attrs">
<slot></slot> <slot></slot>
</component>
</template>
<slot v-else :class="cx('root')" :active="active" :a11yAttrs="a11yAttrs"></slot>
</template>
</template> </template>
<script> <script>
import { ObjectUtils } from 'primevue/utils';
import { mergeProps } from 'vue';
import BaseTabPanel from './BaseTabPanel.vue'; import BaseTabPanel from './BaseTabPanel.vue';
export default { export default {
name: 'TabPanel', name: 'TabPanel',
extends: BaseTabPanel extends: BaseTabPanel,
inheritAttrs: false,
inject: ['$pcTabs'],
computed: {
active() {
return ObjectUtils.equals(this.$pcTabs?.d_value, this.value);
},
id() {
return `${this.$pcTabs?.id}_tabpanel_${this.value}`;
},
ariaLabelledby() {
return `${this.$pcTabs?.id}_tab_${this.value}`;
},
attrs() {
return mergeProps(this.a11yAttrs, this.ptmi('root', this.ptParams));
},
a11yAttrs() {
return {
id: this.id,
tabindex: this.$pcTabs?.tabindex,
role: 'tabpanel',
'aria-labelledby': this.ariaLabelledby,
'data-pc-name': 'tabpanel',
'data-p-active': this.active
};
},
ptParams() {
return {
context: {
active: this.active
}
};
}
}
}; };
</script> </script>

View File

@ -1,5 +1,15 @@
import BaseStyle from 'primevue/base/style'; import BaseStyle from 'primevue/base/style';
const classes = {
root: ({ instance }) => [
'p-tabpanel',
{
'p-active': instance.active
}
]
};
export default BaseStyle.extend({ export default BaseStyle.extend({
name: 'tabpanel' name: 'tabpanel',
classes
}); });

View File

@ -0,0 +1,16 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import TabPanelsStyle from 'primevue/tabpanels/style';
export default {
name: 'BaseTabPanels',
extends: BaseComponent,
props: {},
style: TabPanelsStyle,
provide() {
return {
$parentInstance: this
};
}
};
</script>

126
components/lib/tabpanels/TabPanels.d.ts vendored Executable file
View File

@ -0,0 +1,126 @@
/**
*
* TabPanels is a helper component for Tabs component.
*
* [Live Demo](https://www.primevue.org/tabview/)
*
* @module tabpanels
*
*/
import { VNode } from 'vue';
import { ComponentHooks } from '../basecomponent';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type TabPanelsPassThroughOptionType = TabPanelsPassThroughAttributes | ((options: TabPanelsPassThroughMethodOptions) => TabPanelsPassThroughAttributes | string) | string | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface TabPanelsPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: TabPanelsProps;
/**
* Defines current options.
*/
context: TabPanelsContext;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
/**
* Custom passthrough(pt) options.
* @see {@link TabPanelsProps.pt}
*/
export interface TabPanelsPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: TabPanelsPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
export interface TabPanelsPassThroughAttributes {
[key: string]: any;
}
/**
* Defines valid properties in TabPanels component.
*/
export interface TabPanelsProps {
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {TabPanelsPassThroughOptions}
*/
pt?: PassThrough<TabPanelsPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
}
/**
* Defines current options in TabPanels component.
*/
export interface TabPanelsContext {
[key: string]: any;
}
/**
* Defines valid slots in TabPanels slots.
*/
export interface TabPanelsSlots {
/**
* Custom content template.
*/
default(): VNode[];
}
export interface TabPanelsEmits {}
/**
* **PrimeVue - TabPanels**
*
* _TabPanels is a helper component for Tabs component._
*
* [Live Demo](https://www.primevue.org/tabs/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*
* @group Component
*
*/
declare class TabPanels extends ClassComponent<TabPanelsProps, TabPanelsSlots, TabPanelsEmits> {}
declare module 'vue' {
export interface GlobalComponents {
TabPanels: GlobalComponentConstructor<TabPanels>;
}
}
export default TabPanels;

View File

@ -0,0 +1,15 @@
<template>
<div :class="cx('root')" role="presentation" v-bind="ptmi('root')">
<slot></slot>
</div>
</template>
<script>
import BaseTabPanels from './BaseTabPanels.vue';
export default {
name: 'TabPanels',
extends: BaseTabPanels,
inheritAttrs: false
};
</script>

View File

@ -0,0 +1,9 @@
{
"main": "./tabpanels.cjs.js",
"module": "./tabpanels.esm.js",
"unpkg": "./tabpanels.min.js",
"types": "./TabPanels.d.ts",
"browser": {
"./sfc": "./TabPanels.vue"
}
}

View File

@ -0,0 +1,3 @@
import { BaseStyle } from '../../base/style';
export interface TabPanelsStyle extends BaseStyle {}

View File

@ -0,0 +1,10 @@
import BaseStyle from 'primevue/base/style';
const classes = {
root: 'p-tabpanels'
};
export default BaseStyle.extend({
name: 'tabpanels',
classes
});

View File

@ -0,0 +1,6 @@
{
"main": "./tabpanelsstyle.cjs.js",
"module": "./tabpanelsstyle.esm.js",
"unpkg": "./tabpanelsstyle.min.js",
"types": "./TabPanelsStyle.d.ts"
}

View File

@ -0,0 +1,58 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import TabsStyle from 'primevue/tabs/style';
export default {
name: 'BaseTabs',
extends: BaseComponent,
props: {
value: {
type: String,
default: undefined
},
lazy: {
type: Boolean,
default: false
},
orientation: {
type: String,
default: 'horizontal'
},
scrollable: {
type: Boolean,
default: false
},
showNavigators: {
type: Boolean,
default: true
},
tabindex: {
type: Number,
default: 0
},
selectOnFocus: {
type: Boolean,
default: false
},
previousButtonProps: {
type: Object,
default: () => {
return { severity: 'secondary', text: true };
}
},
nextButtonProps: {
type: Object,
default: () => {
return { severity: 'secondary', text: true };
}
}
},
style: TabsStyle,
provide() {
return {
$pcTabs: this,
$parentInstance: this
};
}
};
</script>

202
components/lib/tabs/Tabs.d.ts vendored Normal file
View File

@ -0,0 +1,202 @@
/**
*
* Tabs facilitates seamless switching between different views.
*
* [Live Demo](https://www.primevue.org/tabs/)
*
* @module tabs
*
*/
import { VNode } from 'vue';
import { ComponentHooks } from '../basecomponent';
import { ButtonProps } from '../button';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type TabsPassThroughOptionType = TabsPassThroughAttributes | ((options: TabsPassThroughMethodOptions) => TabsPassThroughAttributes | string) | string | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface TabsPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: TabsProps;
/**
* Defines current inline state.
*/
state: TabsState;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
/**
* Custom passthrough(pt) options.
* @see {@link TabsProps.pt}
*/
export interface TabsPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: TabsPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
/**
* Custom passthrough attributes for each DOM elements
*/
export interface TabsPassThroughAttributes {
[key: string]: any;
}
/**
* Defines current inline state in Tabs component.
*/
export interface TabsState {
/**
* Current active value state.
*/
d_value: number;
/**
* Unique id for the Tabs component.
*/
id: string;
}
/**
* Defines valid properties in Tabs component.
*/
export interface TabsProps {
/**
* Value of the active tab.
*/
value: string;
/**
* When enabled, hidden tabs are not rendered at all. Defaults to false that hides tabs with css.
* @defaultValue false
*/
lazy?: boolean | undefined;
/**
* Specifies the layout of the component, valid values are 'horizontal' and 'vertical'.
* @defaultValue horizontal
*/
orientation?: 'horizontal' | 'vertical' | undefined;
/**
* When specified, enables horizontal and/or vertical scrolling.
* @defaultValue false
*/
scrollable?: boolean | undefined;
/**
* Whether to display navigation buttons in container when scrollable is enabled.
* @defaultValue true
*/
showNavigators?: boolean | undefined;
/**
* Index of the element in tabbing order.
* @defaultValue 0
*/
tabindex?: number | undefined;
/**
* When enabled, the focused tab is activated.
* @defaultValue false
*/
selectOnFocus?: boolean | undefined;
/**
* Used to pass all properties of the HTMLButtonElement to the previous button.
*/
previousButtonProps?: ButtonProps | undefined;
/**
* Used to pass all properties of the HTMLButtonElement to the next button.
*/
nextButtonProps?: ButtonProps | undefined;
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {TabsPassThroughOptions}
*/
pt?: PassThrough<TabsPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
/**
* When enabled, it removes component related styles in the core.
* @defaultValue false
*/
unstyled?: boolean;
}
/**
* Defines valid slots in Tabs slots.
*/
export interface TabsSlots {
/**
* Default slot to detect TabPanel components.
*/
default(): VNode[];
/**
* Previous button icon template for the scrollable component.
*/
previousicon(): VNode[];
/**
* Next button icon template for the scrollable component.
*/
nexticon(): VNode[];
}
/**
* Defines valid emits in Tabs component.
*/
export interface TabsEmits {
/**
* Emitted when the value changes.
* @param {string} value - Current value.
*/
'update:value'(value: number): void;
}
/**
*
* **PrimeVue - Tabs**
*
* _Tabs facilitates seamless switching between different views._
*
* [Live Demo](https://www.primevue.org/tabs/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*
* @group Component
*
*/
declare class Tabs extends ClassComponent<TabsProps, TabsSlots, TabsEmits> {}
declare module 'vue' {
export interface GlobalComponents {
Tabs: GlobalComponentConstructor<Tabs>;
}
}
export default Tabs;

View File

@ -0,0 +1,42 @@
<template>
<div :class="cx('root')" v-bind="ptmi('root')">
<slot></slot>
</div>
</template>
<script>
import { UniqueComponentId } from 'primevue/utils';
import BaseTabs from './BaseTabs.vue';
export default {
name: 'Tabs',
extends: BaseTabs,
inheritAttrs: false,
emits: ['update:value'],
data() {
return {
id: this.$attrs.id,
d_value: this.value
};
},
watch: {
'$attrs.id'(newValue) {
this.id = newValue || UniqueComponentId();
},
value(newValue) {
this.d_value = newValue;
}
},
mounted() {
this.id = this.id || UniqueComponentId();
},
methods: {
updateValue(newValue) {
if (this.d_value !== newValue) {
this.d_value = newValue;
this.$emit('update:value', newValue);
}
}
}
};
</script>

View File

@ -0,0 +1,9 @@
{
"main": "./tabs.cjs.js",
"module": "./tabs.esm.js",
"unpkg": "./tabs.min.js",
"types": "./Tabs.d.ts",
"browser": {
"./sfc": "./Tabs.vue"
}
}

View File

@ -0,0 +1,3 @@
import { BaseStyle } from '../../base/style';
export interface TabsStyle extends BaseStyle {}

View File

@ -0,0 +1,16 @@
import BaseStyle from 'primevue/base/style';
const classes = {
root: ({ props }) => [
'p-tabs p-component',
{
'p-tabs-scrollable': props.scrollable,
'p-tabs-vertical': props.orientation === 'vertical'
}
]
};
export default BaseStyle.extend({
name: 'tabs',
classes
});

View File

@ -0,0 +1,6 @@
{
"main": "./tabsstyle.cjs.js",
"module": "./tabsstyle.esm.js",
"unpkg": "./tabsstyle.min.js",
"types": "./TabsStyle.d.ts"
}

View File

@ -69,6 +69,7 @@ import splitter from 'primevue/themes/primeone/base/splitter';
import stepper from 'primevue/themes/primeone/base/stepper'; import stepper from 'primevue/themes/primeone/base/stepper';
import steps from 'primevue/themes/primeone/base/steps'; import steps from 'primevue/themes/primeone/base/steps';
import tabmenu from 'primevue/themes/primeone/base/tabmenu'; import tabmenu from 'primevue/themes/primeone/base/tabmenu';
import tabs from 'primevue/themes/primeone/base/tabs';
import tabview from 'primevue/themes/primeone/base/tabview'; import tabview from 'primevue/themes/primeone/base/tabview';
import tag from 'primevue/themes/primeone/base/tag'; import tag from 'primevue/themes/primeone/base/tag';
import terminal from 'primevue/themes/primeone/base/terminal'; import terminal from 'primevue/themes/primeone/base/terminal';
@ -158,6 +159,7 @@ export default {
steps, steps,
stepper, stepper,
tabmenu, tabmenu,
tabs,
tabview, tabview,
textarea, textarea,
tieredmenu, tieredmenu,

View File

@ -0,0 +1,94 @@
export default {
css: ({ dt }) => `
.p-tabs {
display: flex;
flex-direction: column;
}
.p-tablist-scroll-container {
overflow-x: auto;
overflow-y: hidden;
scroll-behavior: smooth;
scrollbar-width: none;
overscroll-behavior: contain auto;
}
.p-tablist-scroll-container::-webkit-scrollbar {
display: none;
}
.p-tablist {
position: relative;
background: ${dt('tabs.nav.background')};
}
.p-tablist-content {
position: relative;
display: flex;
border: 1px solid ${dt('tabs.nav.border.color')};
border-width: 0 0 1px 0;
}
.p-tablist-navigator.p-button {
position: absolute;
z-index: 2;
}
.p-tablist-navigator.p-tablist-prev-button {
top: 0;
left: 0;
}
.p-tablist-navigator.p-tablist-next-button {
top: 0;
right: 0;
}
.p-tab {
cursor: pointer;
border-style: solid;
border-width: 0 0 1px 0;
border-color: transparent transparent ${dt('tabs.header.border.color')} transparent;
color: ${dt('tabs.header.color')};
background: ${dt('tabs.nav.background')};
padding: 1rem 1.125rem;
font-weight: 600;
border-top-right-radius: ${dt('rounded.base')};
border-top-left-radius: ${dt('rounded.base')};
transition: color ${dt('transition.duration')}, outline-color ${dt('transition.duration')};
margin: 0 0 -1px 0;
outline-color: transparent;
line-height: 1;
white-space: nowrap;
}
.p-tab:not(.p-disabled):focus-visible {
outline: ${dt('focus.ring.width')} ${dt('focus.ring.style')} ${dt('focus.ring.color')};
outline-offset: -1px;
}
.p-tab:not(.p-active):not(.p-disabled):hover {
color: ${dt('tabs.header.hover.color')};
}
.p-tab.p-active {
color: ${dt('tabs.header.active.color')};
}
.p-tabpanels {
background: ${dt('tabs.navigator.content.background')};
color: ${dt('tabs.navigator.content.color')};
padding: 0.875rem 1.125rem 1.125rem 1.125rem;
}
.p-tablist-ink-bar {
z-index: 1;
display: block;
position: absolute;
bottom: -1px;
height: 1px;
background-color: ${dt('tabs.header.active.border.color')};
transition: 250ms cubic-bezier(0.35, 0, 0.25, 1);
}
`
};

View File

@ -0,0 +1,6 @@
{
"main": "./index.cjs.js",
"module": "./index.esm.js",
"unpkg": "./index.min.js",
"types": "./index.d.ts"
}

View File

@ -68,6 +68,7 @@ import splitter from 'primevue/themes/primeone/presets/aura/splitter';
import stepper from 'primevue/themes/primeone/presets/aura/stepper'; import stepper from 'primevue/themes/primeone/presets/aura/stepper';
import steps from 'primevue/themes/primeone/presets/aura/steps'; import steps from 'primevue/themes/primeone/presets/aura/steps';
import tabmenu from 'primevue/themes/primeone/presets/aura/tabmenu'; import tabmenu from 'primevue/themes/primeone/presets/aura/tabmenu';
import tabs from 'primevue/themes/primeone/presets/aura/tabs';
import tabview from 'primevue/themes/primeone/presets/aura/tabview'; import tabview from 'primevue/themes/primeone/presets/aura/tabview';
import tag from 'primevue/themes/primeone/presets/aura/tag'; import tag from 'primevue/themes/primeone/presets/aura/tag';
import terminal from 'primevue/themes/primeone/presets/aura/terminal'; import terminal from 'primevue/themes/primeone/presets/aura/terminal';
@ -303,6 +304,7 @@ export default {
stepper, stepper,
steps, steps,
tabmenu, tabmenu,
tabs,
tabview, tabview,
textarea, textarea,
tieredmenu, tieredmenu,

View File

@ -0,0 +1,50 @@
export default {
colorScheme: {
light: {
nav: {
background: '{surface.0}',
borderColor: '{surface.200}'
},
header: {
borderColor: '{surface.200}',
activeBorderColor: '{primary.color}',
color: '{surface.500}',
hoverColor: '{surface.700}',
activeColor: '{primary.color}'
},
navigatorIcon: {
background: '{surface.0}',
color: '{surface.500}',
hoverColor: '{surface.700}',
boxShadow: '0px 0px 10px 50px rgba(255, 255, 255, 0.6)'
},
content: {
background: '{surface.0}',
color: '{surface.700}'
}
},
dark: {
nav: {
background: '{surface.900}',
borderColor: '{surface.700}'
},
header: {
borderColor: '{surface.700}',
activeBorderColor: '{primary.color}',
color: '{surface.400}',
hoverColor: '{surface.0}',
activeColor: '{primary.color}'
},
navigatorIcon: {
background: '{surface.900}',
color: '{surface.400}',
hoverColor: '{surface.0}',
boxShadow: '0px 0px 10px 50px color-mix(in srgb, {surface.900}, transparent 50%)'
},
content: {
background: '{surface.900}',
color: '{surface.0}'
}
}
}
};

View File

@ -0,0 +1,6 @@
{
"main": "./index.cjs.js",
"module": "./index.esm.js",
"unpkg": "./index.min.js",
"types": "./index.d.ts"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
<template>
<DocSectionText id="accessibility" label="Accessibility" v-bind="$attrs">
<h3>Screen Reader</h3>
<p>
TabView container is defined with the <i>tablist</i> role, as any attribute is passed to the container element <i>aria-labelledby</i> can be optionally used to specify an element to describe the TabView. Each tab header has a
<i>tab</i> role along with <i>aria-selected</i> state attribute and <i>aria-controls</i> to refer to the corresponding tab content element. The content element of each tab has <i>tabpanel</i> role, an id to match the
<i>aria-controls</i> of the header and <i>aria-labelledby</i> reference to the header as the accessible name.
</p>
<h3>Tab Keyboard Support</h3>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Key</th>
<th>Function</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<i>tab</i>
</td>
<td>Moves focus through the header.</td>
</tr>
<tr>
<td>
<i>enter</i>
</td>
<td>Activates the focused tab header.</td>
</tr>
<tr>
<td>
<i>space</i>
</td>
<td>Activates the focused tab header.</td>
</tr>
<tr>
<td>
<i>right arrow</i>
</td>
<td>Moves focus to the next header. If focus is on the last header, moves focus to the first header.</td>
</tr>
<tr>
<td>
<i>left arrow</i>
</td>
<td>Moves focus to the previous header. If focus is on the first header, moves focus to the last header.</td>
</tr>
<tr>
<td>
<i>home</i>
</td>
<td>Moves focus to the last header.</td>
</tr>
<tr>
<td>
<i>end</i>
</td>
<td>Moves focus to the first header.</td>
</tr>
<tr>
<td><i>pageUp</i></td>
<td>Moves scroll position to first header.</td>
</tr>
<tr>
<td><i>pageDown</i></td>
<td>Moves scroll position to last header.</td>
</tr>
</tbody>
</table>
</div>
</DocSectionText>
</template>

149
doc/tabs/BasicDoc.vue Normal file
View File

@ -0,0 +1,149 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Tabs comprises a combination of <i>TabList</i>, <i>Tab</i>, <i>TabPanels</i> and <i>Tab</i> components. The <i>value</i> property is essential for associating Tab and TabPanel with each other.</p>
</DocSectionText>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
code: {
basic: `
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
<\/script>
`,
composition: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
<\/script>
`
}
};
}
};
</script>

182
doc/tabs/ControlledDoc.vue Normal file
View File

@ -0,0 +1,182 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Tabs can be controlled programmatically using <i>value</i> property.</p>
</DocSectionText>
<div class="card">
<div class="flex mb-2 gap-2 justify-content-end">
<Button @click="value = '0'" rounded label="1" class="w-2rem h-2rem p-0" :outlined="value !== '0'" />
<Button @click="value = '1'" rounded label="2" class="w-2rem h-2rem p-0" :outlined="value !== '1'" />
<Button @click="value = '2'" rounded label="3" class="w-2rem h-2rem p-0" :outlined="value !== '2'" />
</div>
<Tabs v-model:value="value">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
value: '0',
code: {
basic: `
<div class="flex mb-2 gap-2 justify-content-end">
<Button @click="value = '0'" rounded label="1" class="w-2rem h-2rem p-0" :outlined="value !== '0'" />
<Button @click="value = '1'" rounded label="2" class="w-2rem h-2rem p-0" :outlined="value !== '1'" />
<Button @click="value = '2'" rounded label="3" class="w-2rem h-2rem p-0" :outlined="value !== '2'" />
</div>
<Tabs v-model:value="value">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<div class="flex mb-2 gap-2 justify-content-end">
<Button @click="value = '0'" rounded label="1" class="w-2rem h-2rem p-0" :outlined="value !== '0'" />
<Button @click="value = '1'" rounded label="2" class="w-2rem h-2rem p-0" :outlined="value !== '1'" />
<Button @click="value = '2'" rounded label="3" class="w-2rem h-2rem p-0" :outlined="value !== '2'" />
</div>
<Tabs v-model:value="value">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
export default {
data() {
return {
value: '0'
};
}
};
<\/script>
`,
composition: `
<template>
<div class="card">
<div class="flex mb-2 gap-2 justify-content-end">
<Button @click="value = '0'" rounded label="1" class="w-2rem h-2rem p-0" :outlined="value !== '0'" />
<Button @click="value = '1'" rounded label="2" class="w-2rem h-2rem p-0" :outlined="value !== '1'" />
<Button @click="value = '2'" rounded label="3" class="w-2rem h-2rem p-0" :outlined="value !== '2'" />
</div>
<Tabs v-model:value="value">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
import { ref } from 'vue';
const value = ref('0');
<\/script>
`
}
};
}
};
</script>

151
doc/tabs/DisabledDoc.vue Normal file
View File

@ -0,0 +1,151 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Enabling <i>disabled</i> property of a Tab prevents user interaction.</p>
</DocSectionText>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
<Tab disabled>Header IV</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
code: {
basic: `
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
<Tab disabled>Header IV</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
<Tab disabled>Header IV</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
<\/script>
`,
composition: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0">Header I</Tab>
<Tab value="1">Header II</Tab>
<Tab value="2">Header III</Tab>
<Tab disabled>Header IV</Tab>
</TabList>
<TabPanels>
<TabPanel value="0">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</TabPanel>
<TabPanel value="1">
<p class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</p>
</TabPanel>
<TabPanel value="2">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa
qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
<\/script>
`
}
};
}
};
</script>

102
doc/tabs/DynamicDoc.vue Normal file
View File

@ -0,0 +1,102 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Tabs can be generated dynamically using the standard <i>v-for</i> directive on Tab and TabPanel.</p>
</DocSectionText>
<div class="card">
<Tabs value="0">
<TabList>
<Tab v-for="tab in tabs" :key="tab.title" :value="tab.value">{{ tab.title }}</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in tabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
tabs: [
{ title: 'Tab 1', content: 'Tab 1 Content', value: '0' },
{ title: 'Tab 2', content: 'Tab 2 Content', value: '1' },
{ title: 'Tab 3', content: 'Tab 3 Content', value: '2' }
],
code: {
basic: `
<Tabs value="0">
<TabList>
<Tab v-for="tab in tabs" :key="tab.title" :value="tab.value">{{ tab.title }}</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in tabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab v-for="tab in tabs" :key="tab.title" :value="tab.value">{{ tab.title }}</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in tabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
export default {
data() {
return {
tabs: [
{ title: 'Tab 1', content: 'Tab 1 Content', value: '0' },
{ title: 'Tab 2', content: 'Tab 2 Content', value: '1' },
{ title: 'Tab 3', content: 'Tab 3 Content', value: '2' }
]
};
}
};
<\/script>
`,
composition: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab v-for="tab in tabs" :key="tab.title" :value="tab.value">{{ tab.title }}</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in tabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
import { ref } from 'vue';
const tabs = ref([
{ title: 'Tab 1', content: 'Tab 1 Content', value: '0' },
{ title: 'Tab 2', content: 'Tab 2 Content', value: '1' },
{ title: 'Tab 3', content: 'Tab 3 Content', value: '2' }
]);
<\/script>
`
}
};
}
};
</script>

22
doc/tabs/ImportDoc.vue Normal file
View File

@ -0,0 +1,22 @@
<template>
<DocSectionText v-bind="$attrs" />
<DocSectionCode :code="code" hideToggleCode importCode hideStackBlitz />
</template>
<script>
export default {
data() {
return {
code: {
basic: `
import Tabs from 'primevue/tabs';
import TabList from 'primevue/tablist';
import Tab from 'primevue/tab';
import TabPanels from 'primevue/tabpanels';
import TabPanel from 'primevue/tabpanel';
`
}
};
}
};
</script>

View File

@ -0,0 +1,98 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Adding <i>scrollable</i> property displays navigational buttons at each side to scroll between tabs.</p>
</DocSectionText>
<div class="card">
<Tabs value="0" scrollable>
<TabList>
<Tab v-for="tab in scrollableTabs" :key="tab.title" :value="tab.value">
{{ tab.title }}
</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in scrollableTabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
scrollableTabs: Array.from({ length: 50 }, (_, i) => ({ title: `Tab ${i + 1}`, content: `Tab ${i + 1} Content`, value: `${i}` })),
code: {
basic: `
<Tabs value="0" scrollable>
<TabList>
<Tab v-for="tab in scrollableTabs" :key="tab.title" :value="tab.value">
{{ tab.title }}
</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in scrollableTabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<Tabs value="0" scrollable>
<TabList>
<Tab v-for="tab in scrollableTabs" :key="tab.title" :value="tab.value">
{{ tab.title }}
</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in scrollableTabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
export default {
data() {
return {
scrollableTabs: Array.from({ length: 50 }, (_, i) => ({ title: \`Tab \${i + 1}\`, content: \`Tab \${i + 1} Content\`, value: \`\${i}\` }))
};
}
};
<\/script>
`,
composition: `
<template>
<div class="card">
<Tabs value="0" scrollable>
<TabList>
<Tab v-for="tab in scrollableTabs" :key="tab.title" :value="tab.value">
{{ tab.title }}
</Tab>
</TabList>
<TabPanels>
<TabPanel v-for="tab in scrollableTabs" :key="tab.content" :value="tab.value">
<p class="m-0">{{ tab.content }}</p>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
import { ref } from 'vue';
const scrollableTabs = ref(Array.from({ length: 50 }, (_, i) => ({ title: \`Tab \${i + 1}\`, content: \`Tab \${i + 1} Content\`, value: \`\${i}\` })));
<\/script>
`
}
};
}
};
</script>

195
doc/tabs/TemplateDoc.vue Normal file
View File

@ -0,0 +1,195 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Custom content for a tab is defined using <i>as</i> or <i>asChild</i> properties.</p>
</DocSectionText>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0" as="div" class="flex align-items-center gap-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" shape="circle" />
<span class="font-bold white-space-nowrap">Amy Elsner</span>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="1" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png" shape="circle" />
<span class="font-bold white-space-nowrap">Onyama Limba</span>
</div>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="2" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/ionibowcher.png" shape="circle" />
<span class="font-bold white-space-nowrap">Ioni Bowcher</span>
<Badge value="2" />
</div>
</Tab>
</TabList>
<TabPanels>
<TabPanel value="0" as="p" class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</TabPanel>
<TabPanel value="1" as="p" class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</TabPanel>
<TabPanel v-slot="slotProps" value="2" asChild>
<div v-show="slotProps.active" :class="slotProps.class" v-bind="slotProps.a11yAttrs">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in
culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</div>
</TabPanel>
</TabPanels>
</Tabs>
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
code: {
basic: `
<Tabs value="0">
<TabList>
<Tab value="0" as="div" class="flex align-items-center gap-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" shape="circle" />
<span class="font-bold white-space-nowrap">Amy Elsner</span>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="1" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png" shape="circle" />
<span class="font-bold white-space-nowrap">Onyama Limba</span>
</div>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="2" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/ionibowcher.png" shape="circle" />
<span class="font-bold white-space-nowrap">Ioni Bowcher</span>
<Badge value="2" />
</div>
</Tab>
</TabList>
<TabPanels>
<TabPanel value="0" as="p" class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</TabPanel>
<TabPanel value="1" as="p" class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</TabPanel>
<TabPanel v-slot="slotProps" value="2" asChild>
<div v-show="slotProps.active" :class="slotProps.class" v-bind="slotProps.a11yAttrs">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in
culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</div>
</TabPanel>
</TabPanels>
</Tabs>
`,
options: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0" as="div" class="flex align-items-center gap-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" shape="circle" />
<span class="font-bold white-space-nowrap">Amy Elsner</span>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="1" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png" shape="circle" />
<span class="font-bold white-space-nowrap">Onyama Limba</span>
</div>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="2" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/ionibowcher.png" shape="circle" />
<span class="font-bold white-space-nowrap">Ioni Bowcher</span>
<Badge value="2" />
</div>
</Tab>
</TabList>
<TabPanels>
<TabPanel value="0" as="p" class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</TabPanel>
<TabPanel value="1" as="p" class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</TabPanel>
<TabPanel v-slot="slotProps" value="2" asChild>
<div v-show="slotProps.active" :class="slotProps.class" v-bind="slotProps.a11yAttrs">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in
culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</div>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script>
<\/script>
`,
composition: `
<template>
<div class="card">
<Tabs value="0">
<TabList>
<Tab value="0" as="div" class="flex align-items-center gap-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" shape="circle" />
<span class="font-bold white-space-nowrap">Amy Elsner</span>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="1" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png" shape="circle" />
<span class="font-bold white-space-nowrap">Onyama Limba</span>
</div>
</Tab>
<Tab v-slot="{ a11yAttrs, onClick }" value="2" asChild>
<div class="flex align-items-center gap-2" @click="onClick" v-bind="a11yAttrs">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/ionibowcher.png" shape="circle" />
<span class="font-bold white-space-nowrap">Ioni Bowcher</span>
<Badge value="2" />
</div>
</Tab>
</TabList>
<TabPanels>
<TabPanel value="0" as="p" class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</TabPanel>
<TabPanel value="1" as="p" class="m-0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi.
</TabPanel>
<TabPanel v-slot="slotProps" value="2" asChild>
<div v-show="slotProps.active" :class="slotProps.class" v-bind="slotProps.a11yAttrs">
<p class="m-0">
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in
culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus.
</p>
</div>
</TabPanel>
</TabPanels>
</Tabs>
</div>
</template>
<script setup>
<\/script>
`
}
};
}
};
</script>

8
doc/tabs/pt/PTImage.vue Normal file
View File

@ -0,0 +1,8 @@
<template>
<DocSectionText v-bind="$attrs">
<p>{{ $attrs.description }}</p>
</DocSectionText>
<div class="card">
<img class="w-full" src="https://primefaces.org/cdn/primevue/images/pt/wireframe-placeholder.jpg" />
</div>
</template>

59
doc/tabs/pt/index.vue Normal file
View File

@ -0,0 +1,59 @@
<template>
<div class="doc-main">
<div class="doc-intro">
<h1>Tabs Pass Through</h1>
</div>
<DocSections :docs="docs" />
</div>
<DocSectionNav :docs="docs" />
</template>
<script>
import DocApiTable from '@/components/doc/DocApiTable.vue';
import { getPTOption } from '@/components/doc/helpers/PTHelper.js';
import PTImage from './PTImage.vue';
export default {
data() {
return {
docs: [
{
id: 'pt.image',
label: 'Wireframe',
component: PTImage
},
{
id: 'pt.doc.tabs',
label: 'Tabs PT Options',
component: DocApiTable,
data: getPTOption('Tabs')
},
{
id: 'pt.doc.tablist',
label: 'TabList PT Options',
component: DocApiTable,
data: getPTOption('TabList')
},
{
id: 'pt.doc.tab',
label: 'Tab PT Options',
component: DocApiTable,
data: getPTOption('Tab')
},
{
id: 'pt.doc.tabpanels',
label: 'TabPanels PT Options',
component: DocApiTable,
data: getPTOption('TabPanels')
},
{
id: 'pt.doc.tabpanel',
label: 'TabPanel PT Options',
component: DocApiTable,
data: getPTOption('TabPanel')
}
]
};
}
};
</script>

View File

@ -0,0 +1,33 @@
<template>
<DocSectionText v-bind="$attrs">
<p>List of class names used in the styled mode.</p>
</DocSectionText>
<div class="doc-tablewrapper">
<table class="doc-table">
<thead>
<tr>
<th>Name</th>
<th>Element</th>
</tr>
</thead>
<tbody>
<tr>
<td>p-tabs</td>
<td>Container element.</td>
</tr>
<tr>
<td>p-tab</td>
<td>Container of a tab.</td>
</tr>
<tr>
<td>p-tabpanels</td>
<td>Container panels.</td>
</tr>
<tr>
<td>p-tabpanel</td>
<td>Content of a tab panel.</td>
</tr>
</tbody>
</table>
</div>
</template>

View File

@ -0,0 +1,6 @@
<template>
<DocSectionText v-bind="$attrs">
Visit <a href="https://github.com/primefaces/primevue-tailwind" target="_blank" rel="noopener noreferrer">Tailwind Presets</a> project for detailed documentation, examples and ready-to-use presets about how to style PrimeVue components with
Tailwind CSS.
</DocSectionText>
</template>

View File

@ -0,0 +1,40 @@
<template>
<div class="doc-main">
<div class="doc-intro">
<h1>Tabs Theming</h1>
</div>
<DocSections :docs="docs" />
</div>
<DocSectionNav :docs="docs" />
</template>
<script>
import StyledDoc from './StyledDoc.vue';
import TailwindDoc from './TailwindDoc.vue';
export default {
data() {
return {
docs: [
{
id: 'theming.styled',
label: 'Styled',
component: StyledDoc
},
{
id: 'theming.unstyled',
label: 'Unstyled',
description: 'Theming is implemented with the pass through properties in unstyled mode.',
children: [
{
id: 'theming.tailwind',
label: 'Tailwind',
component: TailwindDoc
}
]
}
]
};
}
};
</script>

View File

@ -38,7 +38,7 @@ const button = ['Button', 'ButtonGroup', 'SpeedDial', 'SplitButton'];
const data = ['Column', 'Row', 'ColumnGroup', 'DataTable', 'DataView', 'OrderList', 'OrganizationChart', 'Paginator', 'PickList', 'Tree', 'TreeTable', 'Timeline', 'VirtualScroller']; const data = ['Column', 'Row', 'ColumnGroup', 'DataTable', 'DataView', 'OrderList', 'OrganizationChart', 'Paginator', 'PickList', 'Tree', 'TreeTable', 'Timeline', 'VirtualScroller'];
const panel = ['Accordion', 'AccordionTab', 'Card', 'DeferredContent', 'Divider', 'Fieldset', 'Panel', 'ScrollPanel', 'Splitter', 'SplitterPanel', 'Stepper', 'StepperPanel', 'TabView', 'TabPanel', 'Toolbar']; const panel = ['Accordion', 'AccordionTab', 'Card', 'DeferredContent', 'Divider', 'Fieldset', 'Panel', 'ScrollPanel', 'Splitter', 'SplitterPanel', 'Stepper', 'StepperPanel', 'TabView', 'Tabs', 'TabList', 'Tab', 'TabPanels', 'TabPanel', 'Toolbar'];
const overlay = [ const overlay = [
{ name: 'ConfirmDialog', use: { as: 'ConfirmationService' } }, { name: 'ConfirmDialog', use: { as: 'ConfirmationService' } },

View File

@ -101,6 +101,10 @@ const STYLE_ALIAS = {
'primevue/stepperpanel/style': path.resolve(__dirname, './components/lib/stepperpanel/style/StepperPanelStyle.js'), 'primevue/stepperpanel/style': path.resolve(__dirname, './components/lib/stepperpanel/style/StepperPanelStyle.js'),
'primevue/styleclass/style': path.resolve(__dirname, './components/lib/styleclass/style/StyleClassStyle.js'), 'primevue/styleclass/style': path.resolve(__dirname, './components/lib/styleclass/style/StyleClassStyle.js'),
'primevue/tabmenu/style': path.resolve(__dirname, './components/lib/tabmenu/style/TabMenuStyle.js'), 'primevue/tabmenu/style': path.resolve(__dirname, './components/lib/tabmenu/style/TabMenuStyle.js'),
'primevue/tabs/style': path.resolve(__dirname, './components/lib/tabs/style/TabsStyle.js'),
'primevue/tablist/style': path.resolve(__dirname, './components/lib/tablist/style/TabListStyle.js'),
'primevue/tab/style': path.resolve(__dirname, './components/lib/tab/style/TabStyle.js'),
'primevue/tabpanels/style': path.resolve(__dirname, './components/lib/tabpanels/style/TabPanelsStyle.js'),
'primevue/tabpanel/style': path.resolve(__dirname, './components/lib/tabpanel/style/TabPanelStyle.js'), 'primevue/tabpanel/style': path.resolve(__dirname, './components/lib/tabpanel/style/TabPanelStyle.js'),
'primevue/tabview/style': path.resolve(__dirname, './components/lib/tabview/style/TabViewStyle.js'), 'primevue/tabview/style': path.resolve(__dirname, './components/lib/tabview/style/TabViewStyle.js'),
'primevue/tag/style': path.resolve(__dirname, './components/lib/tag/style/TagStyle.js'), 'primevue/tag/style': path.resolve(__dirname, './components/lib/tag/style/TagStyle.js'),
@ -170,7 +174,7 @@ const ICON_ALIAS = {
}; };
// prettier-ignore // prettier-ignore
const THEME_COMPONENTS = ['accordion','autocomplete','avatar','badge','blockui','breadcrumb','button','buttongroup','card','carousel','cascadeselect','checkbox','chip','colorpicker','confirmdialog','confirmpopup','contextmenu','datatable','dataview','datepicker','dialog','divider','dock','drawer','editor','fieldset','fileupload','floatlabel','galleria','iconfield','image','inlinemessage','inplace','inputchips','inputgroup','inputnumber','inputotp','inputtext','knob','listbox','megamenu','menu','menubar','message','metergroup','multiselect','orderlist','organizationchart','paginator','panel','panelmenu','password','picklist','popover','progressbar','progressspinner','radiobutton','rating','scrollpanel','scrolltop','select','selectbutton','skeleton','slider','speeddial','splitbutton','splitter','steps','stepper','tabmenu','tabview','tag','terminal','textarea','tieredmenu','timeline','toast','togglebutton','toggleswitch','toolbar','tooltip','tree','treeselect','treetable']; const THEME_COMPONENTS = ['accordion','autocomplete','avatar','badge','blockui','breadcrumb','button','buttongroup','card','carousel','cascadeselect','checkbox','chip','colorpicker','confirmdialog','confirmpopup','contextmenu','datatable','dataview','datepicker','dialog','divider','dock','drawer','editor','fieldset','fileupload','floatlabel','galleria','iconfield','image','inlinemessage','inplace','inputchips','inputgroup','inputnumber','inputotp','inputtext','knob','listbox','megamenu','menu','menubar','message','metergroup','multiselect','orderlist','organizationchart','paginator','panel','panelmenu','password','picklist','popover','progressbar','progressspinner','radiobutton','rating','scrollpanel','scrolltop','select','selectbutton','skeleton','slider','speeddial','splitbutton','splitter','steps','stepper','tabmenu','tabs','tabview','tag','terminal','textarea','tieredmenu','timeline','toast','togglebutton','toggleswitch','toolbar','tooltip','tree','treeselect','treetable'];
const createThemeAlias = (design, presets) => { const createThemeAlias = (design, presets) => {
const baseAlias = THEME_COMPONENTS.reduce((acc, name) => { const baseAlias = THEME_COMPONENTS.reduce((acc, name) => {

75
pages/tabs/index.vue Executable file
View File

@ -0,0 +1,75 @@
<template>
<DocComponent
title="Vue Tabs Component"
header="Tabs"
description="Tabs facilitates seamless switching between different views."
:componentDocs="docs"
:apiDocs="['Tabs', 'TabList', 'Tab', 'TabPanels', 'TabPanel']"
:ptTabComponent="ptComponent"
:themingDocs="themingDoc"
/>
</template>
<script>
import AccessibilityDoc from '@/doc/tabs/AccessibilityDoc.vue';
import BasicDoc from '@/doc/tabs/BasicDoc.vue';
import ControlledDoc from '@/doc/tabs/ControlledDoc.vue';
import DisabledDoc from '@/doc/tabs/DisabledDoc.vue';
import DynamicDoc from '@/doc/tabs/DynamicDoc.vue';
import ImportDoc from '@/doc/tabs/ImportDoc.vue';
import ScrollableDoc from '@/doc/tabs/ScrollableDoc.vue';
import TemplateDoc from '@/doc/tabs/TemplateDoc.vue';
import PTComponent from '@/doc/tabs/pt/index.vue';
import ThemingDoc from '@/doc/tabs/theming/index.vue';
export default {
data() {
return {
docs: [
{
id: 'import',
label: 'Import',
component: ImportDoc
},
{
id: 'basic',
label: 'Basic',
component: BasicDoc
},
{
id: 'dynamic',
label: 'Dynamic',
component: DynamicDoc
},
{
id: 'controlled',
label: 'Controlled',
component: ControlledDoc
},
{
id: 'scrollable',
label: 'Scrollable',
component: ScrollableDoc
},
{
id: 'disabled',
label: 'Disabled',
component: DisabledDoc
},
{
id: 'template',
label: 'Template',
component: TemplateDoc
},
{
id: 'accessibility',
label: 'Accessibility',
component: AccessibilityDoc
}
],
ptComponent: PTComponent,
themingDoc: ThemingDoc
};
}
};
</script>

View File

@ -162,6 +162,10 @@ const CORE_STYLE_DEPENDENCIES = {
'primevue/steps/style': 'primevue.steps.style', 'primevue/steps/style': 'primevue.steps.style',
'primevue/styleclass/style': 'primevue.styleclass.style', 'primevue/styleclass/style': 'primevue.styleclass.style',
'primevue/tabmenu/style': 'primevue.tabmenu.style', 'primevue/tabmenu/style': 'primevue.tabmenu.style',
'primevue/tabs/style': 'primevue.tabs.style',
'primevue/tablist/style': 'primevue.tablist.style',
'primevue/tab/style': 'primevue.tab.style',
'primevue/tabpanels/style': 'primevue.tabpanels.style',
'primevue/tabpanel/style': 'primevue.tabpanel.style', 'primevue/tabpanel/style': 'primevue.tabpanel.style',
'primevue/tabview/style': 'primevue.tabview.style', 'primevue/tabview/style': 'primevue.tabview.style',
'primevue/tag/style': 'primevue.tag.style', 'primevue/tag/style': 'primevue.tag.style',
@ -181,7 +185,7 @@ const CORE_STYLE_DEPENDENCIES = {
}; };
// prettier-ignore // prettier-ignore
const THEME_COMPONENTS = ['accordion','autocomplete','avatar','badge','blockui','breadcrumb','button','buttongroup','card','carousel','cascadeselect','checkbox','chip','colorpicker','confirmdialog','confirmpopup','contextmenu','datatable','dataview','datepicker','dialog','divider','dock','drawer','editor','fieldset','fileupload','floatlabel','galleria','iconfield','image','inlinemessage','inplace','inputchips','inputgroup','inputnumber','inputotp','toggleswitch','inputtext','knob','listbox','megamenu','menu','menubar','message','metergroup','multiselect','orderlist','organizationchart','overlaypanel','paginator','panel','panelmenu','password','picklist','popover','progressbar','progressspinner','radiobutton','rating','scrollpanel','scrolltop','select','selectbutton','skeleton','slider','speeddial','splitbutton','splitter','steps','stepper','tabmenu','tabview','tag','terminal','textarea','tieredmenu','timeline','toast','togglebutton','toggleswitch','toolbar','tooltip','tree','treeselect','treetable']; const THEME_COMPONENTS = ['accordion','autocomplete','avatar','badge','blockui','breadcrumb','button','buttongroup','card','carousel','cascadeselect','checkbox','chip','colorpicker','confirmdialog','confirmpopup','contextmenu','datatable','dataview','datepicker','dialog','divider','dock','drawer','editor','fieldset','fileupload','floatlabel','galleria','iconfield','image','inlinemessage','inplace','inputchips','inputgroup','inputnumber','inputotp','toggleswitch','inputtext','knob','listbox','megamenu','menu','menubar','message','metergroup','multiselect','orderlist','organizationchart','overlaypanel','paginator','panel','panelmenu','password','picklist','popover','progressbar','progressspinner','radiobutton','rating','scrollpanel','scrolltop','select','selectbutton','skeleton','slider','speeddial','splitbutton','splitter','steps','stepper','tabmenu', 'tab', 'tabview','tag','terminal','textarea','tieredmenu','timeline','toast','togglebutton','toggleswitch','toolbar','tooltip','tree','treeselect','treetable'];
const createThemeDependencies = (design, presets) => { const createThemeDependencies = (design, presets) => {
const baseDeps = THEME_COMPONENTS.reduce((acc, name) => { const baseDeps = THEME_COMPONENTS.reduce((acc, name) => {