Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
<template>
<main>
Vue-Tailwind
</main>
<div>
<RadioInput
id="radio1"
name="radioGroup"
label="radioGroup"
value="option1"
:checked="selectedOption === 'option1'"
:disabled="isDisabled"
@change="handleRadioChange"
>
<template #label="{ label }">
<span class="font-semibold">{{ label }}</span>
</template>
</RadioInput>

<RadioInput
id="radio2"
name="radioGroup"
value="option2"
label="option2"
:checked="selectedOption === 'option2'"
:disabled="isDisabled"
@change="handleRadioChange"
>
<template #label="{ label }">
<span>{{ label }}</span>
</template>
</RadioInput>

<p v-if="hint" data-test="hint">{{ hint }}</p>
</div>
</template>

<script setup lang="ts">
import RadioInput from './components/DxhRadio.vue'
import { ref } from 'vue'

const selectedOption = ref<string | null>(null)
const isDisabled = ref(false)
const hint = ref('This is a hint.')

const handleRadioChange = (value) => {
selectedOption.value = value
console.log('Selected Option:', value)
}
</script>
40 changes: 40 additions & 0 deletions src/components/DxhRadio.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<div class="flex items-center space-x-1">
<input
type="radio"
:id="id"
:name="name"
:value="value"
:checked="defaultChecked ? defaultChecked : checked"
:disabled="disabled"
:class="{ 'opacity-50 cursor-not-allowed': disabled }"
data-test="radio"
@change="handleChange"
/>
<label v-if="label" :for="id" :class="{ 'opacity-50': disabled }" data-test="label">
<slot name="label" :label="label">{{ label }}</slot>
</label>
</div>
<p v-if="hint" data-test="hint">{{ hint }}</p>
</template>

<script setup lang="ts">
const props = defineProps<{
id: string
name?: string
value?: string
label?: string
checked: boolean
defaultChecked?: boolean
hint?: string
disabled?: boolean
}>()

const emit = defineEmits(['change'])

const handleChange = (event: any) => {
if (!props.disabled) {
emit('change', event)
}
}
</script>
45 changes: 45 additions & 0 deletions src/components/__tests__/DxhRadio.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import DxhRadio from '../DxhRadio.vue'

describe('DxhRadio.vue', () => {
it('renders a radio button with the correct default state', async () => {
const wrapper: any = mount(DxhRadio, {
props: {
id: '1',
name: 'radioGroup',
value: 'option1',
label: 'Option 1',
checked: false,
defaultChecked: false,
hint: 'Select this option',
disabled: false
}
})

expect(wrapper.find('[data-test="radio"]').exists()).toBe(true)
expect(wrapper.find('[data-test="radio"]').element.checked).toBe(false)
expect(wrapper.find('[data-test="label"]').text()).toBe('Option 1')
expect(wrapper.find('[data-test="hint"]').text()).toBe('Select this option')
})

it('emits a change event when the radio button is clicked', async () => {
const wrapper: any = mount(DxhRadio, {
props: {
id: '2',
name: 'radioGroup',
value: 'option2',
label: 'Option 2',
checked: false,
defaultChecked: false,
hint: 'Select this option',
disabled: false
}
})

await wrapper.find('[data-test="radio"]').trigger('change')

expect(wrapper.emitted()).toHaveProperty('change')
expect(wrapper.emitted('change')[0]).toEqual([expect.any(Object)])
})
})
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import DButton from "./components/DButton.vue"
import DInput from "./components/DInput.vue"
import DButton from './components/DButton.vue'
import DInput from './components/DInput.vue'
import DxhRadio from './components/DxhRadio.vue'

export default {DButton, DInput}
export default { DButton, DInput, DxhRadio }