Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
samithaf committed Dec 15, 2023
2 parents 44d466a + c7290e9 commit c00ac0c
Show file tree
Hide file tree
Showing 18 changed files with 330 additions and 40 deletions.
1 change: 1 addition & 0 deletions apps/site/src/components/code/code.inject-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export {
Selector,
Grid,
Item,
Heading,
} from '@westpac/ui';

export {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
Render the heading in uppercase. Line height is adjusted as necessary.

```jsx
<Fragment>
<h1 className="typography-body-3 uppercase">Heading</h1>
<h1 className="typography-brand-3 uppercase">BrandHeading</h2>
</Fragment>
```
No specific accessibility attributes required.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
There are two heading component options: Heading and BrandHeading. Heading renders in body font and BrandHeading in brand font.

```jsx
<Fragment>
<h1 className="typography-body-1">Heading</h1>
<h1 className="typography-brand-1">BrandHeading</h1>
</Fragment>
<>
<Heading tag="h1" size={1}>Heading</Heading>
<Heading tag="h1" size={1} brandHeading>BrandHeading</Heading>
</>
```
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ Headings are visually sized using the typographic scale and may be set as either
#### Fixed sizing

```jsx
<Fragment>
<h1 className="typography-body-1">Heading size 1</h1>
<h1 className="typography-body-2">Heading size 2</h1>
<h1 className="typography-body-3">Heading size 3</h1>
<h1 className="typography-body-4">Heading size 4</h1>
<h1 className="typography-body-5">Heading size 5</h1>
<h1 className="typography-body-6">Heading size 6</h1>
<h1 className="typography-body-7">Heading size 7</h1>
<h1 className="typography-body-8">Heading size 8</h1>
<h1 className="typography-body-9">Heading size 9</h1>
<h1 className="typography-body-10">Heading size 10</h1>
</Fragment>
() => {
const sizes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
return (
<>
{sizes.map(size => (
<Heading size={size} key={size}>
Heading size {size}
</Heading>
))}
</>
);
}
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Define the heading element tag (<h1> - <h6>). This will be determined by the size if a tag is not provided.

```jsx
<Fragment>
<h1 className="typography-body-3">Heading tag h1 size 3</h1>
<h2 className="typography-body-5">Heading tag h2 size 5</h2>
</Fragment>
<>
<Heading tag="h1" size={3}>Heading tag h1 size 3</Heading>
<Heading tag="h2" size={5}>Heading tag h2 size 5</Heading>
</>
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Render the heading in uppercase. Line height is adjusted as necessary.

```jsx
<Fragment>
<h1 className="typography-body-3 uppercase">Heading</h1>
<h1 className="typography-brand-3 uppercase">BrandHeading</h2>
</Fragment>
<>
<Heading size={1} uppercase>Heading</Heading>
<Heading size={1} brandHeading uppercase>BrandHeading</Heading>
</>
```
3 changes: 3 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
"./grid": {
"default": "./dist/components/grid/index.js"
},
"./heading": {
"default": "./dist/components/heading/index.js"
},
"./icon": {
"default": "./dist/components/icon/index.js"
},
Expand Down
23 changes: 17 additions & 6 deletions packages/ui/src/components/autocomplete/autocomplete.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useMemo } from 'react';
import { mergeProps, useButton, useComboBox, useFilter, useFocusRing, useSearchField } from 'react-aria';
import { Item, useComboBoxState, useSearchFieldState } from 'react-stately';

import { ClearIcon } from '../icon/index.js';
import { ClearIcon, SearchIcon } from '../icon/index.js';
import { ErrorMessage, FormHint, FormLabel } from '../index.js';

