Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react): add Placeholder color props #6232

Merged
merged 4 commits into from
Dec 11, 2024
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
5 changes: 5 additions & 0 deletions .changeset/add-placeholder-color-props.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/ui-react": patch
---

feat(react): add Placeholder color props
14 changes: 14 additions & 0 deletions docs/__tests__/__snapshots__/props-table.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8095,6 +8095,13 @@ exports[`Props Table 1`] = `
"category": "BaseComponentProps",
"isOptional": true
},
"endColor": {
"name": "endColor",
"type": "StyleToken<Property.Color> | undefined",
"description": "This property will change the animation end color of the placeholder component",
"category": "BasePlaceholderProps",
"isOptional": true
},
"isLoaded": {
"name": "isLoaded",
"type": "boolean | undefined",
Expand All @@ -8109,6 +8116,13 @@ exports[`Props Table 1`] = `
"category": "BasePlaceholderProps",
"isOptional": true
},
"startColor": {
"name": "startColor",
"type": "StyleToken<Property.Color> | undefined",
"description": "This property will change the animation start color of the placeholder component",
"category": "BasePlaceholderProps",
"isOptional": true
},
"isDisabled": {
"name": "isDisabled",
"type": "boolean | undefined",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import {
PlaceholderProps,
SelectField,
SwitchField,
TextField,
} from '@aws-amplify/ui-react';

export interface PlaceholderPropControlsProps extends PlaceholderProps {
setStartColor: (
value: React.SetStateAction<PlaceholderProps['startColor']>
) => void;
setEndColor: (
value: React.SetStateAction<PlaceholderProps['endColor']>
) => void;
setSize: (value: React.SetStateAction<PlaceholderProps['size']>) => void;
setIsLoaded: (
value: React.SetStateAction<PlaceholderProps['isLoaded']>
Expand All @@ -18,13 +25,35 @@ interface PlaceholderPropControlsInterface {
}

export const PlaceholderControls: PlaceholderPropControlsInterface = ({
startColor,
setStartColor,
endColor,
setEndColor,
size,
setSize,
isLoaded,
setIsLoaded,
}) => {
return (
<Flex direction="column">
<TextField
placeholder="Set start color"
name="startColor"
value={startColor as string}
onChange={(event: any) => {
setStartColor(event.target.value);
}}
label="startColor"
/>
<TextField
placeholder="Set end color"
name="endColor"
value={endColor as string}
onChange={(event: any) => {
setEndColor(event.target.value);
}}
label="endColor"
/>
<SelectField
value={size}
onChange={(e) =>
Expand Down
6 changes: 5 additions & 1 deletion docs/src/pages/[platform]/components/placeholder/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { demoState } from '@/utils/demoState';
const propsToCode = (props: PlaceholderProps) => {
return (
'<Placeholder' +
(props.startColor ? ` startColor="${props.startColor}"` : '') +
(props.endColor ? ` endColor="${props.endColor}"` : '') +
(props.size ? ` size="${props.size}"` : '') +
(props.isLoaded ? ` isLoaded={${props.isLoaded}}` : '') +
' />'
Expand All @@ -28,8 +30,10 @@ export const PlaceholderDemo = () => {
propControls={<PlaceholderControls {...placeholderProps} />}
>
<Placeholder
isLoaded={placeholderProps.isLoaded}
startColor={placeholderProps.startColor}
endColor={placeholderProps.endColor}
size={placeholderProps.size}
isLoaded={placeholderProps.isLoaded}
/>
</Demo>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Placeholder, useTheme } from '@aws-amplify/ui-react';

export const PlaceholderColorExample = () => {
const { tokens } = useTheme();
return (
<Placeholder
startColor={tokens.colors.neutral[80]}
endColor={tokens.colors.teal[40]}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { DefaultPlaceholderExample } from './DefaultPlaceholderExample';
export { PlaceholderIsLoadedExample } from './PlaceholderIsLoadedExample';
export { PlaceholderSizeExample } from './PlaceholderSizeExample';
export { PlaceholderColorExample } from './PlaceholderColorExample';
export { PlaceholderStylePropsExample } from './PlaceholderStylePropsExample';
export { PlaceholderThemeExample } from './PlaceholderThemeExample';
13 changes: 13 additions & 0 deletions docs/src/pages/[platform]/components/placeholder/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Placeholder } from '@aws-amplify/ui-react';
import { PlaceholderDemo } from './demo';
import {
DefaultPlaceholderExample,
PlaceholderColorExample,
PlaceholderIsLoadedExample,
PlaceholderSizeExample,
PlaceholderStylePropsExample,
Expand Down Expand Up @@ -59,6 +60,18 @@ Use the `size` prop to change the Placeholder size. Available options are `small
</ExampleCode>
</Example>

### Colors

Pass `startColor` and `endColor` props to color your own Placeholder.

<Example>
<PlaceholderColorExample />
<ExampleCode>
```jsx file=./examples/PlaceholderColorExample.tsx
```
</ExampleCode>
</Example>

## Customization

<ThemeExample component="Placeholder">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ interface UsePlaceholderProps {
}

export const usePlaceholderProps: UsePlaceholderProps = (initialValues) => {
const [startColor, setStartColor] = React.useState<
PlaceholderProps['startColor']
>(initialValues.startColor);
const [endColor, setEndColor] = React.useState<PlaceholderProps['endColor']>(
initialValues.endColor
);
const [size, setSize] = React.useState<PlaceholderProps['size']>(
initialValues.size
);
Expand All @@ -18,18 +24,33 @@ export const usePlaceholderProps: UsePlaceholderProps = (initialValues) => {

React.useEffect(() => {
demoState.set(Placeholder.displayName, {
startColor,
endColor,
size,
isLoaded,
});
}, [size, isLoaded]);
}, [startColor, endColor, size, isLoaded]);

return React.useMemo(
() => ({
startColor,
setStartColor,
endColor,
setEndColor,
size,
setSize,
isLoaded,
setIsLoaded,
}),
[size, setSize, isLoaded, setIsLoaded]
[
startColor,
setStartColor,
endColor,
setEndColor,
size,
setSize,
isLoaded,
setIsLoaded,
]
);
};
6 changes: 6 additions & 0 deletions packages/react/__tests__/__snapshots__/exports.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10106,6 +10106,9 @@ exports[`primitive catalog should match primitives catalog snapshot 1`] = `
"display": {
"type": "string",
},
"endColor": {
"type": "string",
},
"flex": {
"type": "string",
},
Expand Down Expand Up @@ -10262,6 +10265,9 @@ exports[`primitive catalog should match primitives catalog snapshot 1`] = `
"size": {
"type": "string",
},
"startColor": {
"type": "string",
},
"testId": {
"type": "string",
},
Expand Down
11 changes: 10 additions & 1 deletion packages/react/src/primitives/Placeholder/Placeholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ import {
import { View } from '../View';
import { primitiveWithForwardRef } from '../utils/primitiveWithForwardRef';

export const CSS_VAR_START_COLOR: string =
Copy link
Member Author

@tiffanynwyeung tiffanynwyeung Dec 2, 2024

Choose a reason for hiding this comment

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

Note: the explicit type declaration here is because csstype deliberately does not recognize CSS variables/custom properties, and they recommend doing either module augmentation or type assertions as a workaround to type errors.

I'm also not too sure about how best to name these constants so feedback/suggestions are welcomed.

'--amplify-components-placeholder-start-color';
export const CSS_VAR_END_COLOR: string =
'--amplify-components-placeholder-end-color';

const PlaceholderPrimitive: Primitive<PlaceholderProps, 'div'> = (
{ className, children, isLoaded, size, ...rest },
{ className, children, endColor, isLoaded, size, startColor, ...rest },
ref
) => {
if (isLoaded) {
Expand All @@ -28,6 +33,10 @@ const PlaceholderPrimitive: Primitive<PlaceholderProps, 'div'> = (
className
)}
ref={ref}
style={{
[CSS_VAR_START_COLOR]: startColor && `${startColor}`,
[CSS_VAR_END_COLOR]: endColor && `${endColor}`,
}}
{...rest}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';

import { Placeholder } from '../Placeholder';
import {
CSS_VAR_END_COLOR,
CSS_VAR_START_COLOR,
Placeholder,
} from '../Placeholder';
import { Text } from '../../Text';
import { ComponentClassName } from '@aws-amplify/ui';

Expand All @@ -14,6 +18,8 @@ describe('Placeholder:', () => {
true
);
expect(placeholder.dataset['size']).toBeUndefined();
expect(placeholder.dataset['startColor']).toBeUndefined();
expect(placeholder.dataset['endColor']).toBeUndefined();
});

it('should render size classes for Placeholder', async () => {
Expand Down Expand Up @@ -86,6 +92,25 @@ describe('Placeholder:', () => {
);
});

it('can apply startColor and endColor styling via props', async () => {
const startColor = 'green';
const endColor = 'gray';
render(
<Placeholder
startColor={startColor}
endColor={endColor}
testId="placeholderId"
/>
);
const placeholder = await screen.findByTestId('placeholderId');
expect(placeholder.style.getPropertyValue(CSS_VAR_START_COLOR)).toBe(
startColor
);
expect(placeholder.style.getPropertyValue(CSS_VAR_END_COLOR)).toBe(
endColor
);
});

it('can apply styling via props', async () => {
render(<Placeholder height="123px" width="50%" testId="placeholderId" />);
const placeholder = await screen.findByTestId('placeholderId');
Expand Down
15 changes: 15 additions & 0 deletions packages/react/src/primitives/types/placeholder.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Property } from 'csstype';

import { Sizes } from './base';
import { StyleToken } from './style';
import { ElementType, PrimitiveProps, BaseViewProps } from './view';

export type PlaceholderSizes = Sizes;

/** @deprecated For internal use only */
export interface BasePlaceholderProps extends BaseViewProps {
/**
* @description
* This property will change the animation end color of the placeholder component
*/
endColor?: StyleToken<Property.Color>;

/**
* @description
* If true, the placeholder won't show, if false the placeholder will show.
Expand All @@ -18,6 +27,12 @@ export interface BasePlaceholderProps extends BaseViewProps {
* Controls the display size of placeholder
*/
size?: PlaceholderSizes;

/**
* @description
* This property will change the animation start color of the placeholder component
*/
startColor?: StyleToken<Property.Color>;
}

export type PlaceholderProps<Element extends ElementType = 'div'> =
Expand Down
Loading