Skip to content

Container ​

A container lets you center and constrain the width of your content.

Demo ​

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae numquam quod excepturi rerum vel quos? Fugit ut quidem sit odit facilis, perferendis sunt, expedita quo deserunt dolorum eligendi pariatur commodi?

This requires the following theme to be installed:

Component ​

Container.vue
vue
<script lang="ts">
import theme from '@/ui/theme/container'
import { Primitive } from 'reka-ui'
import { tv } from 'tailwind-variants'

const container = tv(theme)

export interface ContainerProps {
  as?: any
  class?: any
}

export interface ContainerSlots {
  default: (props?: object) => any
}
</script>

<script setup lang="ts">
const props = withDefaults(defineProps<ContainerProps>(), {
  as: 'div',
})
defineSlots<ContainerSlots>()
</script>

<template>
  <Primitive :as="as" :class="container({ class: props.class })">
    <slot />
  </Primitive>
</template>
Container.vue
vue
<script lang="ts">
import theme from '@/UI/Theme/container'
import { Primitive } from 'reka-ui'
import { tv } from 'tailwind-variants'

const container = tv(theme)

export interface ContainerProps {
  as?: any
  class?: any
}

export interface ContainerSlots {
  default: (props?: object) => any
}
</script>

<script setup lang="ts">
const props = withDefaults(defineProps<ContainerProps>(), {
  as: 'div',
})
defineSlots<ContainerSlots>()
</script>

<template>
  <Primitive :as="as" :class="container({ class: props.class })">
    <slot />
  </Primitive>
</template>

Theme ​

container.ts
ts
export default {
  base: '',
}
View Nuxt UI theme
container.ts
ts
export default {
  base: 'max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8',
}

Test ​

To test this component, you can use the following test file:

Container.test.ts
ts
import type { RenderOptions } from '@testing-library/vue'
import Container from '@/ui/components/Container.vue'
import { render, screen } from '@testing-library/vue'
import { describe, expect, it } from 'vitest'

describe('container', () => {
  it.each<[string, RenderOptions<typeof Container>]>([
    // Props
    ['with as', { props: { as: 'article' } }],
    ['with class', { props: { class: 'max-w-5xl' } }],
    // Slots
    ['with default slot', { slots: { default: () => 'Default slot' } }],
  ])(`renders %s correctly`, (name, options) => {
    render(Container, {
      attrs: {
        'data-testid': 'container',
      },
      ...options,
    })

    expect(screen.getByTestId('container')).toMatchSnapshot()
  })
})
Container.test.ts
ts
import type { RenderOptions } from '@testing-library/vue'
import Container from '@/UI/Components/Container.vue'
import { render, screen } from '@testing-library/vue'
import { describe, expect, it } from 'vitest'

describe('container', () => {
  it.each<[string, RenderOptions<typeof Container>]>([
    // Props
    ['with as', { props: { as: 'article' } }],
    ['with class', { props: { class: 'max-w-5xl' } }],
    // Slots
    ['with default slot', { slots: { default: () => 'Default slot' } }],
  ])(`renders %s correctly`, (name, options) => {
    render(Container, {
      attrs: {
        'data-testid': 'container',
      },
      ...options,
    })

    expect(screen.getByTestId('container')).toMatchSnapshot()
  })
})

Contributors ​

barbapapazes

Changelog ​

c615c - feat: add custom eslint rule to disallow relative imports (#81) on 1/7/2025
5f2d8 - feat: add container component (#95) on 1/2/2025