Skip to content

Commit

Permalink
fix(grid-item): no resposive behavior, closes #1220
Browse files Browse the repository at this point in the history
  • Loading branch information
07akioni committed Sep 27, 2021
1 parent 32b85e4 commit 532a6ce
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 32 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
### Fixes

- Fix `n-data-table` ellipsis not show when last column not set ellipsis, closes [#934](https://github.com/TuSimple/naive-ui/issues/934).
- Fix `n-grid-item` won't work with responsive config.

### Feats

- `n-grid-item` won't display when `span` is 0, closes [#1220](https://github.com/TuSimple/naive-ui/issues/1220).
- `n-grid` add `item-responsive` prop.

## 2.19.2 (2021-09-26)

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
### Fixes

- Fix `n-data-table` 当最后一列未设置 `ellipsis` 时省略失效,关闭 [#934](https://github.com/TuSimple/naive-ui/issues/934)
- Fix `n-grid-item` 响应式不生效

### Feats

- `n-grid-item``span` 为 0 的时候隐藏,关闭 [#1220](https://github.com/TuSimple/naive-ui/issues/1220)
- `n-grid` 新增 `item-responsive` 属性

## 2.19.2 (2021-09-26)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
"highlight.js": "^11.0.1",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"seemly": "^0.3.1",
"seemly": "^0.3.2",
"treemate": "^0.3.8",
"vdirs": "^0.1.4",
"vfonts": "^0.1.0",
Expand Down
6 changes: 4 additions & 2 deletions src/grid/demos/enUS/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ basic
gap
offset
responsive
responsive-item
collapse
```

Expand All @@ -22,15 +23,16 @@ collapse
| collapsed | `boolean` | `false` | Whether to fold by default. |
| collapsed-rows | `number` | `1` | The number of rows displayed by default. |
| responsive | `'self' \| 'screen'` | `'screen'` | `'self'` triggers responsive layout by its own width. `'screen'` triggers responsive layout by viewport's witdh. |
| item-responsive | `boolean` | `false` | Whether the grid item is responsive. |
| x-gap | `number \| ResponsiveDescription` | `0` | Horizontal gap. |
| y-gap | `number \| ResponsiveDescription` | `0` | Vertical gap. |

### GridItem Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| offset | `number` | `0` | The number of intervals to the left of the grid. |
| span | `number` | `1` | The number of columns occupied by the grid. |
| offset | `number \| ResponsiveDescription` | `0` | The number of intervals to the left of the grid. |
| span | `number \| ResponsiveDescription` | `1` | The number of columns occupied by the grid. The grid item would be hidden if it's 0. |
| suffix | `boolean` | `false` | Grid suffix. |

## Slots
Expand Down
52 changes: 52 additions & 0 deletions src/grid/demos/enUS/responsive-item.demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Responsive Grid Item

`n-grid-item`'s `span`, `offset` support responsive config.

When `span` is 0, `n-grid-item` won't be displayed.

```html
<n-divider>Self Responsive</n-divider>
<n-grid cols="4" item-responsive>
<n-grid-item span="0 400:1 600:2 800:3">
<div class="light-green">
0 ~ 400px: hidden<br />
400 ~ 600px: span 1<br />
600 ~ 800px: span 2<br />
800px 以上: span 3
</div>
</n-grid-item>
<n-grid-item>
<div class="green">2</div>
</n-grid-item>
</n-grid>
<n-divider>Screen Responsive</n-divider>
<n-grid cols="4" item-responsive responsive="screen">
<n-grid-item span="0 m:1 l:2">
<div class="light-green">
m-: hidden<br />
m ~ l: span 1<br />
l+: span 2
</div>
</n-grid-item>
<n-grid-item>
<div class="green">2</div>
</n-grid-item>
</n-grid>
```

```css
.light-green {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
background-color: rgba(0, 128, 0, 0.12);
}
.green {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
background-color: rgba(0, 128, 0, 0.24);
}
```
6 changes: 4 additions & 2 deletions src/grid/demos/enUS/responsive.demo.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Responsive
# Responsive Columns

`n-grid`'s `cols`, `x-gap`, `y-gap` and `n-grid-item`'s `span`, `offset` support responsive config.
`n-grid`'s `cols`, `x-gap`, `y-gap` support responsive config.

`n-grid` has 2 responsive mode. The inner `n-grid-item` follows its parent's mode.

Responsive props in `self`(default) mode are controlled by `n-grid`'s own width. A responsive `cols` looks like `'2 400:4 600:6'`. When < 400px there are 2 columns. When 400px <= && < 600px there are 4 columns. When > 600px there are 6 columns.

Responsive props in `screen`(default) mode are controlled by viewport width of the browser. There are `xs` `s` `m` `l` `xl` `2xl` screen width to choose. A responsive `cols` looks like `2 s:3 m:4 l:5 xl:6 2xl:7`.

The default screen config is `xs < 640 <= s < 1024 <= m < 1280 <= l < 1536 <= xl < 1920 <= xxl`.

```html
<n-divider>Self Responsive</n-divider>
<n-grid cols="2 400:4 600:6">
Expand Down
6 changes: 6 additions & 0 deletions src/grid/demos/zhCN/grid-basic-debug.demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@
<n-grid-item span="10">
<div class="light-green">0</div>
</n-grid-item>
<n-grid-item span="0">
<div class="light-green">0.5</div>
</n-grid-item>
<n-grid-item :span="2" offset="0 400:1 500:2 600:3">
<div class="green">1</div>
</n-grid-item>
<n-grid-item span="0">
<div class="light-green">1.5</div>
</n-grid-item>
<n-grid-item :span="2">
<div class="light-green">2</div>
</n-grid-item>
Expand Down
13 changes: 8 additions & 5 deletions src/grid/demos/zhCN/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ basic
gap
offset
responsive
responsive-item
collapse
grid-basic-debug
```

## Props
Expand All @@ -22,16 +24,17 @@ collapse
| collapsed | `boolean` | `false` | 是否默认折叠 |
| collapsed-rows | `number` | `1` | 默认展示的行数 |
| responsive | `'self' \| 'screen'` | `'self'` | `'self'` 根据自身宽度进行响应式布局,`'screen'` 根据屏幕断点进行响应式布局 |
| item-responsive | `boolean` | `false` | 子元素是否可具有响应式宽度 |
| x-gap | `number \| ResponsiveDescription` | `0` | 横向间隔槽 |
| y-gap | `number \| ResponsiveDescription` | `0` | 纵向间隔槽 |

### GridItem Props

| 名称 | 类型 | 默认值 | 说明 |
| ------ | --------- | ------- | ------------------ |
| offset | `number` | `0` | 栅格左侧的间隔格数 |
| span | `number` | `1` | 栅格占据的列数 |
| suffix | `boolean` | `false` | 栅格后缀 |
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| offset | `number \| ResponsiveDescription` | `0` | 栅格左侧的间隔格数 |
| span | `number \| ResponsiveDescription` | `1` | 栅格占据的列数,为 0 的时候会隐藏 |
| suffix | `boolean` | `false` | 栅格后缀 |

## Slots

Expand Down
52 changes: 52 additions & 0 deletions src/grid/demos/zhCN/responsive-item.demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 响应式栅格项

`n-grid-item``span` `offset` 支持响应式参数配置。需要在 `n-grid` 上设定 `item-responsive`

`span` 为 0 的时候,`n-grid-item` 不会被显示。

```html
<n-divider>Self 响应式</n-divider>
<n-grid cols="4" item-responsive>
<n-grid-item span="0 400:1 600:2 800:3">
<div class="light-green">
0~400px:不显示<br />
400~600px:占据空间 1<br />
600~800px:占据空间 2<br />
800px 以上:占据空间 3
</div>
</n-grid-item>
<n-grid-item>
<div class="green">2</div>
</n-grid-item>
</n-grid>
<n-divider>Screen 响应式</n-divider>
<n-grid cols="4" item-responsive responsive="screen">
<n-grid-item span="0 m:1 l:2">
<div class="light-green">
m 以下:不显示<br />
m 到 l:占据空间 1<br />
l 以上:占据空间 2
</div>
</n-grid-item>
<n-grid-item>
<div class="green">2</div>
</n-grid-item>
</n-grid>
```

```css
.light-green {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
background-color: rgba(0, 128, 0, 0.12);
}
.green {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
background-color: rgba(0, 128, 0, 0.24);
}
```
6 changes: 4 additions & 2 deletions src/grid/demos/zhCN/responsive.demo.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# 响应式
# 响应式列数

`n-grid``cols` `x-gap` `y-gap``n-grid-item``span` `offset` 支持响应式参数配置。
`n-grid``cols` `x-gap` `y-gap` 支持响应式参数配置。

`n-grid` 具有两种响应式模式,内部的 `n-grid-item` 遵从父级的模式。

`self` (默认)模式由 `n-grid` 自己的宽度控制响应式属性。一个响应式 `cols` 形如 `'2 400:4 600:6'`,即在小于 400px 的时候有 2 列,400px <= 并且 < 600px 的时候有 4 列,大于 600px 的时候有 6 列。

`screen` 模式由浏览器视口的宽度控制响应式属性,有 `xs` `s` `m` `l` `xl` `2xl` 几个屏幕尺寸可供选择。一个响应式 `cols` 形如 `2 s:3 m:4 l:5 xl:6 2xl:7`

默认的屏幕配置为 `xs < 640 <= s < 1024 <= m < 1280 <= l < 1536 <= xl < 1920 <= xxl`

```html
<n-divider>Self 响应式</n-divider>
<n-grid cols="2 400:4 600:6">
Expand Down
61 changes: 41 additions & 20 deletions src/grid/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import {
mergeProps,
ref,
VNode,
Ref
Ref,
cloneVNode
} from 'vue'
import { useBreakpoint, useMemo } from 'vooks'
import { useBreakpoints, useMemo } from 'vooks'
import { VResizeObserver, VResizeObserverOnResize } from 'vueuc'
import { pxfy, parseResponsivePropValue, beforeNextFrameOnce } from 'seemly'
import { getSlot, flatten, ExtractPublicPropTypes } from '../../_utils'
Expand All @@ -30,6 +31,7 @@ const gridProps = {
type: [Number, String] as PropType<number | string>,
default: defaultCols
},
itemResponsive: Boolean,
collapsed: Boolean,
// may create grid rows < collapsedRows since a item may take all the row
collapsedRows: {
Expand Down Expand Up @@ -65,16 +67,17 @@ export default defineComponent({
const { mergedClsPrefixRef } = useConfig(props)
const numRegex = /^\d+$/
const widthRef = ref<number | undefined>(undefined)
const breakpointRef = useBreakpoint()
const breakpointsRef = useBreakpoints()
const isResponsiveRef = useMemo(() => {
if (props.itemResponsive) return true
if (!numRegex.test(props.cols.toString())) return true
if (!numRegex.test(props.xGap.toString())) return true
if (!numRegex.test(props.yGap.toString())) return true
return false
})
const responsiveQueryRef = computed(() => {
if (!isResponsiveRef.value) return undefined
return props.responsive === 'self' ? widthRef.value : breakpointRef.value
return props.responsive === 'self' ? widthRef.value : breakpointsRef.value
})
const responsiveColsRef = useMemo(() => {
return (
Expand Down Expand Up @@ -123,6 +126,7 @@ export default defineComponent({
rowGap: pxfy(responsiveYGapRef.value)
}
}),
isResponsive: isResponsiveRef,
responsiveQuery: responsiveQueryRef,
responsiveCols: responsiveColsRef,
handleResize: handleResizeRef,
Expand All @@ -135,12 +139,37 @@ export default defineComponent({

// render will be called twice when mounted, I can't figure out why
// 2 jobs will be pushed into job queues with same id, and then be flushed
const children = flatten(getSlot(this))
const rawChildren = flatten(getSlot(this))

const childrenAndRawSpan: Array<{
child: VNode
rawChildSpan: number
}> = []

const { collapsed, collapsedRows, responsiveCols, responsiveQuery } = this

rawChildren.forEach((child) => {
if ((child?.type as any)?.__GRID_ITEM__ !== true) return
const clonedChild = cloneVNode(child)

const rawChildSpan = Number(
parseResponsivePropValue(
clonedChild.props?.span as string | number | undefined,
responsiveQuery
) ?? defaultSpan
)

if (rawChildSpan === 0) return

childrenAndRawSpan.push({
child: clonedChild,
rawChildSpan
})
})

let suffixSpan = 0
const maybeSuffixNode = children[children.length - 1]
const maybeSuffixNode =
childrenAndRawSpan[childrenAndRawSpan.length - 1].child
if (maybeSuffixNode?.props) {
const suffixPropValue = maybeSuffixNode.props?.suffix
if (suffixPropValue !== undefined && suffixPropValue !== false) {
Expand All @@ -153,29 +182,21 @@ export default defineComponent({

let spanCounter = 0
let done = false
for (const child of children) {
// @ts-expect-error
if (child?.type?.__GRID_ITEM__ !== true) continue
for (const { child, rawChildSpan } of childrenAndRawSpan) {
if (done) {
this.overflow = true
}

if (!done) {
const childOffset = Number(
parseResponsivePropValue(
child.props?.offset as string | number | undefined,
responsiveQuery
) ?? 0
)

const childSpan =
Math.min(
Number(
parseResponsivePropValue(
child.props?.span as string | number | undefined,
responsiveQuery
) ?? defaultSpan
) + childOffset,
responsiveCols
) || 1
Math.min(rawChildSpan + childOffset, responsiveCols) || 1

if (!child.props) {
child.props = {
Expand Down Expand Up @@ -223,10 +244,10 @@ export default defineComponent({
},
this.$attrs
),
children
childrenAndRawSpan.map(({ child }) => child)
)
}
return this.responsive === 'self' ? (
return this.isResponsive && this.responsive === 'self' ? (
<VResizeObserver onResize={this.handleResize}>
{{
default: renderContent
Expand Down

0 comments on commit 532a6ce

Please sign in to comment.