A composable audio player component built on media-chrome, with shadcn styling and flexible controls.
The AudioPlayer component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.
<script setup lang="ts">
import type { MediaTimeDisplay } from 'media-chrome'
import type { HTMLAttributes } from 'vue'
import { ButtonGroupText } from '@repo/shadcn-vue/components/ui/button-group'
import { cn } from '@repo/shadcn-vue/lib/utils'
interface Props extends /* @vue-ignore */ Partial<MediaTimeDisplay> {
class?: HTMLAttributes['class']
}
const props = defineProps<Props>()
</script>
<template>
<ButtonGroupText
as-child
class="bg-transparent"
>
<media-time-display
:class="cn('tabular-nums', props.class)"
data-slot="audio-player-time-display"
/>
</ButtonGroupText>
</template>
<script setup lang="ts">
import type { MediaTimeRange } from 'media-chrome'
import type { HTMLAttributes } from 'vue'
import { ButtonGroupText } from '@repo/shadcn-vue/components/ui/button-group'
import { cn } from '@repo/shadcn-vue/lib/utils'
interface Props extends /* @vue-ignore */ Partial<MediaTimeRange> {
class?: HTMLAttributes['class']
}
const props = defineProps<Props>()
</script>
<template>
<ButtonGroupText
as-child
class="bg-transparent"
>
<media-time-range
:class="cn('', props.class)"
data-slot="audio-player-time-range"
/>
</ButtonGroupText>
</template>
<script setup lang="ts">
import type { MediaDurationDisplay } from 'media-chrome'
import type { HTMLAttributes } from 'vue'
import { ButtonGroupText } from '@repo/shadcn-vue/components/ui/button-group'
import { cn } from '@repo/shadcn-vue/lib/utils'
interface Props extends /* @vue-ignore */ Partial<MediaDurationDisplay> {
class?: HTMLAttributes['class']
}
const props = defineProps<Props>()
</script>
<template>
<ButtonGroupText
as-child
class="bg-transparent"
>
<media-duration-display
:class="cn('tabular-nums', props.class)"
data-slot="audio-player-duration-display"
/>
</ButtonGroupText>
</template>
<script setup lang="ts">
import type { MediaMuteButton } from 'media-chrome'
import type { HTMLAttributes } from 'vue'
import { ButtonGroupText } from '@repo/shadcn-vue/components/ui/button-group'
import { cn } from '@repo/shadcn-vue/lib/utils'
interface Props extends /* @vue-ignore */ Partial<MediaMuteButton> {
class?: HTMLAttributes['class']
}
const props = defineProps<Props>()
</script>
<template>
<ButtonGroupText
as-child
class="bg-transparent"
>
<media-mute-button
:class="cn('', props.class)"
data-slot="audio-player-mute-button"
/>
</ButtonGroupText>
</template>
<script setup lang="ts">
import type { MediaVolumeRange } from 'media-chrome'
import type { HTMLAttributes } from 'vue'
import { ButtonGroupText } from '@repo/shadcn-vue/components/ui/button-group'
import { cn } from '@repo/shadcn-vue/lib/utils'
interface Props extends /* @vue-ignore */ Partial<MediaVolumeRange> {
class?: HTMLAttributes['class']
}
const props = defineProps<Props>()
</script>
<template>
<ButtonGroupText
as-child
class="bg-transparent"
>
<media-volume-range
:class="cn('', props.class)"
data-slot="audio-player-volume-range"
/>
</ButtonGroupText>
</template>
export { default as AudioPlayer } from './AudioPlayer.vue'
export { default as AudioPlayerControlBar } from './AudioPlayerControlBar.vue'
export { default as AudioPlayerDurationDisplay } from './AudioPlayerDurationDisplay.vue'
export { default as AudioPlayerElement } from './AudioPlayerElement.vue'
export { default as AudioPlayerMuteButton } from './AudioPlayerMuteButton.vue'
export { default as AudioPlayerPlayButton } from './AudioPlayerPlayButton.vue'
export { default as AudioPlayerSeekBackwardButton } from './AudioPlayerSeekBackwardButton.vue'
export { default as AudioPlayerSeekForwardButton } from './AudioPlayerSeekForwardButton.vue'
export { default as AudioPlayerTimeDisplay } from './AudioPlayerTimeDisplay.vue'
export { default as AudioPlayerTimeRange } from './AudioPlayerTimeRange.vue'
export { default as AudioPlayerVolumeRange } from './AudioPlayerVolumeRange.vue'
Since this component uses Web Components (via media-chrome), you must configure your Vue compiler to recognize media- tags to avoid "Failed to resolve component" warnings.