forked from opentiny/tiny-vue
feat(container): 增加mobile-container 控件 (#958)
Signed-off-by: jacknan <zhumaonan@aliyun.com>
This commit is contained in:
parent
532c01132c
commit
5a7e8fd931
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div class="demo-container">
|
||||
<div class="option-row">
|
||||
<span class="tip">选择版型:</span>
|
||||
<tiny-radio-group v-model="pattern">
|
||||
<tiny-radio label="default">默认:default</tiny-radio>
|
||||
<tiny-radio label="classic">经典:classic</tiny-radio>
|
||||
</tiny-radio-group>
|
||||
</div>
|
||||
<tiny-container :pattern="pattern">
|
||||
<template #left>
|
||||
<div>标题</div>
|
||||
</template>
|
||||
<template #center>
|
||||
<div>
|
||||
内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<div>状态</div>
|
||||
</template>
|
||||
</tiny-container>
|
||||
|
||||
<tiny-container :pattern="pattern">
|
||||
<template #left>
|
||||
<div>标题标题标题标题标题</div>
|
||||
</template>
|
||||
<template #center>
|
||||
<div>
|
||||
内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<div>状态状态状态状态状态</div>
|
||||
</template>
|
||||
</tiny-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Container, Radio, RadioGroup } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyContainer: Container,
|
||||
TinyRadio: Radio,
|
||||
TinyRadioGroup: RadioGroup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pattern: 'default'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.option-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.option-row > span {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.option-row .tiny-radio-group {
|
||||
flex-wrap: wrap;
|
||||
height: 60px;
|
||||
}
|
||||
.demo-container .tiny-container {
|
||||
height: 300px;
|
||||
color: #5f6774;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__header) {
|
||||
background-color: #ecf8ff;
|
||||
border: 3px solid #ffffff;
|
||||
color: #5b90af;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__aside) {
|
||||
background-color: #fff0f0;
|
||||
border: 3px solid #ffffff;
|
||||
color: #d27070;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__main) {
|
||||
background-color: #fffdec;
|
||||
border: 3px solid #ffffff;
|
||||
color: #b1a859;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__footer) {
|
||||
background-color: #e8ffed;
|
||||
border: 3px solid #ffffff;
|
||||
color: #84a18a;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<div class="demo-container">
|
||||
<div class="option-row">
|
||||
<span class="tip">选择版型:</span>
|
||||
<tiny-radio-group v-model="pattern">
|
||||
<tiny-radio label="default">默认:default</tiny-radio>
|
||||
<tiny-radio label="classic">经典:classic</tiny-radio>
|
||||
</tiny-radio-group>
|
||||
</div>
|
||||
<tiny-container :pattern="pattern" :left-width="leftWidth" :right-width="rightWidth">
|
||||
<template #left>
|
||||
<div>标题标题标题标题标题</div>
|
||||
</template>
|
||||
<template #center>
|
||||
<div>
|
||||
内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<div>状态状态状态状态状态</div>
|
||||
</template>
|
||||
</tiny-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Container, Radio, RadioGroup } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyContainer: Container,
|
||||
TinyRadio: Radio,
|
||||
TinyRadioGroup: RadioGroup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pattern: 'default',
|
||||
leftWidth: 80,
|
||||
rightWidth: 80
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.option-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.option-row > span {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.option-row .tiny-radio-group {
|
||||
flex-wrap: wrap;
|
||||
height: 60px;
|
||||
}
|
||||
.demo-container .tiny-container {
|
||||
height: 300px;
|
||||
color: #5f6774;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__header) {
|
||||
background-color: #ecf8ff;
|
||||
border: 3px solid #ffffff;
|
||||
color: #5b90af;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__aside) {
|
||||
background-color: #fff0f0;
|
||||
border: 3px solid #ffffff;
|
||||
color: #d27070;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__main) {
|
||||
background-color: #fffdec;
|
||||
border: 3px solid #ffffff;
|
||||
color: #b1a859;
|
||||
}
|
||||
|
||||
.demo-container .tiny-container :deep(.tiny-container__footer) {
|
||||
background-color: #e8ffed;
|
||||
border: 3px solid #ffffff;
|
||||
color: #84a18a;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Container 版型
|
||||
---
|
||||
|
||||
# Container 版型
|
||||
|
||||
<div> 内置2种常见布局版型,方便快速搭建页面。</div>
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Container dimension
|
||||
---
|
||||
|
||||
# Container dimension
|
||||
|
||||
<div>Container component for layout, which facilitates page layout creation.</div>
|
|
@ -0,0 +1,80 @@
|
|||
export default {
|
||||
column: '2',
|
||||
owner: '',
|
||||
demos: [
|
||||
{
|
||||
'demoId': 'basic-usage',
|
||||
'name': { 'zh-CN': '基础用法', 'en-US': 'Basic Usage' },
|
||||
'desc': {
|
||||
'zh-CN': '基础用法',
|
||||
'en-US': 'base'
|
||||
},
|
||||
'codeFiles': ['basic-usage.vue']
|
||||
},
|
||||
{
|
||||
'demoId': 'custom-width',
|
||||
'name': { 'zh-CN': '自定义宽度和高度', 'en-US': 'Custom width ' },
|
||||
'desc': {
|
||||
'zh-CN': '自定义宽度',
|
||||
'en-US': 'custom width'
|
||||
},
|
||||
'codeFiles': ['custom-width.vue']
|
||||
}
|
||||
],
|
||||
apis: [
|
||||
{
|
||||
'name': 'container',
|
||||
'type': 'component',
|
||||
'props': [
|
||||
{
|
||||
'name': 'pattern',
|
||||
'type': `'default' | 'classic'`,
|
||||
'defaultValue': '"default"',
|
||||
'desc': {
|
||||
'zh-CN': '版型类型',
|
||||
'en-US': 'Measurement type'
|
||||
},
|
||||
'demoId': 'basic-usaage'
|
||||
},
|
||||
{
|
||||
'name': 'left-width',
|
||||
'type': 'number | string',
|
||||
'defaultValue': '60',
|
||||
'desc': { 'zh-CN': '左侧宽度', 'en-US': 'Left width' },
|
||||
'demoId': 'custom-width'
|
||||
},
|
||||
{
|
||||
'name': 'right-width',
|
||||
'type': 'number | string',
|
||||
'defaultValue': '44',
|
||||
'desc': { 'zh-CN': '右侧宽度', 'en-US': 'right width' },
|
||||
'demoId': 'custom-width'
|
||||
}
|
||||
],
|
||||
'events': [],
|
||||
'slots': [
|
||||
{
|
||||
'name': 'left',
|
||||
'type': '',
|
||||
'defaultValue': '',
|
||||
'desc': { 'zh-CN': '左侧内容插槽', 'en-US': 'Title Slot' },
|
||||
'demoId': 'basic-usage'
|
||||
},
|
||||
{
|
||||
'name': 'center',
|
||||
'type': '',
|
||||
'defaultValue': '',
|
||||
'desc': { 'zh-CN': '中部内容插槽', 'en-US': 'Renter Slot' },
|
||||
'demoId': 'basic-usage'
|
||||
},
|
||||
{
|
||||
'name': 'right',
|
||||
'type': '',
|
||||
'defaultValue': '',
|
||||
'desc': { 'zh-CN': '右侧内容插槽', 'en-US': 'Right Slot' },
|
||||
'demoId': 'basic-usage'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -53,7 +53,10 @@ export const cmpMenus = [
|
|||
label: '容器组件',
|
||||
labelEn: 'Container',
|
||||
key: 'cmp_container',
|
||||
children: [{ name: 'Dialog', nameCn: '对话框', key: 'dialogbox' }]
|
||||
children: [
|
||||
{ name: 'Dialog', nameCn: '对话框', key: 'dialogbox' },
|
||||
{ name: 'Container', nameCn: '内容布局', key: 'container' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '数据组件',
|
||||
|
|
|
@ -728,9 +728,15 @@
|
|||
"type": "component",
|
||||
"exclude": false,
|
||||
"mode": [
|
||||
"mobile",
|
||||
"pc"
|
||||
]
|
||||
},
|
||||
"ContainerMobile": {
|
||||
"path": "vue/src/container/src/mobile.vue",
|
||||
"type": "template",
|
||||
"exclude": false
|
||||
},
|
||||
"ContainerPc": {
|
||||
"path": "vue/src/container/src/pc.vue",
|
||||
"type": "template",
|
||||
|
|
|
@ -115,3 +115,26 @@ export const computedFooterStyle =
|
|||
height: transferWidthOrHeight(props.footerHeight)
|
||||
}
|
||||
}
|
||||
|
||||
// mobile
|
||||
export const computedLeftStyle =
|
||||
({ constants, props }) =>
|
||||
() => {
|
||||
return {
|
||||
width: transferWidthOrHeight(props.leftWidth)
|
||||
}
|
||||
}
|
||||
|
||||
export const computedShowRight =
|
||||
({ constants, props }) =>
|
||||
() => {
|
||||
return props.pattern === constants.DEFAULT ? false : true
|
||||
}
|
||||
|
||||
export const computedRightStyle =
|
||||
({ constants, props }) =>
|
||||
() => {
|
||||
return {
|
||||
width: transferWidthOrHeight(props.rightWidth)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@ import {
|
|||
computedHeaderStyle,
|
||||
computedAsideStyle,
|
||||
computedMainStyle,
|
||||
computedFooterStyle
|
||||
computedFooterStyle,
|
||||
computedLeftStyle,
|
||||
computedShowRight,
|
||||
computedRightStyle
|
||||
} from './index'
|
||||
|
||||
export const api = ['state']
|
||||
|
@ -31,7 +34,10 @@ export const renderless = (props, { computed, reactive }, { constants }) => {
|
|||
mainStyle: computed(() => api.computedMainStyle()),
|
||||
asideStyle: computed(() => api.computedAsideStyle()),
|
||||
headerStyle: computed(() => api.computedHeaderStyle()),
|
||||
footerStyle: computed(() => api.computedFooterStyle())
|
||||
footerStyle: computed(() => api.computedFooterStyle()),
|
||||
showRight: computed(() => api.computedShowRight()),
|
||||
leftStyle: computed(() => api.computedLeftStyle()),
|
||||
rightStyle: computed(() => api.computedRightStyle())
|
||||
})
|
||||
|
||||
Object.assign(api, {
|
||||
|
@ -42,7 +48,10 @@ export const renderless = (props, { computed, reactive }, { constants }) => {
|
|||
computedMainStyle: computedMainStyle({ constants, props }),
|
||||
computedAsideStyle: computedAsideStyle({ constants, props }),
|
||||
computedHeaderStyle: computedHeaderStyle({ constants, props }),
|
||||
computedFooterStyle: computedFooterStyle({ constants, props })
|
||||
computedFooterStyle: computedFooterStyle({ constants, props }),
|
||||
computedLeftStyle: computedLeftStyle({ constants, props }),
|
||||
computedShowRight: computedShowRight({ constants, props }),
|
||||
computedRightStyle: computedRightStyle({ constants, props })
|
||||
})
|
||||
|
||||
return api
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (c) 2022 - present TinyVue Authors.
|
||||
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license.
|
||||
*
|
||||
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||
*
|
||||
*/
|
||||
|
||||
@import '../custom.less';
|
||||
@import './vars.less';
|
||||
|
||||
@container-prefix-cls: ~'@{css-prefix}mobile-container';
|
||||
|
||||
.@{container-prefix-cls} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
&__left {
|
||||
margin-right: var(--ti-mobile-container-common-padding);
|
||||
}
|
||||
|
||||
&__center {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__right {
|
||||
margin-left: var(--ti-mobile-container-common-padding);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
:root {
|
||||
--ti-mobile-container-common-padding: var(--ti-mobile-space-3x, 12px);
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common'
|
||||
import template from 'virtual-template?pc'
|
||||
import template from 'virtual-template?pc|mobile'
|
||||
|
||||
const $constants = {
|
||||
DEFAULT: 'default',
|
||||
|
@ -44,6 +44,16 @@ export default defineComponent({
|
|||
footerHeight: {
|
||||
type: [Number, String],
|
||||
default: 60
|
||||
},
|
||||
|
||||
// mobile
|
||||
leftWidth: {
|
||||
type: [Number, String],
|
||||
default: 60
|
||||
},
|
||||
rightWidth: {
|
||||
type: [Number, String],
|
||||
default: 44
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<!--
|
||||
* Copyright (c) 2022 - present TinyVue Authors.
|
||||
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license.
|
||||
*
|
||||
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div :class="[pattern]" class="tiny-mobile-container">
|
||||
<div :style="state.leftStyle" class="tiny-mobile-container__left">
|
||||
<slot name="left"></slot>
|
||||
</div>
|
||||
<div class="tiny-mobile-container__center">
|
||||
<slot name="center"></slot>
|
||||
</div>
|
||||
<div v-if="state.showRight" :style="state.rightStyle" class="tiny-mobile-container__right">
|
||||
<slot name="right"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { renderless, api } from '@opentiny/vue-renderless/container/vue'
|
||||
import { props, setup, defineComponent } from '@opentiny/vue-common'
|
||||
import '@opentiny/vue-theme-mobile/container/index.less'
|
||||
|
||||
export default defineComponent({
|
||||
props: [...props, 'pattern', 'leftWidth', 'rightWidth'],
|
||||
setup(props, context) {
|
||||
return setup({ props, context, renderless, api })
|
||||
}
|
||||
})
|
||||
</script>
|
Loading…
Reference in New Issue