-
Notifications
You must be signed in to change notification settings - Fork 204
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ariakit vue exploration with port of Heading
- Loading branch information
1 parent
081d174
commit c72ccdb
Showing
11 changed files
with
369 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
frontend/src/components/ariakit/heading/AHeading.composable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { computed, MaybeRef, onUnmounted } from "vue" | ||
|
||
import { useMemoize } from "@vueuse/core" | ||
|
||
import { useTagName } from "~/composables/ariakit" | ||
|
||
import type { Renderable } from "~/types/ariakit" | ||
|
||
import { HeadingContext } from "./HeadingContext" | ||
|
||
export interface UseHeadingOptions { | ||
templateRef: MaybeRef<Element | null> | ||
element?: Renderable | ||
} | ||
|
||
export function useHeading({ templateRef, element }: UseHeadingOptions) { | ||
const level = HeadingContext.inject() || 1 | ||
const Element = element || (`h${level}` as const) | ||
const tagName = useTagName( | ||
templateRef, | ||
typeof element === "string" ? element : `h${level}` | ||
) | ||
const getIsNativeHeading = useMemoize((tagName: string) => | ||
/^h\d$/.test(tagName) | ||
) | ||
const isNativeHeading = computed( | ||
() => !!tagName.value && getIsNativeHeading(tagName.value) | ||
) | ||
onUnmounted(() => getIsNativeHeading.clear()) | ||
|
||
const attributes = computed(() => ({ | ||
role: !isNativeHeading.value ? "heading" : undefined, | ||
"aria-level": !isNativeHeading.value ? level : undefined, | ||
})) | ||
|
||
return { | ||
Element, | ||
attributes, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<script setup lang="ts" generic="T extends Renderable = 'h1'"> | ||
import { ref, mergeProps, computed } from "vue" | ||
import type { Renderable, AsProps } from "~/types/ariakit" | ||
import { useHeading } from "./AHeading.composable" | ||
const { as, asProps } = defineProps<AsProps<T>>() | ||
const templateRef = ref<Element | null>(null) | ||
const { Element, attributes } = useHeading({ element: as, templateRef }) | ||
const mergedProps = computed(() => mergeProps(asProps ?? {}, attributes.value)) | ||
</script> | ||
|
||
<template> | ||
<component :is="Element" v-bind="mergedProps" :ref="templateRef"> | ||
<slot | ||
v-bind="{ | ||
Element, | ||
attributes, | ||
setTemplateRef: (e: Element) => (templateRef = e), | ||
}" | ||
/> | ||
</component> | ||
</template> |
15 changes: 15 additions & 0 deletions
15
frontend/src/components/ariakit/heading/AHeadingLevel.composable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { HeadingContext, type HeadingLevels } from "./HeadingContext" | ||
|
||
export interface HeadingLevelOptions { | ||
level?: HeadingLevels | ||
} | ||
|
||
export function useHeadingLevel({ level }: HeadingLevelOptions) { | ||
const contextLevel = HeadingContext.inject() || 0 | ||
const nextLevel = Math.max( | ||
Math.min(level || contextLevel + 1, 6), | ||
1 | ||
) as HeadingLevels | ||
HeadingContext.provide(nextLevel) | ||
return nextLevel | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<script setup lang="ts" generic="T extends Renderable = never"> | ||
import type { Renderable, AsProps } from "~/types/ariakit" | ||
import { | ||
useHeadingLevel, | ||
type HeadingLevelOptions, | ||
} from "./AHeadingLevel.composable" | ||
const props = defineProps<HeadingLevelOptions & AsProps<T>>() | ||
useHeadingLevel(props) | ||
</script> | ||
|
||
<template> | ||
<component :is="as" v-if="as" v-bind="asProps ?? {}"> | ||
<slot /> | ||
</component> | ||
<slot v-else /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { provide, inject, type InjectionKey } from "vue" | ||
|
||
export type HeadingLevels = 1 | 2 | 3 | 4 | 5 | 6 | ||
|
||
export type HeadingContext = HeadingLevels | ||
const HeadingContextKey: InjectionKey<HeadingContext> = | ||
Symbol.for("ariakit-heading") | ||
|
||
export const HeadingContext = Object.freeze({ | ||
key: HeadingContextKey, | ||
provide(context: HeadingContext) { | ||
provide(HeadingContextKey, context) | ||
}, | ||
inject() { | ||
return inject(HeadingContextKey, 0) | ||
}, | ||
}) |
31 changes: 31 additions & 0 deletions
31
frontend/src/components/ariakit/heading/meta/AHeading.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { h } from "vue" | ||
|
||
import AHeading from "~/components/ariakit/heading/AHeading.vue" | ||
|
||
import AHeadingLevel from "~/components/ariakit/heading/AHeadingLevel.vue" | ||
|
||
import type { Meta, StoryObj } from "@storybook/vue3" | ||
|
||
const meta = { | ||
title: "Ariakit/Heading", | ||
} satisfies Meta<typeof AHeading> | ||
|
||
export default meta | ||
type Story = StoryObj<typeof meta> | ||
|
||
export const AHeadingStory: Story = { | ||
render: () => ({ | ||
components: { AHeading, AHeadingLevel }, | ||
setup() { | ||
return () => | ||
h("div", { class: "wrapper" }, [ | ||
h(AHeadingLevel, null, [ | ||
h(AHeading, { class: "heading" }, ["First heading"]), | ||
h(AHeadingLevel, null, [ | ||
h(AHeading, { as: { element: "div" } }, ["Second heading"]), | ||
]), | ||
]), | ||
]) | ||
}, | ||
}), | ||
} |
Oops, something went wrong.