import { styles as autocompleteStyles } from './autocomplete.styles.js';
Expand Down Expand Up @@ -37,6 +37,7 @@ export function Autocomplete<T extends object>({
errorMessage,
hintMessage,
noOptionsMessage,
className,
...props
}: AutocompleteProps<T>) {
const { contains } = useFilter({ sensitivity: 'base' });
Expand All @@ -57,14 +58,11 @@ export function Autocomplete<T extends object>({
state,
);

const styles = autocompleteStyles({
const { clearButton: clearButtonStyle, ...styles } = autocompleteStyles({
isDisabled,
isInputFocusVisible,
size,
invalid,
});

const { clearButton: clearButtonStyle } = autocompleteStyles({
isFocusVisible,
});

Expand Down Expand Up @@ -93,13 +91,26 @@ export function Autocomplete<T extends object>({
);
}, [state, searchProps, noOptionsMessage]);

const iconSize = useMemo(() => {
switch (size) {
case 'small':
case 'medium':
return 'small';
default:
return 'medium';
}
}, [size]);

return (
<div className={styles.base()}>
<div className={styles.base({ className })}>
<FormLabel {...labelProps}>{props.label}</FormLabel>
{hintMessage && <FormHint {...descriptionProps}>{hintMessage}</FormHint>}
{errorMessage && <ErrorMessage {...errorMessageProps} message={errorMessage} />}

<div ref={outerRef} className={styles.outerWrapper()}>
<div className={styles.iconWrapper()}>
<SearchIcon aria-hidden size={iconSize} />
</div>
<input {...mergeProps(inputProps, inputFocusProps)} ref={inputRef} className={styles.input()} />

<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('Autocomplete', () => {
expect(style.input()).toBe('w-full appearance-none bg-[transparent] outline-none form-control-large');
expect(style.label()).toBe('block text-left text-sm font-medium text-text');
expect(style.outerWrapper()).toBe(
'form-control relative flex w-full flex-row items-center overflow-hidden pr-2 disabled:form-control-disabled',
'form-control relative flex w-full flex-row items-stretch overflow-hidden pr-2 disabled:form-control-disabled',
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ export const styles = tv(
base: 'relative flex flex-col',
label: 'block text-left text-sm font-medium text-text',
outerWrapper:
'form-control relative flex w-full flex-row items-center overflow-hidden pr-2 disabled:form-control-disabled',
'form-control relative flex w-full flex-row items-stretch overflow-hidden pr-2 disabled:form-control-disabled',
input: 'w-full appearance-none bg-[transparent] outline-none',
clearButton: 'flex cursor-default items-center justify-center text-text-50 hover:text-border-60',
iconWrapper: 'flex flex-col justify-center',
},
variants: {
invalid: {
Expand All @@ -22,15 +23,19 @@ export const styles = tv(
size: {
small: {
input: 'form-control-small',
iconWrapper: 'pl-1',
},
medium: {
input: 'form-control-medium',
iconWrapper: 'pl-1.5',
},
large: {
input: 'form-control-large',
iconWrapper: 'pl-1.5',
},
xlarge: {
input: 'form-control-xlarge',
iconWrapper: 'pl-2',
},
},
isDisabled: {
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/components/autocomplete/autocomplete.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import { PopoverProps } from './components/index.js';
type Variants = VariantProps<typeof styles>;

export type AutocompleteProps<T extends object> = {
/**
* className
*/
className?: string;
/**
* error message
*/
Expand Down
26 changes: 26 additions & 0 deletions packages/ui/src/components/heading/heading.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

import { styles } from './heading.styles.js';
import { type HeadingProps } from './heading.types.js';

export function Heading({ className, tag, brandHeading, size, children, uppercase, ...props }: HeadingProps) {
const sizeToTag = {
1: 'h1',
2: 'h2',
3: 'h3',
4: 'h4',
5: 'h5',
6: 'h6',
7: 'h6',
8: 'h6',
9: 'h6',
10: 'h6',
};
const Tag = typeof size === 'number' && !tag ? (sizeToTag[size] as keyof HeadingProps['tag']) : tag ? tag : 'h6';

return (
<Tag className={styles({ className, brandHeading, size, uppercase })} {...props}>
{children}
</Tag>
);
}
36 changes: 36 additions & 0 deletions packages/ui/src/components/heading/heading.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { render } from '@testing-library/react';

import { Heading } from './heading.component.js';
import { styles } from './heading.styles.js';
import { HeadingProps } from './heading.types.js';

describe('Heading', () => {
it('renders the component', () => {
const { container } = render(<Heading size={1}>Heading</Heading>);
expect(container).toBeInTheDocument();
});

it('should have the correct size', () => {
const sizes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
sizes.forEach((size: any) => {
const { getByTestId } = render(
<Heading data-testid={size} size={size}>
Heading
</Heading>,
);
expect(getByTestId(size)).toHaveClass(`typography-body-${size}`);
});
});

it('should have the heading tag', () => {
const headingLevels = [1, 2, 3, 4, 5, 6];
headingLevels.forEach((level: any) => {
const { getByRole } = render(
<Heading tag={`h${level}` as keyof HeadingProps['tag']} size={1}>
Heading
</Heading>,
);
expect(getByRole('heading', { level: level })).toBeInTheDocument();
});
});
});
100 changes: 100 additions & 0 deletions packages/ui/src/components/heading/heading.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { type Meta, StoryFn, type StoryObj } from '@storybook/react';

import { Heading } from './heading.component.js';
import { HeadingProps } from './heading.types.js';

const meta: Meta<typeof Heading> = {
title: 'Components/Heading',
component: Heading,
tags: ['autodocs'],
decorators: [(Story: StoryFn) => <Story />],
parameters: {
layout: 'centered',
},
};

export default meta;
type Story = StoryObj<typeof meta>;

const sizes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

/**
* > Default usage example
*/
export const Default = () => {
return sizes.map((size: any) => <Heading size={size}>Heading size: {size}</Heading>);
};

/**
* > With tag prop
*/
export const WithTag = () => {
return sizes.map((size: any) => (
<Heading tag={size > 1 ? 'h1' : 'h2'} size={size}>
Heading tag:{size > 1 ? ' h1' : ' h2'} size: {size}
</Heading>
));
};

/**
* > Brand usage example
*/
export const Brand = () => {
return sizes.map((size: any) => (
<Heading size={size} brandHeading>
Heading size: {size}
</Heading>
));
};

/**
* > With tag and brand prop
*/
export const WithTagAndBrand = () => {
return sizes.map((size: any) => (
<Heading tag={size > 1 ? 'h1' : 'h2'} size={size} brandHeading>
Heading tag:{size > 1 ? ' h1' : ' h2'} size: {size}
</Heading>
));
};

/**
* > Uppercase usage example
*/
export const Uppercase = () => {
return sizes.map((size: any) => (
<Heading size={size} uppercase>
Heading size: {size}
</Heading>
));
};

/**
* > Responsive usage example
*/
export const Responsive = () => {
return (
<>
<Heading size={{ xsl: 10, sm: 8, md: 6, lg: 4, xl: 2 }}>
Heading size: [xsl: 10, sm: 8, md: 6, lg: 4, xl: 2 ]
</Heading>
<Heading size={{ xsl: 10, xl: 2 }}>Heading size: [xsl: 10, xl: 2]</Heading>
</>
);
};

/**
* > Responsive with tag usage example
*/
export const ResponsiveWithTag = () => {
return (
<>
<Heading tag="h2" size={{ xsl: 10, sm: 8, md: 6, lg: 4, xl: 2 }}>
Heading tag: h2 size: [xsl: 10, sm: 8, md: 6, lg: 4, xl: 2 ]
</Heading>
<Heading tag="h2" size={{ xsl: 10, xl: 2 }}>
Heading tag: h2 size: [xsl: 10, xl: 2]
</Heading>
</>
);
};
Loading

1 comment on commit c00ac0c

@vercel
Copy link

@vercel vercel bot commented on c00ac0c Dec 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

gel-next-site – ./apps/site

gel-next-site.vercel.app
gel-next-site-git-main-westpacgel.vercel.app
gel-next-site-westpacgel.vercel.app

Please sign in to comment.