Permalink
Browse files

feat(b-img): New component (#933)

* feat(b-img): New functional component

Support many options, plus the ability to create blank images of any size

* [b-img] Support solid/transparent color blank image

* make b-img component avilalable

* Create meta.json

* Create index.js

* Create README.md

* Add b-img docs

* Create demo.html

* Create demo.js

* Create img.spec.js
  • Loading branch information...
tmorehouse committed Aug 28, 2017
1 parent 019f8fa commit c4358e045d6f28be5c692e3df7f1fd33033c70ed
@@ -0,0 +1,128 @@
# Images
> Documentation and examples for opting images (via `<b-img>` component) into
responsive behavior (so they never become larger than their parent elements),
optionally adding lightweight styles to them — all via props. Support for
rounded images, thumbnail styling, alignment, and even the ability to create
blank images with an optional solid background color.
## Responsive images
Images in Bootstrap-Vue can be made responsive with the `fluid` prop (which
sets `max-width: 100%; height: auto;` via CSS classes) are applied to the image
so that it scales with the parent element.
```html
<div>
<b-img src="https://lorempixel.com/1024/400/" fluid alt="Responsive image" />
</div>
<!-- b-img-responsive-1.vue -->
```
To make a fluid image that will grow to fill the width of it's container, use
the `fluid-grow` prop. Note this may cause bluring on small bitmap images.
```html
<div>
<b-img src="https://lorempixel.com/300/150/" fluid-grow alt="Responsive image" />
</div>
<!-- b-img-responsive-2.vue -->
```
**Note:** _In Internet Explorer 10, SVG images with `fluid` are disproportionately sized.
To fix this, add the style `width: 100% \9;` where necessary. This fix improperly sizes
other image formats, so Bootstrap V4 doesn’t apply it automatically._
## Image thumbnails
You can use prop `thumbnail` to give an image a rounded light border appearance.
```html
<div class="p-5 bg-info text-center">
<b-img src="https://lorempixel.com/200/200/technics/8/" thumbnail alt="Thumbnail image" />
</div>
<!-- b-img-thumbnail.vue -->
```
## Rounded corners
You can control which corners are rounded by setting the rounded prop to one
of several values:
- `true` (or prop present with no value): round all corners
- `false` (or prop not present): no explit rounding or corners (default)
- `'top'`: round the top corners
- `'right'`: round the right corners
- `'bottom'`: round the bottom corners
- `'left'`: round the left corners
- `'circle'`: make a circle (if square image) or oval (of not square) border
- `'0'`: explicity turn off rounding or corenrs
```html
<div>
<b-img rounded blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="top" blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="right" blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="bottom" blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="left" blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="circle" blank width="75" height="75" blank-color="#777" alt="img" />
<b-img rounded="0" blank width="75" height="75" blank-color="#777" alt="img" />
</div>
<!-- b-img-rounded.vue -->
```
## Aligning images
Align images with the boolean props `left` (floats left) `right`(floats right),
and `center` (auto left+right margins). You can also center images by placing them
in a container that has the class `text-center`.
**Left an Right aligned (float):**
```html
<div>
<b-img src="https://lorempixel.com/125/125/technics/8/" left alt="left image" />
<b-img src="https://lorempixel.com/125/125/technics/8/" right alt="right image" />
</div>
<!-- b-img-left-right.vue >
```
**Center aligned (block):**
```html
<div>
<b-img src="https://lorempixel.com/125/125/technics/8/" center alt="center image" />
</div>
<!-- b-img-center.vue >
```
Note: `left` takes precedence over `right` which takes precedence over `center`.
## Blank (or solid color) Images
`<b-img>` provides built-in support for generating blank images (transparent by
default) of any width and height, by setting the `blank` prop, and specifying a width and
height value (in pixels). You can apply any of the other props that `<b-img>` to change the
style/behavior of the image.
Set the prop `blank-color` to any valid CSS color (hex foramt, RGB, RGBA, named
color, etc). The default color is `transparent`.
```html
<div>
<b-img blank width="75" height="75" alt="transparent img" />
<b-img blank width="75" height="75" blank-color="#777" alt="img" />
<b-img blank width="75" height="75" blank-color="red" alt="img" />
<b-img blank width="75" height="75" blank-color="black" alt="img" />
<b-img blank width="75" height="75" blank-color="#338833" alt="img" />
<b-img blank width="75" height="75" blank-color="rgba(255,255,255,0.5)" alt="img" />
<b-img blank width="75" height="75" blank-color="#88f" alt="img" />
</div>
<!-- b-img-blank.vue -->
```
**Notes:**
- In blank image mode, if only one of width or height is set, the image will be have both width and height set to the same value.
- In blank image mode, if width and height are not set, both width and height will internally be set to 1.
- The `blank` prop takes precedence over the `src` prop. If you set both and later set `blank` to `false` the image specified in `src` will then be displayed.
- Blank images are rendered using SVG image data URLs.
- The `width` and `height` props will also apply the `width` and `height` attributes to the rendered `<img>` tag, even if `blank` is not set.
@@ -0,0 +1,4 @@
import meta from './meta.json';
import readme from './README.md';
export default {meta, readme};
@@ -0,0 +1,4 @@
{
"title": "Images",
"component": "bImg"
}
@@ -21,6 +21,7 @@ export default {
'form-file': require('./form-file').default,
'form-group': require('./form-group').default,
'input-group': require('./input-group').default,
'img': require('./img').default,
'jumbotron': require('./jumbotron').default,
'list-group': require('./list-group').default,
'modal': require('./modal').default,
@@ -0,0 +1,136 @@
import { mergeData } from "../utils";
// Blank image with fill template
const BLANK_TEMPLATE = '<svg width="%{w}" height="%{h}" '
+ 'xmlns="http://www.w3.org/2000/svg" '
+ 'viewBox="0 0 %{w} %{h}" preserveAspectRatio="none">'
+ '<rect width="100%" height="100%" style="fill:%{f};"></rect>'
+ '</svg>';
function makeBlankImgSrc(width, height, color) {
const src = encodeURIComponent(
BLANK_TEMPLATE
.replace('%{w}', String(width))
.replace('%{h}', String(height))
.replace('%{f}', color)
);
return `data:image/svg+xml;charset=UTF-8,${src}`;
}
export const props = {
src: {
type: String,
default: null
},
alt: {
type: String,
default: null
},
width: {
type: [Number, String],
default: null
},
height: {
type: [Number, String],
default: null
},
fluid: {
type: Boolean,
default: false
},
fluidGrow: {
// Gives fluid images class `w-100` to make them grow to fit container
type: Boolean,
default: false
},
rounded: {
// rounded can be:
// 'false': no rounding of corners
// 'true': slightly rounded corners
// 'top': top corners rounded
// 'right': right corners rounded
// 'bottom': bottom corners rounded
// 'left': left corners rounded
// 'circle': circle/oval
// '0': force rounding off
type: [Boolean, String],
default: false
},
thumbnail: {
type: Boolean,
default: false
},
left: {
type: Boolean,
default: false
},
right: {
type: Boolean,
default: false
},
center: {
type: Boolean,
default: false
},
blank: {
type: Boolean,
default: false
},
blankColor: {
type: String,
default: 'transparent'
}
};
export default {
functional: true,
props,
render(h, { props, data }) {
let src = props.src;
let width = Boolean(parseInt(props.width,10)) ? parseInt(props.width,10) : null;
let height = Boolean(parseInt(props.height,10)) ? parseInt(props.height,10) : null;
let align = null;
let block = null;
if (props.blank) {
if (!height && Boolean(width)) {
height = width;
} else if (!width && Boolean(height)) {
width = height;
}
if (!width && !height) {
width = 1;
height = 1;
}
// Make a blank SVG image
src = makeBlankImgSrc(width, height, props.blankColor || 'transparent');
}
if (props.left) {
align = 'float-left';
} else if (props.right) {
align = 'float-right';
} else if (props.center) {
align = 'mx-auto';
block = true;
}
return h(
'img',
mergeData(data, {
attrs: {
'src': src,
'alt': props.alt,
'width': width ? String(width) : null,
'height': height ? String(height) : null
},
class: {
'img-thumbnail': props.thumbnail,
'img-fluid': props.fluid || props.fluidGrow,
'w-100': props.fluidGrow,
'rounded': props.rounded === '' || props.rounded === true,
[`rounded-${props.rounded}`]: typeof props.rounded === 'string' && props.rounded !== '',
[align]: Boolean(align),
'd-block': block
}
})
);
}
};
@@ -36,6 +36,7 @@ import bFormInput from "./form-input.vue";
import bFormTextarea from "./form-textarea.vue";
import bFormFile from "./form-file.vue";
import bFormSelect from "./form-select.vue";
import bImg from "./img";
import bJumbotron from "./jumbotron";
import bLink from "./link";
import bListGroup from "./list-group";
@@ -110,6 +111,7 @@ export {
bFormInput,
bFormTextarea,
bFormSelect,
bImg,
bJumbotron,
bBadge,
bMedia,
Oops, something went wrong.

0 comments on commit c4358e0

Please sign in to comment.