feat: Add more thinned variants to Separator
This commit is contained in:
5 files changed
+61
-27
No files matched your search
@@ -11,7 +11,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
* - Single or double line variants inspired by newspaper layout traditions
|
||||
* - Multiple color options (black, outline, outline-light) with theme support
|
||||
* - Horizontal and vertical orientations
|
||||
* - Optional thinned gradient fade effect at line ends (10% fade length)
|
||||
* - Optional thinned gradient fade effect at line ends ('thinned', 'thinned-start', 'thinned-end', 'none')
|
||||
* - 2px stroke width following print design standards
|
||||
* - Semantic div elements with proper ARIA separator role for accessibility
|
||||
*/
|
||||
@@ -44,14 +44,15 @@ const meta: Meta<typeof Separator> = {
|
||||
description: 'Orientation of the separator',
|
||||
},
|
||||
thinned: {
|
||||
control: 'boolean',
|
||||
description: 'Whether line ends should be thinned with gradient fade (10% fade length)',
|
||||
control: 'select',
|
||||
options: ['thinned', 'thinned-start', 'thinned-end', 'none'],
|
||||
description: 'How line ends should be thinned with gradient fade',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
type: 'single',
|
||||
direction: 'horizontal',
|
||||
thinned: true,
|
||||
thinned: 'thinned',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -191,7 +192,7 @@ export const VerticalDouble: Story = {
|
||||
*/
|
||||
export const NonThinned: Story = {
|
||||
args: {
|
||||
thinned: false,
|
||||
thinned: 'none',
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
@@ -251,19 +252,27 @@ export const AllTypes: Story = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Comparison between thinned and non-thinned effects.
|
||||
* Demonstrates the 10% gradient fade at line ends.
|
||||
* Comparison between different thinning effects.
|
||||
* Demonstrates the gradient fade at line ends.
|
||||
*/
|
||||
export const ThinnedComparison: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-8 w-96">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">With Thinned Ends (Default)</h3>
|
||||
<Separator thinned />
|
||||
<h3 className="text-sm font-medium mb-2">Full Thinned (Default)</h3>
|
||||
<Separator thinned="thinned" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">Without Thinned Ends</h3>
|
||||
<Separator thinned={false} />
|
||||
<h3 className="text-sm font-medium mb-2">Thinned Start Only</h3>
|
||||
<Separator thinned="thinned-start" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">Thinned End Only</h3>
|
||||
<Separator thinned="thinned-end" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">No Fading (None)</h3>
|
||||
<Separator thinned="none" />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
||||
@@ -5,6 +5,11 @@ import { VStack } from '../VStack/VStack';
|
||||
|
||||
import type { ClassNameProps, TestIdProps } from '@ermnvldmr/stl';
|
||||
|
||||
/**
|
||||
* Options for thinning the separator line ends with a gradient fade.
|
||||
*/
|
||||
export type SeparatorThinnedType = 'thinned' | 'thinned-end' | 'thinned-start' | 'none';
|
||||
|
||||
/**
|
||||
* Props for the Separator component.
|
||||
*/
|
||||
@@ -15,10 +20,32 @@ export interface SeparatorProps extends ClassNameProps, TestIdProps {
|
||||
color?: 'black' | 'outline' | 'outline-light';
|
||||
/** Orientation of the separator */
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
/** Whether line ends should be thinned with gradient fade */
|
||||
thinned?: boolean;
|
||||
/**
|
||||
* How line ends should be thinned with gradient fade.
|
||||
* - 'thinned': Both ends fade out (default)
|
||||
* - 'thinned-start': Only the start of the line fades out
|
||||
* - 'thinned-end': Only the end of the line fades out
|
||||
* - 'none': No fading, sharp edges
|
||||
*/
|
||||
thinned?: SeparatorThinnedType;
|
||||
}
|
||||
|
||||
const THINNED_TYPE_CLASSES: Record<
|
||||
'horizontal' | 'vertical',
|
||||
Record<Exclude<SeparatorThinnedType, 'none'>, string>
|
||||
> = {
|
||||
horizontal: {
|
||||
thinned: '[mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]',
|
||||
'thinned-start': '[mask-image:linear-gradient(to_right,transparent,black_10%,black)]',
|
||||
'thinned-end': '[mask-image:linear-gradient(to_right,black,black_90%,transparent)]',
|
||||
},
|
||||
vertical: {
|
||||
thinned: '[mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)]',
|
||||
'thinned-start': '[mask-image:linear-gradient(to_bottom,transparent,black_10%,black)]',
|
||||
'thinned-end': '[mask-image:linear-gradient(to_bottom,black,black_90%,transparent)]',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A separator component for dividing content sections.
|
||||
*
|
||||
@@ -26,7 +53,7 @@ export interface SeparatorProps extends ClassNameProps, TestIdProps {
|
||||
* - Single or double line variants inspired by newspaper layout traditions
|
||||
* - Multiple color options (black, outline, outline-light) with theme support
|
||||
* - Horizontal and vertical orientations
|
||||
* - Optional thinned gradient fade effect at line ends (10% fade length)
|
||||
* - Optional thinned gradient fade effect at line ends ('thinned', 'thinned-start', 'thinned-end', 'none')
|
||||
* - 2px stroke width following print design standards
|
||||
* - Semantic HTML with proper ARIA attributes for accessibility
|
||||
*
|
||||
@@ -35,14 +62,17 @@ export interface SeparatorProps extends ClassNameProps, TestIdProps {
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* // Basic horizontal separator
|
||||
* // Basic horizontal separator (defaults to thinned)
|
||||
* <Separator />
|
||||
*
|
||||
* // Double-line separator with black color
|
||||
* <Separator type="double" color="black" />
|
||||
*
|
||||
* // Vertical separator without thinned ends
|
||||
* <Separator direction="vertical" thinned={false} />
|
||||
* <Separator direction="vertical" thinned="none" />
|
||||
*
|
||||
* // Separator with only the end thinned
|
||||
* <Separator thinned="thinned-end" />
|
||||
*
|
||||
* // Light separator for subtle content division
|
||||
* <Separator color="outline-light" />
|
||||
@@ -52,7 +82,7 @@ export const Separator = memo(function Separator({
|
||||
type = 'single',
|
||||
color,
|
||||
direction = 'horizontal',
|
||||
thinned = true,
|
||||
thinned = 'thinned',
|
||||
className,
|
||||
'data-testid': testId,
|
||||
}: SeparatorProps) {
|
||||
@@ -77,13 +107,8 @@ export const Separator = memo(function Separator({
|
||||
];
|
||||
|
||||
// Thinned effect using CSS mask
|
||||
const thinnedClasses = thinned
|
||||
? [
|
||||
direction === 'horizontal'
|
||||
? '[mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]'
|
||||
: '[mask-image:linear-gradient(to_bottom,transparent,black_10%,black_90%,transparent)]',
|
||||
]
|
||||
: [];
|
||||
const thinnedClasses =
|
||||
thinned !== 'none' ? [THINNED_TYPE_CLASSES[direction][thinned]] : [];
|
||||
|
||||
// Size classes - fill container by default
|
||||
const sizeClasses =
|
||||
|
||||
@@ -35,7 +35,7 @@ export function ThemeSwitch(): React.JSX.Element {
|
||||
/>
|
||||
<Moon className="w-4 h-4 text-[var(--rb-text)] opacity-60" />
|
||||
</HStack>
|
||||
<Separator direction="vertical" thinned={false} />
|
||||
<Separator direction="vertical" thinned="none" />
|
||||
<Button
|
||||
aria-label="Follow system theme"
|
||||
color={preference === 'system' ? 'primary' : 'neutral'}
|
||||
|
||||
Reference in new issue
Block a user