Skip to content
Merged
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
56 changes: 35 additions & 21 deletions apps/www/src/content/docs/components/headline/demo.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,66 @@
"use client";
'use client';

import { getPropsString } from "@/lib/utils";
import { getPropsString } from '@/lib/utils';

export const getCode = (props: any) => {
export const getCode = (props: Record<string, unknown>) => {
const { children, ...rest } = props;
return `<Headline${getPropsString(rest)}>${children}</Headline>`;
};

export const playground = {
type: "playground",
type: 'playground',
controls: {
size: {
type: "select",
options: ["t1", "t2", "t3", "t4"],
defaultValue: "t1",
type: 'select',
options: ['t1', 't2', 't3', 't4'],
defaultValue: 't1'
},
weight: {
type: 'select',
options: ['regular', 'medium'],
defaultValue: 'medium'
},
as: {
type: "select",
options: ["h1", "h2", "h3", "h4", "h5", "h6"],
defaultValue: "h2",
type: 'select',
options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
defaultValue: 'h2'
},
align: {
type: "select",
options: ["left", "center", "right"],
defaultValue: "left",
initialValue: "center",
type: 'select',
options: ['left', 'center', 'right'],
defaultValue: 'left',
initialValue: 'center'
},
truncate: { type: "checkbox", defaultValue: false },
children: { type: "text", initialValue: "This is a Headline" },
truncate: { type: 'checkbox', defaultValue: false },
children: { type: 'text', initialValue: 'This is a Headline' }
},
getCode,
getCode
};

export const alignDemo = {
type: "code",
type: 'code',
code: `
<Flex direction="column" style={{width:"100%"}} gap="large">
<Headline size="small" align="left">Left Aligned</Headline>
<Headline size="small" align="center">Center Aligned</Headline>
<Headline size="small" align="right">Right Aligned</Headline>
</Flex>`,
</Flex>`
};
export const truncateDemo = {
type: "code",
type: 'code',
code: `
<Flex style={{ width: "200px" }}>
<Headline size="small" truncate>
This is a very long headline that will be truncated with an ellipsis
</Headline>
</Flex>`,
</Flex>`
};

export const weightDemo = {
type: 'code',
code: `
<Flex direction="column" style={{width:"100%"}} gap="large">
<Headline size="t2" weight="regular">Regular Weight Headline</Headline>
<Headline size="t2" weight="medium">Medium Weight Headline</Headline>
</Flex>`
};
7 changes: 6 additions & 1 deletion apps/www/src/content/docs/components/headline/index.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
---
title: Headline
description: A typographic component for displaying headings with different sizes and alignments.
tag: update
---

import { playground, alignDemo, truncateDemo } from "./demo.ts";
import { playground, alignDemo, truncateDemo, weightDemo } from "./demo.ts";

<Demo data={playground} />

Expand All @@ -23,6 +24,10 @@ import { Headline } from '@raystack/apsara'

<Demo data={alignDemo} />

### Weight

<Demo data={weightDemo} />

### Truncation

<Demo data={truncateDemo} />
12 changes: 9 additions & 3 deletions apps/www/src/content/docs/components/headline/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@ export interface HeadlineProps {
* Controls the size of the headline.
* @default "t1"
*/
size?: "t1" | "t2" | "t3" | "t4";
size?: 't1' | 't2' | 't3' | 't4';

/**
* The headline weight.
* @default "medium"
*/
weight?: 'regular' | 'medium';

/**
* HTML heading element to render.
* @default "h2"
*/
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';

/**
* Text alignment.
* @default "left"
*/
align?: "left" | "center" | "right";
align?: 'left' | 'center' | 'right';

/**
* Enable text truncation with ellipsis.
Expand Down
8 changes: 7 additions & 1 deletion apps/www/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"]
}
20 changes: 20 additions & 0 deletions packages/raystack/components/headline/__tests__/headline.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ describe('Headline', () => {
});
});

describe('Weight', () => {
it('renders regular weight correctly', () => {
render(<Headline weight='regular'>Heading</Headline>);
const heading = screen.getByText('Heading');
expect(heading).toHaveClass(styles['headline-weight-regular']);
});

it('renders medium weight correctly', () => {
render(<Headline weight='medium'>Heading</Headline>);
const heading = screen.getByText('Heading');
expect(heading).toHaveClass(styles['headline-weight-medium']);
});

it('defaults to medium weight', () => {
render(<Headline>Heading</Headline>);
const heading = screen.getByText('Heading');
expect(heading).toHaveClass(styles['headline-weight-medium']);
});
});

describe('Alignment', () => {
const alignments = ['left', 'center', 'right'] as const;

Expand Down
9 changes: 9 additions & 0 deletions packages/raystack/components/headline/headline.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@
width: 100%;
max-width: 100%;
}

/* Headline Weight */
.headline-weight-regular {
font-weight: var(--rs-font-weight-regular);
}

.headline-weight-medium {
font-weight: var(--rs-font-weight-medium);
}
65 changes: 39 additions & 26 deletions packages/raystack/components/headline/headline.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,73 @@
import { cva, type VariantProps } from "class-variance-authority";
import { forwardRef, HTMLAttributes } from "react";
import { type VariantProps, cva } from 'class-variance-authority';
import { HTMLAttributes, forwardRef } from 'react';

import styles from "./headline.module.css";
import styles from './headline.module.css';

const headline = cva(styles.headline, {
variants: {
size: {
t1: styles["headline-t1"],
t2: styles["headline-t2"],
t3: styles["headline-t3"],
t4: styles["headline-t4"],
small: styles["headline-small"],
medium: styles["headline-medium"],
large: styles["headline-large"],
t1: styles['headline-t1'],
t2: styles['headline-t2'],
t3: styles['headline-t3'],
t4: styles['headline-t4'],
small: styles['headline-small'],
medium: styles['headline-medium'],
large: styles['headline-large']
},
weight: {
regular: styles['headline-weight-regular'],
medium: styles['headline-weight-medium']
},
align: {
left: styles["headline-align-left"],
center: styles["headline-align-center"],
right: styles["headline-align-right"],
left: styles['headline-align-left'],
center: styles['headline-align-center'],
right: styles['headline-align-right']
},
truncate: {
true: styles["headline-truncate"],
},
true: styles['headline-truncate']
}
},
defaultVariants: {
size: "t2",
align: "left",
truncate: false,
},
size: 't2',
weight: 'medium',
align: 'left',
truncate: false
}
});

export type HeadlineBaseProps = VariantProps<typeof headline> & {
/**
* @remarks Use "t1" | "t2" | "t3" | "t4"
*/
size?: "t1" | "t2" | "t3" | "t4" | "small" | "medium" | "large";
size?: 't1' | 't2' | 't3' | 't4' | 'small' | 'medium' | 'large';
};

type HeadlineProps = HeadlineBaseProps &
HTMLAttributes<HTMLHeadingElement> & {
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
};

export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>(
(
{ className, size, align, truncate, as: Component = "h2", ...props },
ref,
{
className,
size,
weight,
align,
truncate,
as: Component = 'h2',
...props
},
ref
) => {
return (
<Component
ref={ref}
className={headline({ size, align, truncate, className })}
className={headline({ size, weight, align, truncate, className })}
{...props}
/>
);
},
}
);

Headline.displayName = "Headline";
Headline.displayName = 'Headline';