diff --git a/.changeset/small-bikes-wink.md b/.changeset/small-bikes-wink.md new file mode 100644 index 00000000..a1c31e8a --- /dev/null +++ b/.changeset/small-bikes-wink.md @@ -0,0 +1,8 @@ +--- +'@chakra-ui/vue': minor +'chakra-ui-docs': minor +--- + +- This changeset adds a srcset support to the CImage component. +- Fixes merging of Popper.js modifiers +- Adds CGridItems components to the core 👏🏾 diff --git a/packages/chakra-ui-core/src/CBox/CBox.stories.js b/packages/chakra-ui-core/src/CBox/CBox.stories.js index 636d71c2..cddad12d 100644 --- a/packages/chakra-ui-core/src/CBox/CBox.stories.js +++ b/packages/chakra-ui-core/src/CBox/CBox.stories.js @@ -1,5 +1,5 @@ import { storiesOf } from '@storybook/vue' -import { CBox } from '..' +import CBox from '../CBox' storiesOf('UI | Box', module) .add('Box', () => ({ @@ -28,13 +28,26 @@ storiesOf('UI | Box', module) template: `
- + + + + Tempations + + + Spacial cakes for special moments. + +
` diff --git a/packages/chakra-ui-core/src/CGrid/CGrid.js b/packages/chakra-ui-core/src/CGrid/CGrid.js index 93fc3caf..be26534d 100644 --- a/packages/chakra-ui-core/src/CGrid/CGrid.js +++ b/packages/chakra-ui-core/src/CGrid/CGrid.js @@ -10,7 +10,65 @@ */ import { createStyledAttrsMixin } from '../utils' -import { SNA } from '../config/props/props.types' +import { SNA, StringArray } from '../config/props/props.types' + +/** + * @description Map "span" values to accommodate breakpoint values + * @param {Array} value + * @returns {(String|Array)} String or Array of breakpoint values + */ +const spanFn = (value) => { + if (Array.isArray(value)) { + return value.map(v => + v === 'auto' ? 'auto' : `span ${v}/span ${v}` + ) + } else { + return value === 'auto' ? 'auto' : `span ${value}/span ${value}` + } +} + +/** + * CGridItem component + * + * A primitive component useful for grid layouts. + * + * @extends CBox + * @see Docs https://vue.chakra-ui.com/grid + */ + +const CGridItem = { + name: 'CGridItem', + mixins: [createStyledAttrsMixin('CGridItem')], + props: { + colSpan: { type: StringArray }, + rowSpan: { type: StringArray }, + colStart: { type: StringArray }, + colEnd: { type: StringArray }, + rowStart: { type: StringArray }, + rowEnd: { type: StringArray } + }, + computed: { + componentStyles () { + return { + gridColumn: this.colSpan ? spanFn(this.colSpan) : null, + gridRow: this.rowSpan ? spanFn(this.rowSpan) : null, + gridColumnStart: this.colStart, + gridColumnEnd: this.colEnd, + gridRowStart: this.rowStart, + gridRowEnd: this.rowEnd + } + } + }, + render (h) { + return h('div', + { + class: this.className, + attrs: this.computedAttrs + }, + this.$slots.default + ) + } +} /** * CGrid component @@ -61,11 +119,18 @@ const CGrid = { } }, render (h) { - return h(this.as, { - class: this.className, - attrs: this.computedAttrs - }, this.$slots.default) + return h( + this.as, + { + class: this.className, + attrs: this.computedAttrs + }, + this.$slots.default + ) } } -export default CGrid +export { + CGrid, + CGridItem +} diff --git a/packages/chakra-ui-core/src/CGrid/CGrid.stories.js b/packages/chakra-ui-core/src/CGrid/CGrid.stories.js index 7cfb30bd..36c5c7a6 100644 --- a/packages/chakra-ui-core/src/CGrid/CGrid.stories.js +++ b/packages/chakra-ui-core/src/CGrid/CGrid.stories.js @@ -1,5 +1,5 @@ import { storiesOf } from '@storybook/vue' -import { CReset, CGrid, CBox } from '..' +import { CReset, CGrid, CGridItem, CBox } from '..' storiesOf('UI | Grid', module) .add('Default Grid', () => ({ @@ -17,3 +17,17 @@ storiesOf('UI | Grid', module) ` })) + +storiesOf('UI | Grid', module) + .add('Grid Items', () => ({ + components: { CReset, CGrid, CGridItem }, + template: ` +
+ + + + + +
+ ` + })) diff --git a/packages/chakra-ui-core/src/CGrid/index.js b/packages/chakra-ui-core/src/CGrid/index.js index 6c9cd408..d9613022 100644 --- a/packages/chakra-ui-core/src/CGrid/index.js +++ b/packages/chakra-ui-core/src/CGrid/index.js @@ -1,2 +1 @@ -import CGrid from './CGrid' -export default CGrid +export * from './CGrid' diff --git a/packages/chakra-ui-core/src/CGrid/test/CGrid.test.js b/packages/chakra-ui-core/src/CGrid/test/CGrid.test.js index e8e035f6..7aa3ea22 100644 --- a/packages/chakra-ui-core/src/CGrid/test/CGrid.test.js +++ b/packages/chakra-ui-core/src/CGrid/test/CGrid.test.js @@ -1,10 +1,10 @@ -import CGrid from '..' +import { CGrid, CGridItem } from '..' import { render } from '@/tests/test-utils' const renderComponent = (props) => { const inlineAttrs = (props && props.inlineAttrs) || '' const base = { - components: { CGrid }, + components: { CGrid, CGridItem }, template: `Grid Me`, ...props } @@ -23,3 +23,25 @@ it('should change gap', () => { expect(asFragment()).toMatchSnapshot() }) + +it('should offset columns', () => { + const inlineAttrs = 'col-start="4" col-end="6"' + const { asFragment } = renderComponent({ + template: ` + + I'm in a grid item + ` + }) + expect(asFragment()).toMatchSnapshot() +}) + +it('should span columns', () => { + const inlineAttrs = 'col-span="2"' + const { asFragment } = renderComponent({ + template: ` + + I'm in a grid item + ` + }) + expect(asFragment()).toMatchSnapshot() +}) diff --git a/packages/chakra-ui-core/src/CGrid/test/__snapshots__/CGrid.test.js.snap b/packages/chakra-ui-core/src/CGrid/test/__snapshots__/CGrid.test.js.snap index eb89f731..c14e6ff7 100644 --- a/packages/chakra-ui-core/src/CGrid/test/__snapshots__/CGrid.test.js.snap +++ b/packages/chakra-ui-core/src/CGrid/test/__snapshots__/CGrid.test.js.snap @@ -11,6 +11,22 @@ exports[`should change gap 1`] = ` `; +exports[`should offset columns 1`] = ` + +
+
+ I'm in a grid item +
+
+
+`; + exports[`should render correctly 1`] = `
`; + +exports[`should span columns 1`] = ` + +
+
+ I'm in a grid item +
+
+
+`; diff --git a/packages/chakra-ui-core/src/CImage/CImage.js b/packages/chakra-ui-core/src/CImage/CImage.js index 25b6c59a..a93cc3f9 100644 --- a/packages/chakra-ui-core/src/CImage/CImage.js +++ b/packages/chakra-ui-core/src/CImage/CImage.js @@ -25,6 +25,7 @@ const CImage = { mixins: [createStyledAttrsMixin('CImage')], props: { src: String, + srcset: String, fallbackSrc: String, ignoreFalback: Boolean, htmlWidth: String, @@ -48,12 +49,13 @@ const CImage = { created () { // Should only invoke window.Image in the browser. if (process.browser) { - this.loadImage(this.src) + this.loadImage(this.src, this.srcset) } }, methods: { - loadImage (src) { + loadImage (src, srcset) { const image = new window.Image() + image.srcset = srcset image.src = src image.onload = (event) => { @@ -70,9 +72,9 @@ const CImage = { render (h) { let imageProps if (this.ignoreFallback) { - imageProps = { src: this.src } + imageProps = { src: this.src, srcset: this.srcset } } else { - imageProps = { src: this.hasLoaded ? this.src : this.fallbackSrc } + imageProps = { src: this.hasLoaded ? this.src : this.fallbackSrc, srcset: this.srcset } } return h(CNoSsr, [ h('img', { diff --git a/packages/chakra-ui-core/src/CImage/tests/CImage.test.js b/packages/chakra-ui-core/src/CImage/tests/CImage.test.js index 3b6feaff..04836872 100644 --- a/packages/chakra-ui-core/src/CImage/tests/CImage.test.js +++ b/packages/chakra-ui-core/src/CImage/tests/CImage.test.js @@ -45,3 +45,10 @@ it('fallback src works', async () => { expect(screen.getByAltText(/Mesut Koca/i)).toHaveAttribute('src', 'LOAD_FALLBACK_SRC') }) }) + +it('srcset works', async () => { + renderComponent({ template: '' }) + await wait(() => { + expect(screen.getByAltText(/My Image Description/i)).toHaveAttribute('srcset', 'LOAD_SUCCESS_SRC 400w') + }) +}) diff --git a/packages/chakra-ui-core/src/CPopper/CPopper.js b/packages/chakra-ui-core/src/CPopper/CPopper.js index d495e05b..44fd5c0e 100644 --- a/packages/chakra-ui-core/src/CPopper/CPopper.js +++ b/packages/chakra-ui-core/src/CPopper/CPopper.js @@ -42,6 +42,27 @@ function flipPlacement (placement) { } } +/** + * Call _.merge() for each item of `object` array with the corresponding + * item of `source` array + * @param {*} object The destination Modifiers array. + * @param {*} source The source array. + * @returns Returns merged `array` + */ +function mergeModifiers (object, source) { + if (!Array.isArray(object)) throw new Error('`object` must be an array') + + const _source = Array.isArray(source) ? source : [source] + + object.forEach((o) => { + const { name } = o + const _s = _source.find(s => s.name === name) + if (_s) merge(o, _s) + }) + + return object +} + /** * CPopper component * @@ -153,7 +174,7 @@ const CPopper = { return ref }, computedModifiers () { - return merge([ + return mergeModifiers([ this.usePortal && { name: 'preventOverflow', options: { diff --git a/packages/chakra-ui-core/src/CSimpleGrid/CSimpleGrid.js b/packages/chakra-ui-core/src/CSimpleGrid/CSimpleGrid.js index e4b7dd9b..e8a71fe0 100644 --- a/packages/chakra-ui-core/src/CSimpleGrid/CSimpleGrid.js +++ b/packages/chakra-ui-core/src/CSimpleGrid/CSimpleGrid.js @@ -8,7 +8,7 @@ * @see Source https://github.com/chakra-ui/chakra-ui-vue/blob/master/packages/chakra-ui-core/src/CSimpleGrid/CSimpleGrid.js */ -import CGrid from '../CGrid' +import { CGrid } from '../CGrid' import { SNA } from '../config/props/props.types' import { createStyledAttrsMixin } from '../utils' import { countToColumns, widthToColumns } from './utils/grid.styles' diff --git a/packages/chakra-ui-core/src/index.js b/packages/chakra-ui-core/src/index.js index 6b3ca0b7..3b380c32 100644 --- a/packages/chakra-ui-core/src/index.js +++ b/packages/chakra-ui-core/src/index.js @@ -55,7 +55,7 @@ export { default as CFormHelperText } from './CFormHelperText' export { default as CFragment } from './CFragment' // G -export { default as CGrid } from './CGrid' +export * from './CGrid' // H export { default as CHeading } from './CHeading' diff --git a/website/pages/grid.mdx b/website/pages/grid.mdx index 5b373fff..e0c45771 100644 --- a/website/pages/grid.mdx +++ b/website/pages/grid.mdx @@ -1,4 +1,4 @@ -import SEO from "../components/SEO"; +import SEO from '../components/SEO' ``` +## Spanning Columns + +In some layouts, you may need certain grid items to span specific amount of columns or rows instead of an even distribution. To achieve this, you need to pass the `colSpan` prop to the `CGridItem` component to span across columns and also pass the `rowSpan` component to span across rows. You also need to specify the `templateColumns` and `templateRows`. + +```vue live=true + + + + + + +``` + +## Starting and Ending Lines + +Pass the `colStart` and `colEnd` prop to `CGridItem` component to make an element start or end at the `nth` grid position. + +```vue live=true + + + + +``` + ## Props -> `CGrid` composes the `CBox` component. So it accepts all Box props along with the related CSS grid props. See [Box](/box#props) component for list of props \ No newline at end of file +> `CGrid` composes the `CBox` component. So it accepts all Box props along with the related CSS grid props. See [Box](/box#props) component for list of props + +### `CGridItem` Props + +> `CGridItem` composes `CBox` so you can pass all `CBox` props. + +| Name | Type | Description | +| -------- | -------- | ------------------------------------------------ | +| colSpan | `number` | The number of columns the grid item should span. | +| colStart | `number` | The column number the grid item should start. | +| colEnd | `number` | The column number the grid item should end. | +| rowSpan | `number` | The number of rows the grid item should span. | +| rowStart | `number` | The row number the grid item should start. | +| rowEnd | `number` | The row number the grid item should end. |