Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 5d18525

Browse files
feat(c-radio): add radio
1 parent aaadd1a commit 5d18525

File tree

6 files changed

+157
-22
lines changed

6 files changed

+157
-22
lines changed

packages/c-radio/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"@chakra-ui/vue-composables": "workspace:*",
3232
"@chakra-ui/vue-utils": "workspace:*",
3333
"@zag-js/radio-group": "0.7.0",
34-
"@zag-js/vue": "0.7.0"
34+
"@zag-js/vue": "0.7.0",
35+
"@chakra-ui/styled-system": "2.9.0"
3536
},
3637
"devDependencies": {
3738
"vue": "^3.2.37"

packages/c-radio/src/c-radio-group.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
useMultiStyleConfig,
88
} from "@chakra-ui/vue-system"
99
import { RadioGroupProvider, RadioGroupStylesProvider } from "./radio-context"
10-
import { useThemingProps } from "@chakra-ui/vue-utils"
10+
import { useThemingProps, vueThemingProps } from "@chakra-ui/vue-utils"
1111

1212
export interface CRadioGroupProps
1313
extends UseRadioGroupProps,
@@ -44,6 +44,7 @@ export const CRadioGroup = defineComponent({
4444
readonly: {
4545
type: Boolean as PropType<CRadioGroupProps["readOnly"]>,
4646
},
47+
...vueThemingProps,
4748
},
4849
emits: ["change", "update:modelValue"],
4950
setup(props, { slots, attrs }) {

packages/c-radio/src/c-radio.tsx

+115-15
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,126 @@
88
* @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices-1.2
99
*/
1010

11-
import { defineComponent, h, Fragment, PropType } from "vue"
11+
import {
12+
computed,
13+
defineComponent,
14+
h,
15+
InputHTMLAttributes,
16+
isVNode,
17+
mergeProps,
18+
PropType,
19+
reactive,
20+
} from "vue"
1221
import {
1322
chakra,
14-
DOMElements,
23+
HTMLChakraProps,
24+
type ThemingProps,
25+
type StyleResolverProps,
26+
useMultiStyleConfig,
1527
} from "@chakra-ui/vue-system"
28+
import * as VS from "@chakra-ui/vue-system"
29+
import { SNAO, vueThemingProps } from "@chakra-ui/vue-utils"
30+
import { RadioContext, useRadioGroupContext } from "./radio-context"
1631

17-
export interface CRadioProps {}
32+
export interface CRadioProps
33+
extends Omit<HTMLChakraProps<"label">, keyof RadioContext>,
34+
ThemingProps<"Radio">,
35+
RadioContext {
36+
/**
37+
* The spacing between the checkbox and its label text
38+
* @default 0.5rem
39+
* @type SystemProps["marginLeft"]
40+
*/
41+
spacing?: StyleResolverProps["marginLeft"]
42+
/**
43+
* Additional props to be forwarded to the `input` element
44+
*/
45+
inputProps?: InputHTMLAttributes
46+
}
1847

1948
export const CRadio = defineComponent({
20-
props: {
21-
as: {
22-
type: [Object, String] as PropType<DOMElements>,
23-
default: "div",
24-
},
49+
props: {
50+
value: {
51+
type: String as PropType<CRadioProps["value"]>,
52+
required: true,
53+
},
54+
disabled: {
55+
type: Boolean as PropType<CRadioProps["disabled"]>,
56+
},
57+
invalid: {
58+
type: Boolean as PropType<CRadioProps["invalid"]>,
59+
},
60+
readOnly: {
61+
type: Boolean as PropType<CRadioProps["readOnly"]>,
2562
},
26-
setup(props, { slots, attrs }) {
27-
return () => (
28-
<chakra.div as={props.as} {...attrs}>
29-
{slots}
30-
</chakra.div>
31-
)
63+
spacing: {
64+
type: SNAO as PropType<CRadioProps["spacing"]>,
3265
},
33-
})
66+
...vueThemingProps,
67+
},
68+
setup(props, { slots, attrs }) {
69+
const groupApi = useRadioGroupContext()
70+
71+
const styleAttrs = computed(() => mergeProps(props, groupApi.value, attrs))
72+
73+
const styles = useMultiStyleConfig("Radio", styleAttrs)
74+
75+
const radioProps = reactive({
76+
value: props.value,
77+
disabled: props.disabled,
78+
invalid: props.invalid,
79+
readOnly: props.readOnly,
80+
})
81+
82+
const inputProps = computed(() => {
83+
const apiInputProps = groupApi.value.getRadioInputProps(radioProps)
84+
const apiInputState = groupApi.value.getRadioState(radioProps)
85+
86+
return {
87+
...apiInputProps,
88+
modelValue: apiInputState.isChecked,
89+
}
90+
})
91+
92+
const labelStyles = computed(() => ({
93+
userSelect: "none",
94+
marginStart: props.spacing,
95+
...styles.value.label,
96+
}))
97+
98+
const controlStyles = computed(() => ({
99+
display: "inline-flex",
100+
alignItems: "center",
101+
justifyContent: "center",
102+
flexShrink: 0,
103+
...styles.value.control,
104+
}))
105+
106+
const RadioLabel = computed(() => {
107+
return isVNode(slots.default) ? (
108+
<chakra.span
109+
__label="radio__label"
110+
{...groupApi.value.getRadioLabelProps(radioProps)}
111+
>
112+
{slots.default?.()}
113+
</chakra.span>
114+
) : null
115+
})
116+
117+
return () => (
118+
<chakra.label {...groupApi.value.getRadioProps(radioProps)} {...attrs}>
119+
<chakra.input
120+
__label="radio__input"
121+
{...inputProps.value}
122+
__css={labelStyles.value}
123+
/>
124+
<chakra.span
125+
__label="radio__control"
126+
{...groupApi.value.getRadioControlProps(radioProps)}
127+
__css={controlStyles.value}
128+
/>
129+
{RadioLabel.value}
130+
</chakra.label>
131+
)
132+
},
133+
})

packages/c-radio/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { CRadioGroup, type CRadioGroupProps } from "./c-radio-group"
2+
export { CRadio, type CRadioProps } from "./c-radio"
23
export { RadioGroupContext } from "./radio-context"

packages/c-radio/src/radio-context.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import * as CSS from "csstype"
12
import * as radio from "@zag-js/radio-group"
23
import { createContext } from "@chakra-ui/vue-utils"
34
import type { UseRadioGroupReturn } from "./use-radio-group"
45
import { UnwrapRef } from "vue"
56
import { createStylesContext } from "@chakra-ui/vue-system"
7+
import * as VS from "@chakra-ui/vue-system"
68

79
export type RadioContext = Parameters<
810
ReturnType<typeof radio.connect>["getRadioProps"]

pnpm-lock.yaml

+35-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)