feat(container): 增加mobile-container 控件 (#958)

Signed-off-by: jacknan <zhumaonan@aliyun.com>
This commit is contained in:
jacknan 2023-12-05 09:57:39 +08:00 committed by GitHub
parent 532c01132c
commit 5a7e8fd931
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 423 additions and 5 deletions

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,7 @@
---
title: Container 版型
---
# Container 版型
<div> 内置2种常见布局版型方便快速搭建页面。</div>

View File

@ -0,0 +1,7 @@
---
title: Container dimension
---
# Container dimension
<div>Container component for layout, which facilitates page layout creation.</div>

View File

@ -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'
}
]
}
]
}

View File

@ -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: '数据组件',

View File

@ -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",

View File

@ -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)
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -0,0 +1,3 @@
:root {
--ti-mobile-container-common-padding: var(--ti-mobile-space-3x, 12px);
}

View File

@ -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) {

View File

@ -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>