Separator

Horizontal separators can be built with the HTML <hr> element. However, there is no HTML element for a vertical separator. This is an accessible implementation of a Separator that supports purely decorative separators, i.e. removed from the accessibility tree, and can be styled as needed.

Usage

SeparatorExample.tsx
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
<div className="border-muted-200 my-10 max-w-md rounded-lg border p-6">
<h2 className="text-bold text-2xl font-bold">VerveUI</h2>
<p className="text-muted-500 text-lg">A UI component library.</p>
<Separator className="my-4" />
<Flex gap="10" items="center" className="h-5">
<p>Blog</p>
<Separator orientation="vertical" decorative />
<p>Docs</p>
<Separator orientation="vertical" decorative />
<p>Source</p>
</Flex>
</div>

Here's the <Separator /> component in action.

VerveUI

A UI component library.

Blog

Docs

Source

Features

  • Supports horizontal and vertical orientations.
  • Support visibility in the accessibility tree.
  • Supports purely decorative separators, i.e. removed from the accessibility tree.

Parts and their API

Separator

Visually or semantically separates content.

Props

PropTypeDefaultDescription
orientation'horizontal' | 'vertical''horizontal'The orientation of the separator.
decorativebooleanfalseWhether the separator is decorative or not.

Source

separator.tsx
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
import { type HTMLAttributes, type PropsWithChildren, forwardRef } from 'react'
import { cn } from '#app/utils/tailwind-merge.ts'
type SeparatorProps = PropsWithChildren<HTMLAttributes<HTMLDivElement>> & {
orientation?: 'horizontal' | 'vertical'
decorative?: boolean
}
/**
* Accessible implementation of a Separator. Supports purely decorative separators, i.e. removed from the accessibility tree.
*
* @component
* @example
* ```jsx
* <div className="border-muted-200 my-10 max-w-md rounded-lg border p-6">
* <h2 className="text-bold text-2xl font-bold">VerveUI</h2>
* <p className="text-muted-500 text-lg">A UI component library.</p>
* <Separator className="my-4" />
* <Flex gap="10" items="center" className="h-5">
* <p>Blog</p>
* <Separator orientation="vertical" decorative />
* <p>Docs</p>
* <Separator orientation="vertical" decorative />
* <p>Source</p>
* </Flex>
* </div>
* ```
*
* @param {string} [orientation='horizontal'] - The orientation of the separator. Can be 'horizontal' or 'vertical'.
* @param {decorative} [decorative] - Whether the separator is decorative or not.
* @param {string} [className] - Additional CSS class names.
* @param {React.HTMLAttributes<HTMLDivElement>} [props] - Additional HTML attributes.
* @returns {JSX.Element} The Separator component.
*/
const Separator = forwardRef<HTMLDivElement, SeparatorProps>(({ orientation = 'horizontal', decorative, className, ...props }, forwardedRef) => {
// if orientation is horizontal, we leave aria-orientation undefined because the default is horizontal
// if it's vertical, we need to specify it
const ariaOrientation = orientation === 'vertical' ? orientation : undefined
// If component is purely decorative, we set role as 'none' to remove it from the accessibility tree
const semanticProps = decorative ? { role: 'none' } : { 'aria-orientation': ariaOrientation, role: 'separator' }
return <div ref={forwardedRef} data-orientation={orientation} {...semanticProps} className={cn('separator', className)} {...props} />
})
Separator.displayName = 'Separator'
export { Separator }