Newer
Older
gnexus-ui-kit / src / vue / components / GnTabs.js
@Eugene Sukhodolskiy Eugene Sukhodolskiy 15 hours ago 1 KB Add Vue adapter foundation
import { computed, defineComponent, h } from "vue";
import { cx, iconNode } from "../utils.js";

export default defineComponent({
	name: "GnTabs",
	props: {
		modelValue: { type: String, default: "" },
		items: { type: Array, required: true },
		compact: { type: Boolean, default: false },
		vertical: { type: Boolean, default: false },
		ariaLabel: { type: String, default: "Tabs" }
	},
	emits: ["update:modelValue"],
	setup(props, { emit, slots }) {
		const activeId = computed(() => props.modelValue || props.items.find(item => !item.disabled)?.id || props.items[0]?.id);

		const activate = item => {
			if(!item.disabled) {
				emit("update:modelValue", item.id);
			}
		};

		return () => h("div", {
			class: cx("tabs", {
				"tabs-compact": props.compact,
				"tabs-vertical": props.vertical
			})
		}, [
			h("div", { class: "tabs-list", role: "tablist", "aria-label": props.ariaLabel }, props.items.map(item => {
				const active = item.id === activeId.value;
				const panelId = `${item.id}-panel`;

				return h("button", {
					class: cx("tab", { "tab-active": active }),
					type: "button",
					role: "tab",
					"aria-selected": active ? "true" : "false",
					"aria-controls": panelId,
					"aria-disabled": item.disabled ? "true" : undefined,
					tabindex: active ? "0" : "-1",
					onClick: () => activate(item)
				}, [
					iconNode(item.icon),
					item.label
				]);
			})),
			h("div", { class: "tabs-panels" }, props.items.map(item => {
				const active = item.id === activeId.value;

				return h("div", {
					id: `${item.id}-panel`,
					class: cx("tab-panel", { "tab-panel-active": active }),
					role: "tabpanel",
					hidden: !active
				}, slots[item.id]?.({ item, active }) || (active && slots.default?.({ item, active })));
			}))
		]);
	}
});