diff --git a/app/components/malio/date/internal/MonthPicker.test.ts b/app/components/malio/date/internal/MonthPicker.test.ts
new file mode 100644
index 0000000..be9379c
--- /dev/null
+++ b/app/components/malio/date/internal/MonthPicker.test.ts
@@ -0,0 +1,33 @@
+import { describe, expect, it } from 'vitest'
+import { mount } from '@vue/test-utils'
+import MonthPicker from './MonthPicker.vue'
+
+const mountPicker = (props: { currentYear: number, selectedMonth?: number, min?: string, max?: string }) =>
+ mount(MonthPicker, { props })
+
+describe('MalioDateMonthPicker', () => {
+ it('renders 12 months', () => {
+ const wrapper = mountPicker({ currentYear: 2026 })
+ expect(wrapper.findAll('[data-test="month"]')).toHaveLength(12)
+ })
+
+ it('emits select with the clicked month index', async () => {
+ const wrapper = mountPicker({ currentYear: 2026 })
+ await wrapper.get('[data-test="month"][data-month="0"]').trigger('click')
+ expect(wrapper.emitted('select')?.[0]).toEqual([0])
+ })
+
+ it('disables months before min in the current year and does not emit', async () => {
+ const wrapper = mountPicker({ currentYear: 2026, min: '2026-05-01' })
+ const april = wrapper.get('[data-test="month"][data-month="3"]')
+ expect(april.attributes('disabled')).toBeDefined()
+ await april.trigger('click')
+ expect(wrapper.emitted('select')).toBeUndefined()
+ })
+
+ it('disables months after max in the current year', () => {
+ const wrapper = mountPicker({ currentYear: 2026, max: '2026-05-31' })
+ expect(wrapper.get('[data-test="month"][data-month="5"]').attributes('disabled')).toBeDefined()
+ expect(wrapper.get('[data-test="month"][data-month="4"]').attributes('disabled')).toBeUndefined()
+ })
+})
diff --git a/app/components/malio/date/internal/MonthPicker.vue b/app/components/malio/date/internal/MonthPicker.vue
index 2b525a1..ab16781 100644
--- a/app/components/malio/date/internal/MonthPicker.vue
+++ b/app/components/malio/date/internal/MonthPicker.vue
@@ -9,14 +9,19 @@
type="button"
data-test="month"
:data-month="index"
+ :disabled="!isMonthInRange(currentYear, index, min, max)"
+ :aria-disabled="!isMonthInRange(currentYear, index, min, max)"
class="flex h-[45px] w-full items-center justify-center"
+ :class="isMonthInRange(currentYear, index, min, max) ? 'cursor-pointer' : 'cursor-not-allowed'"
@click="emit('select', index)"
>
{{ name }}
@@ -25,9 +30,16 @@