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

Size prop added to ImageInput component #1260

Merged
merged 34 commits into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e9eddd2
bit and byte added to border radius theme story
giedoka Nov 8, 2021
f929b1c
radius added to giga avatar
giedoka Nov 8, 2021
5572bb1
yotta size added to ImageInput
giedoka Nov 8, 2021
9cfdc77
Avatar snapshot updated due to border radius change
giedoka Nov 8, 2021
d28f119
types added to radius function in Avatar
giedoka Nov 8, 2021
bade336
size added to ImageInputProps to component field
giedoka Nov 8, 2021
2e2be27
giga removed from radius
giedoka Nov 9, 2021
a88e1c1
ActionButtonProps added to ImageInput
giedoka Nov 9, 2021
682a6fc
prettier and lint fixes
giedoka Nov 9, 2021
2abe03b
avatar radius - return changed to assignment
giedoka Nov 9, 2021
84d2198
snapshot test for giga imageinput added
giedoka Nov 9, 2021
8e05b47
Create cool-pandas-fly.md
giedoka Nov 9, 2021
e34e103
Update .changeset/cool-pandas-fly.md
giedoka Nov 10, 2021
48cad92
Update .changeset/cool-pandas-fly.md
giedoka Nov 10, 2021
2d59cdc
Update packages/circuit-ui/components/ImageInput/ImageInput.spec.tsx
giedoka Nov 10, 2021
3bf0d2e
unnecessary extra line removed
giedoka Nov 10, 2021
42ad65e
Merge remote-tracking branch 'origin/feature/image-input-size' into f…
giedoka Nov 10, 2021
56c31f9
snapshot updated
giedoka Nov 10, 2021
be5e128
borderStyles added and snapshots updated
giedoka Nov 10, 2021
70f93f9
Story for giga avatar image input added
giedoka Nov 15, 2021
975f05d
ImageInput size prop changed to buttonSize and snapshot updated
giedoka Nov 15, 2021
7fca1d6
lint fixes
giedoka Nov 15, 2021
1360b5d
new changeset added
giedoka Nov 15, 2021
1d4ba08
Required type added
giedoka Nov 15, 2021
c6ae6ec
Fix Avatar types
Nov 15, 2021
34a165c
Update packages/circuit-ui/components/ImageInput/ImageInput.tsx
giedoka Nov 17, 2021
65bd5b2
Update .changeset/nice-toys-reply.md
giedoka Nov 17, 2021
5a08deb
Update packages/circuit-ui/components/ImageInput/ImageInput.tsx
giedoka Nov 17, 2021
7680520
Update packages/circuit-ui/components/ImageInput/ImageInput.tsx
giedoka Nov 17, 2021
6fd208b
CR fixes
giedoka Nov 17, 2021
d2d19bf
Merge remote-tracking branch 'origin/feature/image-input-size' into f…
giedoka Nov 17, 2021
549ef0f
snapshot and story updated
giedoka Nov 17, 2021
1dffb64
test fix
giedoka Nov 17, 2021
1f5718a
Update packages/circuit-ui/components/ImageInput/ImageInput.tsx
giedoka Nov 17, 2021
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/nice-toys-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/circuit-ui': patch
---

Adjusted the border radius of the `Avatar` component when `size="giga"` and `variant="object"`.
5 changes: 5 additions & 0 deletions .changeset/purple-months-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/circuit-ui': minor
---

Added an optional `size` prop to the `ImageInput` component to change the action button's size.
5 changes: 3 additions & 2 deletions docs/features/theme.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,14 @@ theme.iconSizes.[kilo|mega|giga]
## Border radius

```
theme.borderRadius.[kilo|mega|giga|circle|pill]
theme.borderRadius.[bit|byte|kilo|mega|circle|pill]
robinmetral marked this conversation as resolved.
Show resolved Hide resolved
```

<Preview>
<BorderRadius size="bit" />
<BorderRadius size="byte" />
<BorderRadius size="kilo" />
<BorderRadius size="mega" />
<BorderRadius size="giga" />
<BorderRadius size="circle" />
<BorderRadius size="pill" style={{ height: '16px' }} />
</Preview>
Expand Down
46 changes: 34 additions & 12 deletions packages/circuit-ui/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import isPropValid from '@emotion/is-prop-valid';

