diff --git a/.changeset/real-cycles-hammer.md b/.changeset/real-cycles-hammer.md new file mode 100644 index 00000000..fa099ba3 --- /dev/null +++ b/.changeset/real-cycles-hammer.md @@ -0,0 +1,6 @@ +--- +"@chakra-ui/vue": patch +"@chakra-ui/nuxt": patch +--- + +fix(select): prevent duplicated ID on wrapper + input diff --git a/packages/chakra-ui-core/src/CSelect/CSelect.js b/packages/chakra-ui-core/src/CSelect/CSelect.js index 0221dce8..cb98e0e9 100644 --- a/packages/chakra-ui-core/src/CSelect/CSelect.js +++ b/packages/chakra-ui-core/src/CSelect/CSelect.js @@ -166,6 +166,12 @@ const CSelect = { position: 'relative', width: '100%' } + }, + filteredComputedAttrs () { + // filter ID from attributes to not insert it on both the wrapper + // and the select itself. See https://github.com/chakra-ui/chakra-ui-vue/issues/484 + const removeIdFromAttrs = Object.entries(this.computedAttrs).filter(([key, _attr]) => key !== 'id') + return Object.fromEntries(removeIdFromAttrs) } }, render (h) { @@ -174,7 +180,7 @@ const CSelect = { return h('div', { class: [this.className], attrs: { - ...this.computedAttrs, + ...this.filteredComputedAttrs, 'data-chakra-component': 'CSelect' } }, [ diff --git a/packages/chakra-ui-core/src/CSelect/CSelect.stories.js b/packages/chakra-ui-core/src/CSelect/CSelect.stories.js index 0569341d..cbce9ef5 100644 --- a/packages/chakra-ui-core/src/CSelect/CSelect.stories.js +++ b/packages/chakra-ui-core/src/CSelect/CSelect.stories.js @@ -7,7 +7,7 @@ storiesOf('UI | Select', module) components: { CBox, CSelect }, template: ` - + @@ -60,3 +60,28 @@ storiesOf('UI | Select', module) /> ` })) + .add('Disabled select', () => ({ + components: { CSelect }, + template: ` + + + + + + + + `, + data () { + return { + value: 'option3' + } + }, + watch: { + value (newValue) { + this.action('Selected value', newValue) + } + }, + methods: { + action: action() + } + })) diff --git a/packages/chakra-ui-core/src/CSelect/tests/CSelect.test.js b/packages/chakra-ui-core/src/CSelect/tests/CSelect.test.js new file mode 100644 index 00000000..f227b148 --- /dev/null +++ b/packages/chakra-ui-core/src/CSelect/tests/CSelect.test.js @@ -0,0 +1,38 @@ +import { CSelect } from '../..' +import { render, screen } from '@/tests/test-utils' + +const renderComponent = (props) => { + const inlineAttrs = (props && props.inlineAttrs) || '' + const base = { + data: () => ({ value: 'option1' }), + components: { CSelect }, + template: ` + + + + `, + ...props + } + return render(base) +} + +test('should render correctly', () => { + const { asFragment } = renderComponent() + expect(asFragment()).toMatchSnapshot() +}) + +test('disabled select renders correctly', () => { + renderComponent({ inlineAttrs: 'isDisabled' }) + const select = screen.getByRole('combobox') + + expect(select).toHaveAttribute('disabled') +}) + +test('passes the ID directly to the select and not to the wrapper', () => { + renderComponent() + const select = screen.getByRole('combobox') + const selectWrapper = screen.getByTestId('select') + + expect(select).toHaveAttribute('id') + expect(selectWrapper).not.toHaveAttribute('id') +}) diff --git a/packages/chakra-ui-core/src/CSelect/tests/__snapshots__/CSelect.test.js.snap b/packages/chakra-ui-core/src/CSelect/tests/__snapshots__/CSelect.test.js.snap new file mode 100644 index 00000000..865f6788 --- /dev/null +++ b/packages/chakra-ui-core/src/CSelect/tests/__snapshots__/CSelect.test.js.snap @@ -0,0 +1,184 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + + .emotion-0 { + position: relative; + width: 100%; +} + +.emotion-1 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: relative; + -webkit-transition: all 0.2s; + transition: all 0.2s; + outline: 2px solid transparent; + outline-offset: 2px; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + font-size: var(--fontSizes-md); + -webkit-padding-start: var(--space-4); + padding-inline-start: var(--space-4); + -webkit-padding-end: var(--space-4); + padding-inline-end: var(--space-4); + height: var(--sizes-10); + line-height: var(--lineHeights-normal); + border-radius: var(--radii-md); + border-width: 1px; + border-color: inherit; + background: var(--colors-white); + font-family: var(--fonts-body); + padding-right: 2rem; + padding-bottom: var(--space-px); + color: inherit; +} + +.emotion-1[aria-readonly=true], +.emotion-1[readonly], +.emotion-1[data-readonly] { + background: var(--colors-transparent); + box-shadow: none!important; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + user-select: all; +} + +.emotion-1:hover, +.emotion-1[data-hover] { + border-color: var(--colors-gray-300); +} + +.emotion-1[disabled], +.emotion-1[aria-disabled=true], +.emotion-1[data-disabled] { + opacity: 0.4; + cursor: not-allowed; +} + +.emotion-1:focus, +.emotion-1[data-focus] { + z-index: 1; + border-color: #7db1ff; + box-shadow: 0 0 0 1px #7db1ff; +} + +.emotion-1[aria-invalid=true], +.emotion-1[data-invalid] { + border-color: #e66673; + box-shadow: 0 0 0 1px #e66673; +} + +.emotion-2 { + color: inherit; + position: absolute; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + width: 1.5rem; + height: 100%; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + right: 0.5rem; + top: 50%; + pointer-events: none; + z-index: 2; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); +} + +.emotion-3 { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} + +.emotion-3:not(:root) { + overflow: hidden; +} + +.emotion-4 { + width: var(--sizes-5); + height: var(--sizes-5); + display: inline-block; + vertical-align: middle; +} + +
+ +
+ +
+
+
+`;