This commit is contained in:
oneao committed 2025-09-14 21:38:52 +08:00
1 parent 5e3dccc88b
commit ae0ad2bd63
16 files changed
+201 -109

No files matched your search

@@ -1,2 +1 @@
@use './theme/index.scss' as *;
@@ -17,7 +17,6 @@ $btn-prefix: #{$prefix}-btn;
transition: all 0.2s ease;
font-weight: 500;
border: 1px solid transparent;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
&-small {
height: 24px;
@@ -27,7 +27,6 @@ $drawer-prefix: '#{$prefix}-drawer';
background: #fff;
display: flex;
flex-direction: column;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
transition:
transform 0.25s ease,
opacity 0.25s ease;
@@ -1,4 +1,5 @@
@use './_styles/index.scss' as *;
@use './_styles/variables' as variables;
@use './button/index.scss' as *;
@use './input/index.scss' as *;
@@ -16,3 +17,99 @@
@use './space/index.scss' as *;
@use './separator/index.scss' as *;
@use './radio/index.scss' as *;
[class*='#{variables.$prefix}-'] {
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-family:
'Helvetica', 'Arial', 'PingFangSC-Regular', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', 'Microsoft JhengHei';
}
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
@@ -36,7 +36,6 @@ $input-prefix: #{$prefix}-input;
background-color cubic-bezier(0.38, 0, 0.24, 1) 0.2s;
.#{$input-prefix}-inner {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
width: 100%;
border: none;
outline: none;
@@ -23,7 +23,6 @@ $message-prefix: #{$prefix}-message;
color: $text-color-base;
box-shadow: $shadow-overlay;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
&-message {
font-size: 14px;
line-height: 1;
@@ -19,7 +19,6 @@ $notification-prefix: #{$prefix}-notification;
color: $text-color-base;
box-shadow: $shadow-overlay;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
outline: 0;
border: 0;
margin: 0;
@@ -23,7 +23,6 @@ $popconfirm-prefix: '#{$prefix}-popconfirm';
vertical-align: top;
max-width: 320px;
color: $text-color-base;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
word-break: break-all;
}
@@ -0,0 +1,12 @@
import type { InjectionKey, Slots } from 'vue'
export interface RadioGroupContext {
name: 'ArcoRadioGroup'
value: string | number | boolean
disabled: boolean
slots: Slots
handleChange: (value: string | number | boolean, e: Event) => void
}
export const radioGroupKey: InjectionKey<RadioGroupContext>
= Symbol('RadioGroup')
@@ -3,80 +3,75 @@
$radio-prefix: '#{$prefix}-radio';
.#{$radio-prefix} {
color: $text-color-base;
display: inline-flex;
align-items: center;
gap: 8px;
position: relative;
cursor: pointer;
font-size: 14px;
user-select: none;
&-wrapper {
position: relative;
width: 16px;
height: 16px;
&:hover .#{$radio-prefix}-main .#{$radio-prefix}-inner {
border-color: $primary-color;
}
input[type='radio'] {
position: absolute;
&.#{$radio-prefix}-checked .#{$radio-prefix}-main .#{$radio-prefix}-inner {
border-color: $primary-color;
&::after {
transform: translate(-50%, -50%) scale(1);
background-color: $primary-color;
}
}
.#{$radio-prefix}-main {
cursor: pointer;
display: inline-flex;
white-space: nowrap;
outline: 0;
.#{$radio-prefix}-input {
opacity: 0;
width: 100%;
height: 100%;
outline: 0;
position: absolute;
z-index: -1;
margin: 0;
cursor: pointer;
z-index: 2;
width: 0;
height: 0;
box-sizing: border-box;
}
& .#{$radio-prefix}-circle {
position: absolute;
top: 0;
left: 0;
.#{$radio-prefix}-inner {
border: 1px solid $border-color;
border-radius: 100%;
width: 16px;
height: 16px;
border: 1px solid #d9d9d9;
border-radius: 50%;
background-color: #fff;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
// 勾选圆点
input[type='radio']:checked + .#{$radio-prefix}-circle::after {
content: '';
width: 8px;
height: 8px;
background-color: #1890ff;
border-radius: 50%;
display: block;
animation: scaleIn 0.2s ease forwards;
box-shadow: 0 0 6px #1890ff33; // #33 = 20% 透明度
background-color: $bg-color-container;
position: relative;
display: inline-block;
cursor: pointer;
box-sizing: border-box;
outline: 0;
&::after {
box-sizing: border-box;
width: 8px;
height: 8px;
border-radius: 999px;
background-color: transparent;
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) scale(0);
transition:
transform 0.15s ease-in,
background-color 0.15s ease-in;
}
}
}
&-content {
display: flex;
flex-direction: column;
}
&-disabled {
cursor: not-allowed;
opacity: 0.5;
}
&-clicked {
.#{$radio-prefix}-circle {
transform: scale(0.9);
transition: transform 0.15s ease;
}
}
}
@keyframes scaleIn {
from {
transform: scale(0);
}
to {
transform: scale(1);
.#{$radio-prefix}-content {
font-size: 12px;
margin-left: 8px;
vertical-align: middle;
line-height: 1;
}
}
@@ -1,70 +1,69 @@
import { computed, defineComponent, ref } from 'vue'
import { defineComponent, inject } from 'vue'
import { getPrefixCls } from '../_utils/getPrefixCls'
import { radioGroupKey } from './context'
export default defineComponent({
name: 'AnimatedRadio',
name: 'Radio',
props: {
modelValue: {
type: [String, Number, Boolean],
default: null,
checked: {
type: Boolean,
default: false,
},
value: {
type: [String, Number, Boolean],
required: true,
type: [String, Number],
required: false,
},
disabled: {
type: Boolean,
default: false,
},
class: {
type: [String, Array, Object],
default: '',
},
style: {
type: Object,
default: () => ({}),
// private
uninjectGroupContext: {
type: Boolean,
default: false,
},
},
emits: ['update:modelValue'],
emits: ['change', 'update:checked'],
setup(props, { slots, emit }) {
const prefixCls = getPrefixCls('radio')
const isClicked = ref(false)
const checked = computed(() => props.modelValue === props.value)
const radioGroupCtx = !props.uninjectGroupContext
? inject(radioGroupKey, undefined)
: undefined
const handleChange = () => {
if (!props.disabled) {
emit('update:modelValue', props.value)
// 播放点击动画
isClicked.value = true
setTimeout(() => (isClicked.value = false), 300)
}
const handleClick = () => {
if (props.disabled)
return
const newChecked = !props.checked
emit('update:checked', newChecked)
emit('change', {
value: props.value,
checked: newChecked,
})
}
return () => (
<label
class={[
prefixCls,
props.class,
checked.value ? `${prefixCls}-checked` : '',
props.checked ? `${prefixCls}-checked` : '',
props.disabled ? `${prefixCls}-disabled` : '',
isClicked.value ? `${prefixCls}-clicked` : '',
]}
style={{ ...props.style }}
onClick={handleClick}
>
<div class={`${prefixCls}-wrapper`}>
<span class={`${prefixCls}-main`}>
<span class={`${prefixCls}-inner`} />
<input
class={`${prefixCls}-input`}
type="radio"
value={props.value}
checked={checked.value}
checked={props.checked}
disabled={props.disabled}
onChange={handleChange}
onClick={e => e.stopPropagation()}
/>
<span class={`${prefixCls}-circle`} />
</div>
<div class={`${prefixCls}-content`}>
</span>
<span class={`${prefixCls}-content`}>
{slots.default ? slots.default() : null}
</div>
</span>
</label>
)
},
@@ -8,7 +8,6 @@ $separator-prefix: '#{$prefix}-separator';
padding: 0;
list-style: none;
font-size: 14px;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: $text-color-base;
box-sizing: border-box;
&.#{$separator-prefix}-layout-horizontal {
@@ -14,7 +14,6 @@ $tag-prefix: '#{$prefix}-tag';
border: 1px solid transparent;
white-space: nowrap;
border-radius: $border-color;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
&.#{$tag-prefix}-size-large {
padding: 0 8px;
@@ -6,7 +6,6 @@ import Icon from '../icon/index'
export default defineComponent({
name: 'Tag',
props: {
shape: {
type: String as PropType<'square' | 'round' | 'mark'>,
default: 'square',
@@ -12,7 +12,6 @@ $textarea-prefix: #{$prefix}-textarea;
width: 100%;
.#{$textarea-prefix}-inner {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
height: 100%;
width: 100%;
display: flex;
+2 -2
View File
@@ -3,8 +3,8 @@
<template>
<div style="height: 800px;display: flex;align-items: center;justify-content: center;">
<ARadio>
123
<ARadio :checked="true">
选项一
</ARadio>
</div>
</template>