Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: migrate Accordion components to Vue files #581

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,17 @@ export default antfu(
],
rules: {
'import/first': 'off',
'sort-imports': 'off',
'import/no-duplicates': 'off',
'import/order': 'off',
'vue/block-order': ['error', {
order: ['script', 'template', 'style'],
}],
'vue/block-tag-newline': 'off',
'vue/component-api-style': ['error', ['script-setup']],
'vue/component-tags-order': ['error', {
order: ['script', 'template', 'style'],
}],
},
},
)
43 changes: 0 additions & 43 deletions packages/core/src/accordion/AccordionContent.ts

This file was deleted.

58 changes: 56 additions & 2 deletions packages/core/src/accordion/AccordionContent.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,61 @@
<script lang="ts">
import type { Ref } from 'vue'
import type { RadixPrimitiveGetAttrs, RadixPrimitiveReturns } from '../shared/index.ts'
import {
type CollapsibleContentProps,
DEFAULT_COLLAPSIBLE_CONTENT_PROPS,
useCollapsibleContent,
type UseCollapsibleContentProps,
} from '../collapsible/index.ts'
import {
convertPropsToHookProps,
mergePrimitiveAttrs,
normalizeAttrs,
} from '../shared/index.ts'
import { useAccordionItemContext } from './AccordionItem.vue'
import { useAccordionContext } from './AccordionRoot.vue'

export type AccordionContentProps = CollapsibleContentProps

export const DEFAULT_ACCORDION_CONTENT_PROPS = DEFAULT_COLLAPSIBLE_CONTENT_PROPS

export interface UseAccordionContentProps extends UseCollapsibleContentProps {}

export function useAccordionContent(props: UseAccordionContentProps): RadixPrimitiveReturns<{
isOpen: Ref<boolean>
attrs: RadixPrimitiveGetAttrs
}> {
const collapsibleContent = useCollapsibleContent(props)

const accordionContext = useAccordionContext('AccordionContent')
const itemContext = useAccordionItemContext('AccordionContent')

const style = {
'--radix-accordion-content-height': 'var(--radix-collapsible-content-height)',
'--radix-accordion-content-width': 'var(--radix-collapsible-content-width)',
}

return {
isOpen: collapsibleContent.isOpen,
attrs(extraAttrs = []) {
const attrs = {
'role': 'region',
'aria-labelledby': itemContext.triggerId,
'data-orientation': accordionContext.orientation,
'style': style,
}

mergePrimitiveAttrs(attrs, [collapsibleContent.attrs(), ...extraAttrs])

return attrs
},
}
}

</script>

<script setup lang="ts">
import { Primitive } from '../primitive/index.ts'
import { convertPropsToHookProps, normalizeAttrs } from '../shared/index.ts'
import { type AccordionContentProps, DEFAULT_ACCORDION_CONTENT_PROPS, useAccordionContent } from './AccordionContent.ts'

defineOptions({
name: 'AccordionContent',
Expand Down
30 changes: 0 additions & 30 deletions packages/core/src/accordion/AccordionHeader.ts

This file was deleted.

36 changes: 34 additions & 2 deletions packages/core/src/accordion/AccordionHeader.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
<script lang="ts">
import type { PrimitiveProps } from '../primitive/index.ts'
import type { RadixPrimitiveReturns } from '../shared/index.ts'
import { mergePrimitiveAttrs, normalizeAttrs } from '../shared/index.ts'
import { useAccordionItemContext } from './AccordionItem.vue'
import { useAccordionContext } from './AccordionRoot.vue'

export interface AccordionHeaderProps {
as?: PrimitiveProps['as']
}

export function useAccordionHeader(): RadixPrimitiveReturns {
const accordionContext = useAccordionContext('AccordionHeader')
const itemContext = useAccordionItemContext('AccordionHeader')

return {
attrs(extraAttrs) {
const attrs = {
'data-orientation': accordionContext.orientation,
'data-state': itemContext.open.value ? 'open' : 'closed',
'data-disabled': itemContext.disabled.value ? '' : undefined,
}

if (extraAttrs && extraAttrs.length > 0) {
mergePrimitiveAttrs(attrs, extraAttrs)
}

return attrs
},
}
}

</script>

<script setup lang="ts">
import { Primitive } from '../primitive/index.ts'
import { normalizeAttrs } from '../shared/index.ts'
import { type AccordionHeaderProps, useAccordionHeader } from './AccordionHeader.ts'

defineOptions({
name: 'AccordionHeader',
Expand Down
77 changes: 0 additions & 77 deletions packages/core/src/accordion/AccordionItem.ts

This file was deleted.

82 changes: 81 additions & 1 deletion packages/core/src/accordion/AccordionItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,87 @@
<script lang="ts">
import type { PrimitiveDefaultProps, RadixPrimitiveReturns } from '../shared/index.ts'
import { computed, type Ref } from 'vue'
import { useCollapsibleRoot } from '../collapsible/index.ts'
import { createContext, useId } from '../hooks/index.ts'
import { useAccordionContext } from './AccordionRoot.vue'

export interface AccordionItemProps {
/**
* Whether or not an accordion item is disabled from user interaction.
*
* @defaultValue false
*/
disabled?: boolean
/**
* A string value for the accordion item. All items within an accordion should use a unique value.
*/
value: string
}

export const DEFAULT_ACCORDION_ITEM_PROPS = {
disabled: undefined,
} satisfies PrimitiveDefaultProps<AccordionItemProps>

export interface AccordionItemContext {
open: Ref<boolean>
disabled: Ref<boolean | undefined>
triggerId: string
}

export const [provideAccordionItemContext, useAccordionItemContext] = createContext<AccordionItemContext>('AccordionItem')

export interface UseAccordionItemProps {
value: () => string
disabled?: () => boolean | undefined
}

export function useAccordionItem(props: UseAccordionItemProps): RadixPrimitiveReturns {
const context = useAccordionContext('AccordionItem')
const open = computed(() => {
const value = props.value()
return (value && context.value.value.includes(value)) || false
})
const disabled = computed(() => context.disabled?.() || props.disabled?.())

function onUpdateOpen(open: boolean) {
if (open)
context.onItemOpen(props.value())
else
context.onItemClose(props.value())
}

provideAccordionItemContext({
open,
disabled,
triggerId: useId(),
})

const collapsibleRoot = useCollapsibleRoot({
open() {
return open.value
},
onUpdateOpen,
disabled() {
return disabled.value
},
})

return {
attrs(extraAttrs = []) {
const collapsibleRootAttrs = {
'data-orientation': context.orientation,
}

return collapsibleRoot.attrs([collapsibleRootAttrs, ...extraAttrs])
},
}
}

</script>

<script setup lang="ts">
import { Primitive } from '../primitive/index.ts'
import { convertPropsToHookProps, normalizeAttrs } from '../shared/index.ts'
import { type AccordionItemProps, DEFAULT_ACCORDION_ITEM_PROPS, useAccordionItem } from './AccordionItem.ts'

defineOptions({
name: 'AccordionItem',
Expand Down
Loading
Loading