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

Add floats to EuiImage #4209

Merged
merged 3 commits into from
Nov 2, 2020
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Added `labelWidth` and `descriptionDisplay` props to `EuiSuggestItem` ([#4180](https://github.com/elastic/eui/pull/4180))
- Added `float` and `margin` props to `EuiImage` ([#4209](https://github.com/elastic/eui/pull/4209))

**Bug fixes**

Expand Down
34 changes: 34 additions & 0 deletions src-docs/src/views/image/float.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';

import { EuiImage, EuiText } from '../../../../src/components';
import { fake } from 'faker';

export default () => (
<EuiText>
<EuiImage
size="l"
float="right"
margin="l"
hasShadow
caption="Random nature image"
allowFullScreen
alt="Random nature image"
url="https://picsum.photos/800/500"
/>
<p>{fake('{{lorem.paragraphs}}')}</p>
<p>{fake('{{lorem.paragraphs}}')}</p>
<p>{fake('{{lorem.paragraphs}}')}</p>
<EuiImage
size="l"
float="left"
margin="l"
hasShadow
allowFullScreen
caption="Another random image"
alt="Random nature image"
url="https://picsum.photos/300/300"
/>
<p>{fake('{{lorem.paragraphs}}')}</p>
<p>{fake('{{lorem.paragraphs}}')}</p>
</EuiText>
);
45 changes: 45 additions & 0 deletions src-docs/src/views/image/image_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ const imageZoomSnippet = `<EuiImage
/>
`;

import ImageFloat from './float';
import { EuiCallOut } from '../../../../src/components/call_out';
import { Fragment } from 'react-is';
const imageFloatSource = require('!!raw-loader!./float');
const imageFloatHtml = renderToHtml(ImageFloat);
const imageFloatSnippet = `<EuiImage
alt={description}
url={someUrl}
float="left"
margin="l"
/>
`;

export const ImageExample = {
title: 'Image',
sections: [
Expand Down Expand Up @@ -115,6 +128,38 @@ export const ImageExample = {
demo: <ImageSizes />,
snippet: imageSizesSnippet,
},
{
title: 'Float images within text',
source: [
{
type: GuideSectionTypes.JS,
code: imageFloatSource,
},
{
type: GuideSectionTypes.HTML,
code: imageFloatHtml,
},
],
text: (
<Fragment>
<p>
When using <EuiCode>EuiImage</EuiCode> within{' '}
<EuiCode>EuiText</EuiCode> it is often useful to apply floats.
Almost always you&apos;ll want to pair the <EuiCode>float</EuiCode>{' '}
prop usage, with a <EuiCode>margin</EuiCode> prop usage to give
space around your image. Margins, when used in combo with floats,
will adjust depending upon the position of the float.
</p>
<EuiCallOut title="Be careful with floats" color="warning">
Floats should only be used on images within <strong>large</strong>{' '}
bodies of text. Specifically, we only suggest using them with{' '}
<EuiCode>EuiText</EuiCode> which comes automatically clears floats.
</EuiCallOut>
</Fragment>
),
demo: <ImageFloat />,
snippet: imageFloatSnippet,
},
],
playground: imageConfig,
};
24 changes: 24 additions & 0 deletions src/components/image/__snapshots__/image.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,30 @@ exports[`EuiImage is rendered and allows full screen 1`] = `
</figure>
`;

exports[`EuiImage is rendered with a float 1`] = `
<figure
class="euiImage euiImage--floatLeft "
>
<img
alt="alt"
class="euiImage__img"
src="/cat.jpg"
/>
</figure>
`;

exports[`EuiImage is rendered with a margin 1`] = `
<figure
class="euiImage euiImage--marginLarge "
>
<img
alt="alt"
class="euiImage__img"
src="/cat.jpg"
/>
</figure>
`;

exports[`EuiImage is rendered with a node as the caption 1`] = `
<figure
class="euiImage "
Expand Down
67 changes: 63 additions & 4 deletions src/components/image/_image.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
min-height: 1px; /* 1 */
line-height: 0; // Fixes cropping when image is resized by forcing its height to be determined by the image not line-height

// Required for common usage of nesting within EuiText
.euiImage__img {
margin-bottom: 0;
}

&.euiImage--hasShadow {
.euiImage__img {
@include euiBottomShadowMedium;
Expand Down Expand Up @@ -50,25 +55,60 @@
}

// These sizes are mostly suggestions. Don't look too hard for meaning in their values.
&.euiImage--small {
// Size is applied to the image, rather than the figure to work better with floats
&.euiImage--small .euiImage__img {
width: convertToRem(120px);
}

&.euiImage--medium {
&.euiImage--medium .euiImage__img {
width: convertToRem(200px);
}

&.euiImage--large {
&.euiImage--large .euiImage__img {
width: convertToRem(360px);
}

&.euiImage--xlarge {
&.euiImage--xlarge .euiImage__img {
width: convertToRem(600px);
}

&.euiImage--fullWidth {
width: 100%;
}

&.euiImage--floatLeft {
float: left;

&[class*='euiImage--margin'] {
margin-left: 0;
margin-top: 0;
}
}

&.euiImage--floatRight {
float: right;

&[class*='euiImage--margin'] {
margin-right: 0;
margin-top: 0;
}
}

&.euiImage--marginSmall {
margin: $euiSizeS;
}

&.euiImage--marginMedium {
margin: $euiSize;
}

&.euiImage--marginLarge {
margin: $euiSizeL;
}

&.euiImage--marginXlarge {
margin: $euiSizeXL;
}
}

// The image itself is full width within the container.
Expand All @@ -79,6 +119,7 @@

.euiImage__caption {
@include euiFontSizeS;
margin-top: $euiSizeXS;
text-align: center;
}

Expand Down Expand Up @@ -136,3 +177,21 @@
}
}

@include euiBreakpoint('xs', 's', 'm') {

.euiImage {

&.euiImage--floatLeft,
&.euiImage--floatRight {
float: none;

// Return back to whatever margin settings were set without the float
&[class*='euiImage--margin'] {
margin-top: inherit;
margin-right: inherit;
margin-bottom: inherit;
margin-left: inherit;
}
}
}
}
14 changes: 14 additions & 0 deletions src/components/image/image.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ describe('EuiImage', () => {
expect(component).toMatchSnapshot();
});

test('is rendered with a float', () => {
const component = render(
<EuiImage alt="alt" float="left" url="/cat.jpg" />
);

expect(component).toMatchSnapshot();
});

test('is rendered with a margin', () => {
const component = render(<EuiImage alt="alt" margin="l" url="/cat.jpg" />);

expect(component).toMatchSnapshot();
});

test('is rendered with custom size', () => {
const component = render(<EuiImage alt="alt" size={50} url="/cat.jpg" />);

Expand Down
26 changes: 26 additions & 0 deletions src/components/image/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import { keys } from '../../services';
import { useInnerText } from '../inner_text';

type ImageSize = 's' | 'm' | 'l' | 'xl' | 'fullWidth' | 'original';
type Floats = 'left' | 'right';
type Margins = 's' | 'm' | 'l' | 'xl';

const sizeToClassNameMap: { [size in ImageSize]: string } = {
s: 'euiImage--small',
Expand All @@ -48,6 +50,18 @@ const sizeToClassNameMap: { [size in ImageSize]: string } = {
original: '',
};

const marginToClassNameMap: { [margin in Margins]: string } = {
s: 'euiImage--marginSmall',
m: 'euiImage--marginMedium',
l: 'euiImage--marginLarge',
xl: 'euiImage--marginXlarge',
};

const floatToClassNameMap: { [float in Floats]: string } = {
left: 'euiImage--floatLeft',
right: 'euiImage--floatRight',
};

export const SIZES = Object.keys(sizeToClassNameMap);

type FullScreenIconColor = 'light' | 'dark';
Expand Down Expand Up @@ -87,6 +101,14 @@ interface EuiImageProps extends CommonProps, HTMLAttributes<HTMLImageElement> {
* When set to `true` will make the image clickable to a larger version
*/
allowFullScreen?: boolean;
/**
* Float the image to the left or right. Useful in large text blocks.
*/
float?: Floats;
/**
* Margin around the image.
snide marked this conversation as resolved.
Show resolved Hide resolved
*/
margin?: Margins;
}

export const EuiImage: FunctionComponent<EuiImageProps> = ({
Expand All @@ -99,6 +121,8 @@ export const EuiImage: FunctionComponent<EuiImageProps> = ({
fullScreenIconColor = 'light',
alt,
style,
float,
margin,
...rest
}) => {
const [isFullScreenActive, setIsFullScreenActive] = useState(false);
Expand Down Expand Up @@ -127,6 +151,8 @@ export const EuiImage: FunctionComponent<EuiImageProps> = ({
'euiImage--hasShadow': hasShadow,
'euiImage--allowFullScreen': allowFullScreen,
},
margin ? marginToClassNameMap[margin] : null,
float ? floatToClassNameMap[float] : null,
className
);

Expand Down
2 changes: 2 additions & 0 deletions src/components/text/_text.scss
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@
// of other styling concerns, we should inherit their coloring. The default
// coloring will likely coming from the reset.scss anyway.
color: inherit;
// EuiImage with floats are often used within EuiText.
clear: both;

// Style anchors that don't have a class. This prevents overwriting "buttons"
// and other stylized elements passed in.
Expand Down