feat(radio): radio button group

This commit is contained in:
07akioni 2019-07-16 17:20:43 +08:00
parent 8089b55766
commit c4b5e17ebb
3 changed files with 116 additions and 21 deletions

View File

@ -142,12 +142,25 @@ export default {
v-for="song in songs"
:key="song.value"
:value="song.value"
:disabled="song.label === 'Live Forever'"
:disabled="(song.label === 'Live Forever' && disabled1 || song.label === 'Shakermaker' && disabled2)"
>
{{ song.label }}
</n-radio-button>
</n-radio-group>
</div>
<div class="n-doc-section__view">
<n-checkbox
v-model="disabled2"
style="margin-right: 12px;"
>
disable Shakemaker
</n-checkbox>
<n-checkbox
v-model="disabled1"
>
disable Live Forever
</n-checkbox>
</div>
<pre class="n-doc-section__inspect">value: {{ JSON.stringify(value3) }}</pre>
<div class="n-doc-section__source">
<textarea v-pre><n-radio-group v-model="value">
@ -210,6 +223,8 @@ export default {
value1: null,
value2: null,
value3: 'Shakermaker',
disabled1: false,
disabled2: false,
songs: [
{
value: 'Rock\'n\'Roll Star',

View File

@ -1,17 +1,63 @@
<script>
function mapSlot (defaultSlot, currentComponent) {
return defaultSlot.map(el => {
if (el.componentOptions.tag === 'n-radio' || el.componentOptions.tag === 'n-radio-button') {
el.componentOptions.propsData.privateValue = currentComponent.value
el.componentOptions.listeners = {
...el.componentOptions.listeners,
function mapSlot (h, defaultSlot, currentComponent) {
/**
* connect current component's v-model to child instance
*/
const wrapInstance = instance => {
if (instance.componentOptions.tag === 'n-radio' || instance.componentOptions.tag === 'n-radio-button') {
instance.componentOptions.propsData.privateValue = currentComponent.value
instance.componentOptions.listeners = {
...instance.componentOptions.listeners,
input: (v) => {
currentComponent.$emit('input', v)
}
}
return el
} else return el
})
return instance
} else return null
}
const mappedSlot = []
for (let i = 0; i < defaultSlot.length; ++i) {
const wrappedInstance = wrapInstance(defaultSlot[i])
if (wrappedInstance === null) {
console.error('[naive ui]: Please don\'t use tags other than `n-radio` and `n-radio-button` in `n-radio-group`.')
continue
}
if (i === 0 || wrappedInstance.componentOptions.tag === 'n-radio') {
mappedSlot.push(wrappedInstance)
} else {
const lastInstanceComponentOptions = mappedSlot[mappedSlot.length - 1].componentOptions
const lastInstanceChecked = lastInstanceComponentOptions.propsData.privateValue === lastInstanceComponentOptions.propsData.value
const lastInstanceDisabled = lastInstanceComponentOptions.propsData.disabled
const currentInstanceChecked = wrappedInstance.componentOptions.propsData.privateValue === wrappedInstance.componentOptions.propsData.value
const currentInstanceDisabled = wrappedInstance.componentOptions.propsData.disabled
/**
* Priority of button splitor:
* !disabled checked >
* !disabled !checked >
* disabled checked >
* disabled !checked
*/
const lastInstancePriority = (!lastInstanceDisabled ? 2 : 0) + (lastInstanceChecked ? 1 : 0)
const currentInstancePriority = (!currentInstanceDisabled ? 2 : 0) + (currentInstanceChecked ? 1 : 0)
const lastInstanceClass = {
'n-radio-group__splitor--disabled': lastInstanceDisabled,
'n-radio-group__splitor--checked': lastInstanceChecked
}
const currentInstanceClass = {
'n-radio-group__splitor--disabled': currentInstanceDisabled,
'n-radio-group__splitor--checked': currentInstanceChecked
}
let splitorClass
if (lastInstancePriority < currentInstancePriority) splitorClass = currentInstanceClass
else splitorClass = lastInstanceClass
mappedSlot.push(h('div', {
staticClass: 'n-radio-group__splitor',
class: splitorClass
}), wrappedInstance)
}
}
return mappedSlot
}
export default {
@ -28,9 +74,10 @@ export default {
}
},
render (h) {
console.log('render radio')
return h('div', {
staticClass: 'n-radio-group'
}, mapSlot(this.$slots.default, this))
}, mapSlot(h, this.$slots.default, this))
}
}
</script>

View File

@ -78,8 +78,23 @@
}
@include b(radio-group) {
display: inline-block;
display: inline-flex;
vertical-align: middle;
.n-radio-group__splitor {
height: 100%;
width: 1px;
background-color: rgba(255,255,255,0.5);
transition: background-color .2s $default-cubic-bezier;
&.n-radio-group__splitor--checked {
background-color: #63E2B7;
&.n-radio-group__splitor--disabled {
background-color: rgba(99, 226, 183, .4);
}
}
&.n-radio-group__splitor--disabled {
background-color: rgba(255,255,255,0.25);
}
}
}
@include b(radio-button) {
@ -92,13 +107,15 @@
line-height: 28px;
border-top: 1px solid rgba(255,255,255,0.5);
border-bottom: 1px solid rgba(255,255,255,0.5);
box-sizing: border-box;
box-sizing: content-box;
color: rgba(233,233,236,1);
transition: background-color .2s $default-cubic-bezier, border-color .2s $default-cubic-bezier;
.n-radio-button__label {
height: 28px;
line-height: 28px;
display: inline-block;
color: rgba(233,233,236,1);
margin: 0 14px;
transition: color .2s $default-cubic-bezier;
}
.n-radio-button__border-mask {
pointer-events: none;
@ -114,7 +131,6 @@
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
border-left: 1px solid rgba(255,255,255,0.5);
border-right: 1px solid rgba(255,255,255,0.5);
.n-radio-button__border-mask {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
@ -123,30 +139,47 @@
&:last-child {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
border-right: 1px solid rgba(255,255,255,0.5);
.n-radio-button__border-mask {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
}
&:not(:first-child):not(:last-child) {
border-right: 1px solid rgba(255,255,255,0.5);
}
&:not(.n-radio-button--disabled) {
cursor: pointer;
&.n-radio-button--checked {
background-color: #63E2B7;
color: #1F263E;
border-color: #63E2B7;
.n-radio-button__label {
color: #1F263E;
transition: color .2s $fast-in-cubic-bezier;
}
}
&:hover .n-radio-button__border-mask {
box-shadow: inset 0 0 0 1px rgba(99, 226, 183, 1);
transition: box-shadow .2s $default-cubic-bezier;
}
&:hover:not(.n-radio-button--checked) .n-radio-button__label {
color: #63E2B7;
}
&:active .n-radio-button__border-mask {
box-shadow: inset 0 0 0 1px rgba(99, 226, 183, 1), 0px 0px 10px 1px rgba(99,226,183,0.3);
}
}
&.n-radio-button--disabled {
cursor: not-allowed;
.n-radio__label {
color: rgba(233,233,236,0.25);
border-color: rgba(255,255,255,0.16);
.n-radio-button__label {
color: rgba(255,255,255,0.25);
}
&.n-radio-button--checked {
color: rgba(31, 38, 62, .25);
border-color: transparent;
background-color: rgba(99, 226, 183, .4);
.n-radio-button__label {
color: rgba(31, 38, 62, .4);
}
}
}
}