Skip to content

Commit

Permalink
fix(ktabs): slotted anchor link (#2480)
Browse files Browse the repository at this point in the history
* fix(ktabs): slotted anchor link color

* fix(ktabs): slotted link color

* fix(ktabs): slotted anchor link active

* fix(ktabs): add anchor-tabindex prop

* docs(tabs): anchor-tabindex prop
  • Loading branch information
portikM authored Oct 25, 2024
1 parent 2dbdd0a commit 72ae295
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 14 deletions.
27 changes: 22 additions & 5 deletions docs/components/table-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,28 @@ The `rowKey` prop accepts either a unique string or a function that returns a un
If a string is provided which corresponds to a property of the `row`, the unique identifier will utilize the `row[rowKey]` as the unique identifier.

```html
<KTableView
row-key="id"
:data="tableData"
:headers="headers"
/>
<template>
<KTableView
row-key="id"
:data="tableData"
:headers="headers"
/>
</template>

<script setup lang="ts">
import type { TableViewData } from '@kong/kongponents'
const tableData: TableViewData = [
{
id: 'a70642b3-20f2-4658-b459-fe1cbcf9e315',
...
},
{
id: '58c599a9-f453-41f3-9e64-0a7fc6caedad',
...
}
]
</script>
```

Alternatively, if a function is passed, it allows for the creation of a custom identifier based on the row data passed to the function.
Expand Down
4 changes: 4 additions & 0 deletions docs/components/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ const tabChange = (hash: string): void => {
</script>
```

### anchorTabindex

This prop allows setting a custom `tabindex` for the tab anchor element. It’s useful when passing a custom interactive element, like a link, through the [`anchor` slot](#anchor-panel), ensuring that only the slotted element is focusable by resetting the default anchor `tabindex`. Default value is `0`.

#### Dynamic RouterView

Here's an example (code only) of utilizing a dynamic `router-view` component within the host app:
Expand Down
1 change: 1 addition & 0 deletions sandbox/pages/SandboxTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
/>
<SandboxSectionComponent title="Dynamic router view without panels">
<KTabs
:anchor-tabindex="-1"
hide-panels
:tabs="dynamicRouterViewItems"
@change="(hash: string) => $router.replace({ hash })"
Expand Down
46 changes: 37 additions & 9 deletions src/components/KTabs/KTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
class="tab-link"
:class="{ 'has-panels': !hidePanels, disabled: tab.disabled }"
role="tab"
:tabindex="tab.disabled ? '-1' : '0'"
:tabindex="getAnchorTabindex(tab)"
@click.prevent="!tab.disabled ? handleTabChange(tab.hash) : undefined"
@keydown.enter.prevent="!tab.disabled ? handleTabChange(tab.hash) : undefined"
@keydown.space.prevent="!tab.disabled ? handleTabChange(tab.hash) : undefined"
>
<slot :name="`${tab.hash.replace('#','')}-anchor`">
<slot :name="`${getTabSlotName(tab.hash)}-anchor`">
<span>{{ tab.title }}</span>
</slot>
</div>
Expand All @@ -34,13 +34,13 @@
v-for="(tab, i) in tabs"
:id="`panel-${i}`"
:key="tab.hash"
:aria-labelledby="`${tab.hash.replace('#','')}-tab`"
:aria-labelledby="`${getTabSlotName(tab.hash)}-tab`"
class="tab-container"
role="tabpanel"
>
<slot
v-if="activeTab === tab.hash"
:name="tab.hash.replace('#','')"
:name="getTabSlotName(tab.hash)"
/>
</div>
</template>
Expand Down Expand Up @@ -75,6 +75,11 @@ const props = defineProps({
type: Boolean,
default: false,
},
anchorTabindex: {
type: Number,
default: 0,
validator: (val: number): boolean => val >= -1 && val <= 32767,
},
})
const emit = defineEmits<{
Expand All @@ -90,6 +95,16 @@ const handleTabChange = (tab: string): void => {
emit('update:modelValue', tab)
}
const getTabSlotName = (tabHash: string): string => tabHash.replace('#', '')
const getAnchorTabindex = (tab: Tab): string => {
if (tab.disabled) {
return '-1'
}
return typeof props.anchorTabindex === 'number' && props.anchorTabindex >= -1 && props.anchorTabindex <= 32767 ? String(props.anchorTabindex) : '0'
}
watch(() => props.modelValue, (newTabHash) => {
activeTab.value = newTabHash
emit('change', newTabHash)
Expand All @@ -98,6 +113,14 @@ watch(() => props.modelValue, (newTabHash) => {
</script>

<style lang="scss" scoped>
@mixin kTabsFocus {
background-color: var(--kui-color-background-neutral-weaker, $kui-color-background-neutral-weaker);
border-radius: var(--kui-border-radius-30, $kui-border-radius-30);
box-shadow: var(--kui-shadow-focus, $kui-shadow-focus);
color: var(--kui-color-text, $kui-color-text);
outline: none;
}
.k-tabs {
ul {
border-bottom: var(--kui-border-width-10, $kui-border-width-10) solid var(--kui-color-border, $kui-color-border);
Expand Down Expand Up @@ -141,19 +164,20 @@ watch(() => props.modelValue, (newTabHash) => {
}
a, :deep(a) {
color: var(--kui-color-text, $kui-color-text);
color: var(--kui-color-text-neutral, $kui-color-text-neutral);
text-decoration: none;
&:focus-visible {
@include kTabsFocus;
}
}
&:hover:not(.disabled) {
background-color: var(--kui-color-background-neutral-weaker, $kui-color-background-neutral-weaker);
}
&:focus-visible {
background-color: var(--kui-color-background-neutral-weaker, $kui-color-background-neutral-weaker);
box-shadow: var(--kui-shadow-focus, $kui-shadow-focus);
color: var(--kui-color-text, $kui-color-text);
outline: none;
@include kTabsFocus;
}
&.disabled {
Expand All @@ -167,6 +191,10 @@ watch(() => props.modelValue, (newTabHash) => {
.tab-link {
color: var(--kui-color-text, $kui-color-text);
a, :deep(a) {
color: var(--kui-color-text, $kui-color-text);
}
}
}
}
Expand Down

0 comments on commit 72ae295

Please sign in to comment.