import styled, { StyleProps } from '../../styles/styled';

type AvatarSize = 'giga' | 'yotta';
type AvatarVariant = 'object' | 'identity';

export interface AvatarProps extends ImgHTMLAttributes<HTMLImageElement> {
/**
* The source URL of the Avatar image.
Expand All @@ -33,11 +36,11 @@ export interface AvatarProps extends ImgHTMLAttributes<HTMLImageElement> {
* The variant of the Avatar, either identity or object. Refer to the docs for usage guidelines.
* The variant also changes which placeholder is rendered when the `src` prop is not provided.
*/
variant?: 'object' | 'identity';
variant?: AvatarVariant;
/**
* One of two available sizes for the Avatar, either giga or yotta.
*/
size?: 'giga' | 'yotta';
size?: AvatarSize;
}

const avatarSizes = {
Expand All @@ -52,26 +55,45 @@ const placeholders = {
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 96 96"><path fill="white" d="M48 18c-7.732 0-14 6.268-14 14s6.268 14 14 14 14-6.268 14-14-6.268-14-14-14zM47.9998 88C61.53 88 73.4913 81.2822 80.73 71c-7.2387-10.2822-19.2-17-32.7303-17-13.5302 0-25.4914 6.7178-32.7302 17 7.2388 10.2822 19.2 17 32.7303 17z"/></svg>',
};

const baseStyles = ({
theme,
variant,
size = 'yotta',
}: AvatarProps & StyleProps) => css`
type StyledImageProps = Omit<AvatarProps, 'size' | 'variant'> & {
size: AvatarSize;
variant: AvatarVariant;
};

const baseStyles = ({ theme, size }: StyledImageProps & StyleProps) => css`
display: block;
width: ${avatarSizes[size]};
height: ${avatarSizes[size]};
box-shadow: 0 0 0 ${theme.borderWidth.kilo} rgba(0, 0, 0, 0.1);

background-color: ${theme.colors.n300};
border-radius: ${variant === 'identity'
? theme.borderRadius.circle
: theme.borderRadius.kilo};
object-fit: cover;
object-position: center;
`;

const borderStyles = ({
theme,
variant,
size,
}: StyledImageProps & StyleProps) => {
let styles = css`
border-radius: ${theme.borderRadius.kilo};
`;
if (variant === 'identity') {
styles = css`
border-radius: ${theme.borderRadius.circle};
`;
} else if (size === 'giga') {
styles = css`
border-radius: ${theme.borderRadius.byte};
`;
}
return styles;
};

const StyledImage = styled('img', {
shouldForwardProp: (prop) => isPropValid(prop),
})<AvatarProps>(baseStyles);
})<StyledImageProps>(baseStyles, borderStyles);

/**
* The Avatar component displays an identity or an object image.
Expand All @@ -80,7 +102,7 @@ export const Avatar = ({
src,
alt = '',
variant = 'object',
size,
size = 'yotta',
...props
}: AvatarProps): JSX.Element => {
const placeholder = `data:image/svg+xml;utf8,${placeholders[variant]}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ exports[`Avatar styles should render the giga size 1`] = `
height: 48px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 12px;
object-fit: cover;
object-position: center;
border-radius: 8px;
}

<div>
Expand All @@ -28,9 +28,9 @@ exports[`Avatar styles should render the identity variant placeholder 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 100%;
object-fit: cover;
object-position: center;
border-radius: 100%;
}

<div>
Expand All @@ -49,9 +49,9 @@ exports[`Avatar styles should render the identity variant with an image 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 100%;
object-fit: cover;
object-position: center;
border-radius: 100%;
}

<div>
Expand All @@ -70,9 +70,9 @@ exports[`Avatar styles should render the object variant placeholder 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 12px;
object-fit: cover;
object-position: center;
border-radius: 12px;
}

