mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-24 12:45:18 +08:00
feat(radio): radio button group
This commit is contained in:
parent
8089b55766
commit
c4b5e17ebb
@ -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',
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user