<div>
Expand All @@ -91,9 +91,9 @@ exports[`Avatar styles should render the object variant with an image 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 12px;
object-fit: cover;
object-position: center;
border-radius: 12px;
}

<div>
Expand All @@ -112,9 +112,9 @@ exports[`Avatar styles should render the yotta size 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 12px;
object-fit: cover;
object-position: center;
border-radius: 12px;
}

<div>
Expand All @@ -133,9 +133,9 @@ exports[`Avatar styles should render with default styles 1`] = `
height: 96px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #CCC;
border-radius: 12px;
object-fit: cover;
object-position: center;
border-radius: 12px;
}

<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ describe('ImageInput', () => {
expect(container).toMatchSnapshot();
});

it('should render with smaller button', () => {
const { container } = renderImageInput({
...defaultProps,
size: 'giga',
});
expect(container).toMatchSnapshot();
});

it('should render a custom component', () => {
const { container } = renderImageInput({
...defaultProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ export const WithImage = (): JSX.Element => (
/>
);

export const AsGigaAvatar = (): JSX.Element => (
<ImageInput
label="Upload an image"
clearButtonLabel="Clear"
onChange={() => Promise.resolve()}
onClear={() => {}}
loadingLabel="Uploading"
component={({ src, alt }) => <Avatar src={src} alt={alt} size="giga" />}
size="giga"
/>
);

export const Invalid = (): JSX.Element => (
<ImageInput
label="Upload an image"
Expand Down
41 changes: 34 additions & 7 deletions packages/circuit-ui/components/ImageInput/ImageInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ import styled, { StyleProps } from '../../styles/styled';
import { uniqueId } from '../../util/id';
import { focusOutline, hideVisually } from '../../styles/style-mixins';
import Label from '../Label';
import IconButton from '../IconButton';
import IconButton, { IconButtonProps } from '../IconButton';
import Spinner from '../Spinner';
import ValidationHint from '../ValidationHint';

type Size = 'giga' | 'yotta';

export interface ImageInputProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'onChange'> {
/**
Expand Down Expand Up @@ -78,6 +80,10 @@ export interface ImageInputProps
* An information or error message, displayed below the input.
*/
validationHint?: string;
/**
* Changes the size of the button that controls the input. Defaults to "yotta".
*/
size?: Size;
}

const InputWrapper = styled.div`
Expand Down Expand Up @@ -223,12 +229,30 @@ const StyledLabel = styled(Label)<StyledLabelProps>(
addButtonStyles,
);

const ActionButton = styled(IconButton)(
({ theme }) => css`
position: absolute;
right: -${theme.spacings.bit};
bottom: -${theme.spacings.bit};
`,
const actionButtonBaseStyles = ({ theme }: StyleProps) => css`
position: absolute;
right: -${theme.spacings.bit};
bottom: -${theme.spacings.bit};
`;

const actionButtonSizeStyles = ({ buttonSize }: ActionButtonProps) => {
if (buttonSize === 'giga') {
return css`
padding: 5px;
svg {
width: 14px;
height: 14px;
}
`;
}
return null;
};

type ActionButtonProps = IconButtonProps & { buttonSize: Size };
robinmetral marked this conversation as resolved.
Show resolved Hide resolved

const ActionButton = styled(IconButton)<ActionButtonProps>(
actionButtonBaseStyles,
actionButtonSizeStyles,
);

const AddButton = styled(ActionButton)`
Expand Down Expand Up @@ -272,6 +296,7 @@ export const ImageInput = ({
label,
src,
alt,
size = 'yotta',
id: customId,
clearButtonLabel,
onChange,
Expand Down Expand Up @@ -421,6 +446,7 @@ export const ImageInput = ({
label={clearButtonLabel}
onClick={handleClear}
disabled={isLoading}
buttonSize={size}
>
<Delete size="16" />
</ActionButton>
Expand All @@ -433,6 +459,7 @@ export const ImageInput = ({
tabIndex={-1}
label="-" // We need to pass a label here to prevent IconButton from throwing
disabled={isLoading}
buttonSize={size}
>
<Plus size="16" />
</AddButton>
Expand Down
Loading