-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SelectUnstyled] Create unstyled select (+ hook) #30113
Merged
Merged
Changes from 59 commits
Commits
Show all changes
61 commits
Select commit
Hold shift + click to select a range
09e24c1
Create useListbox implementation
michaldudak 1bef211
Add few tests
michaldudak b2ba738
Add tests and small fixes
michaldudak 0ff3247
Remove temporary demos
michaldudak 140b8b9
Add more jsdoc comments
michaldudak 3b632a5
Cleanup
michaldudak b9fc66c
Improvements after CR
michaldudak 88d69db
Merge branch 'master' into unstyled-listbox
michaldudak 3252a28
Merge branch 'master' into unstyled-listbox
michaldudak 3e41655
Create SelectUnstyled and useSelect
michaldudak 1e2da48
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak 99c9c57
Fix TS compilation error
michaldudak 864b85d
Fix proptypes generation in SelectUnstyled
michaldudak 20c010d
Fix docs generation
michaldudak 7dc728d
Fix conformance tests
michaldudak 93e8a04
Fix passing ownerState to slots
michaldudak 07f57e7
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak 96627c5
Docs and demos
michaldudak 432eaee
Merge branch 'master' into unstyled-select
michaldudak 77b906a
Fix stylelint errors
michaldudak 7b4a133
Fix tests
michaldudak fe0988f
Accept external event handlers
michaldudak 0900af3
Export SingleSelectUnstyled and MultiSelectUnstyled
michaldudak c023e22
Correct imports in demos
michaldudak 5e4cd6d
Fix the tests
michaldudak d263a44
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak 7bda657
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak cfed174
Improve useSelect types, add demo
michaldudak a03bbae
Improve types
michaldudak ac01aaa
Polish the implementation and demos
michaldudak a61c6aa
Fix TS errors
michaldudak 6cb1975
Move option rendering logic to OptionUnstyled and OptionGroupUnstyled
michaldudak 8e723d1
Remove duplicated export
michaldudak a1feede
Move OptionUnstyled out of Select directory
michaldudak a6518ee
Prop types and API docs
michaldudak 4a64150
Fix unit tests
michaldudak 101174c
Fix problem with API docs generation
michaldudak 6693c8e
Clean up the demos
michaldudak 9fe65ea
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak a5b17c7
PR fixes
michaldudak 22ed1e9
Export SelectUnstyled and MultiSelectUntyled
michaldudak 9852828
Add a not about forwardRef
michaldudak ea26853
Move MultiSelectUnstyled to its own directory
michaldudak 81b6b71
API docs
michaldudak 72a19c4
Fix errors
michaldudak 04b1fcd
Merge branch 'master' into unstyled-select
michaldudak 3e00b30
Fix runtime errors in demos
michaldudak d81dbb5
Fix issues reported in PR
michaldudak 91600c8
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak 26a236f
Proptypes
michaldudak a778b69
Add preventDefault for arrow key presses
michaldudak 064b927
Use enter key to open the dropdown
michaldudak bd2c8fe
Tests
michaldudak 65ec3f0
Proptypes
michaldudak c52328a
Scroll highlighted element into view
michaldudak 31aa964
Call scrollIntoView only if available
michaldudak b8f373a
Allow customizing popper
michaldudak 2ace209
Merge remote-tracking branch 'upstream/master' into unstyled-select
michaldudak f1796d2
Update docs/src/pages/components/selects/UnstyledSelectObjectValues.tsx
michaldudak 07d9f85
Test opening and selection with different keys
michaldudak 7cbfc7d
Move focus management to useSelect, update tests and demos
michaldudak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react'; | ||
import ApiPage from 'docs/src/modules/components/ApiPage'; | ||
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; | ||
import jsonPageContent from './multi-select-unstyled.json'; | ||
|
||
export default function Page(props) { | ||
const { descriptions, pageContent } = props; | ||
return <ApiPage descriptions={descriptions} pageContent={pageContent} />; | ||
} | ||
|
||
Page.getInitialProps = () => { | ||
const req = require.context( | ||
'docs/translations/api-docs/multi-select-unstyled', | ||
false, | ||
/multi-select-unstyled.*.json$/, | ||
); | ||
const descriptions = mapApiPageTranslations(req); | ||
|
||
return { | ||
descriptions, | ||
pageContent: jsonPageContent, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"props": { | ||
"autoFocus": { "type": { "name": "bool" } }, | ||
"components": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ Listbox?: elementType, Popper?: elementType, Root?: elementType }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"componentsProps": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ listbox?: object, popper?: object, root?: object }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"defaultListboxOpen": { "type": { "name": "bool" } }, | ||
"defaultValue": { "type": { "name": "array" }, "default": "[]" }, | ||
"disabled": { "type": { "name": "bool" } }, | ||
"listboxOpen": { "type": { "name": "bool" }, "default": "undefined" }, | ||
"onChange": { "type": { "name": "func" } }, | ||
"onListboxOpenChange": { "type": { "name": "func" } }, | ||
"renderValue": { "type": { "name": "func" } }, | ||
"value": { "type": { "name": "array" } } | ||
}, | ||
"name": "MultiSelectUnstyled", | ||
"styles": { "classes": [], "globalClasses": {}, "name": null }, | ||
"spread": true, | ||
"forwardsRefTo": "HTMLButtonElement", | ||
"filename": "/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.tsx", | ||
"inheritance": null, | ||
"demos": "<ul><li><a href=\"/components/selects/\">Selects</a></li></ul>", | ||
"cssComponent": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react'; | ||
import ApiPage from 'docs/src/modules/components/ApiPage'; | ||
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; | ||
import jsonPageContent from './option-group-unstyled.json'; | ||
|
||
export default function Page(props) { | ||
const { descriptions, pageContent } = props; | ||
return <ApiPage descriptions={descriptions} pageContent={pageContent} />; | ||
} | ||
|
||
Page.getInitialProps = () => { | ||
const req = require.context( | ||
'docs/translations/api-docs/option-group-unstyled', | ||
false, | ||
/option-group-unstyled.*.json$/, | ||
); | ||
const descriptions = mapApiPageTranslations(req); | ||
|
||
return { | ||
descriptions, | ||
pageContent: jsonPageContent, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"props": { | ||
"component": { "type": { "name": "elementType" } }, | ||
"components": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ Label?: elementType, List?: elementType, Root?: elementType }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"componentsProps": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ label?: object, list?: object, root?: object }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"disabled": { "type": { "name": "bool" } }, | ||
"label": { "type": { "name": "node" } } | ||
}, | ||
"name": "OptionGroupUnstyled", | ||
"styles": { "classes": [], "globalClasses": {}, "name": null }, | ||
"spread": true, | ||
"forwardsRefTo": "HTMLLIElement", | ||
"filename": "/packages/mui-base/src/OptionGroupUnstyled/OptionGroupUnstyled.tsx", | ||
"inheritance": null, | ||
"demos": "<ul><li><a href=\"/components/selects/\">Selects</a></li></ul>", | ||
"cssComponent": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react'; | ||
import ApiPage from 'docs/src/modules/components/ApiPage'; | ||
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; | ||
import jsonPageContent from './option-unstyled.json'; | ||
|
||
export default function Page(props) { | ||
const { descriptions, pageContent } = props; | ||
return <ApiPage descriptions={descriptions} pageContent={pageContent} />; | ||
} | ||
|
||
Page.getInitialProps = () => { | ||
const req = require.context( | ||
'docs/translations/api-docs/option-unstyled', | ||
false, | ||
/option-unstyled.*.json$/, | ||
); | ||
const descriptions = mapApiPageTranslations(req); | ||
|
||
return { | ||
descriptions, | ||
pageContent: jsonPageContent, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"props": { | ||
"value": { "type": { "name": "any" }, "required": true }, | ||
"component": { "type": { "name": "elementType" } }, | ||
"components": { | ||
"type": { "name": "shape", "description": "{ Root?: elementType }" }, | ||
"default": "{}" | ||
}, | ||
"componentsProps": { | ||
"type": { "name": "shape", "description": "{ root?: object }" }, | ||
"default": "{}" | ||
}, | ||
"disabled": { "type": { "name": "bool" } } | ||
}, | ||
"name": "OptionUnstyled", | ||
"styles": { "classes": [], "globalClasses": {}, "name": null }, | ||
"spread": true, | ||
"forwardsRefTo": "HTMLLIElement", | ||
"filename": "/packages/mui-base/src/OptionUnstyled/OptionUnstyled.tsx", | ||
"inheritance": null, | ||
"demos": "<ul><li><a href=\"/components/selects/\">Selects</a></li></ul>", | ||
"cssComponent": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react'; | ||
import ApiPage from 'docs/src/modules/components/ApiPage'; | ||
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; | ||
import jsonPageContent from './select-unstyled.json'; | ||
|
||
export default function Page(props) { | ||
const { descriptions, pageContent } = props; | ||
return <ApiPage descriptions={descriptions} pageContent={pageContent} />; | ||
} | ||
|
||
Page.getInitialProps = () => { | ||
const req = require.context( | ||
'docs/translations/api-docs/select-unstyled', | ||
false, | ||
/select-unstyled.*.json$/, | ||
); | ||
const descriptions = mapApiPageTranslations(req); | ||
|
||
return { | ||
descriptions, | ||
pageContent: jsonPageContent, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"props": { | ||
"autoFocus": { "type": { "name": "bool" } }, | ||
"components": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ Listbox?: elementType, Popper?: elementType, Root?: elementType }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"componentsProps": { | ||
"type": { | ||
"name": "shape", | ||
"description": "{ listbox?: object, popper?: object, root?: object }" | ||
}, | ||
"default": "{}" | ||
}, | ||
"defaultListboxOpen": { "type": { "name": "bool" } }, | ||
"defaultValue": { "type": { "name": "any" } }, | ||
"disabled": { "type": { "name": "bool" } }, | ||
"listboxOpen": { "type": { "name": "bool" }, "default": "undefined" }, | ||
"onChange": { "type": { "name": "func" } }, | ||
"onListboxOpenChange": { "type": { "name": "func" } }, | ||
"renderValue": { "type": { "name": "func" } }, | ||
"value": { "type": { "name": "any" } } | ||
}, | ||
"name": "SelectUnstyled", | ||
"styles": { "classes": [], "globalClasses": {}, "name": null }, | ||
"spread": true, | ||
"forwardsRefTo": "HTMLButtonElement", | ||
"filename": "/packages/mui-base/src/SelectUnstyled/SelectUnstyled.tsx", | ||
"inheritance": null, | ||
"demos": "<ul><li><a href=\"/components/selects/\">Selects</a></li></ul>", | ||
"cssComponent": false | ||
} |
129 changes: 129 additions & 0 deletions
129
docs/src/pages/components/selects/UnstyledSelectControlled.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import * as React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import SelectUnstyled, { selectUnstyledClasses } from '@mui/base/SelectUnstyled'; | ||
import OptionUnstyled, { optionUnstyledClasses } from '@mui/base/OptionUnstyled'; | ||
import PopperUnstyled from '@mui/base/PopperUnstyled'; | ||
import { styled } from '@mui/system'; | ||
|
||
const StyledButton = styled('button')` | ||
font-family: IBM Plex Sans, sans-serif; | ||
font-size: 0.875rem; | ||
box-sizing: border-box; | ||
min-height: calc(1.5em + 22px); | ||
min-width: 200px; | ||
background: #fff; | ||
border: 1px solid #ccc; | ||
border-radius: 0.75em; | ||
margin: 0.5em; | ||
padding: 10px; | ||
text-align: left; | ||
line-height: 1.5; | ||
color: #000; | ||
&.${selectUnstyledClasses.focusVisible} { | ||
outline: 4px solid rgba(100, 100, 100, 0.3); | ||
} | ||
&.${selectUnstyledClasses.expanded} { | ||
border-radius: 0.75em 0.75em 0 0; | ||
&::after { | ||
content: '▴'; | ||
} | ||
} | ||
&::after { | ||
content: '▾'; | ||
float: right; | ||
} | ||
`; | ||
|
||
const StyledListbox = styled('ul')` | ||
font-family: IBM Plex Sans, sans-serif; | ||
font-size: 0.875rem; | ||
box-sizing: border-box; | ||
padding: 0; | ||
margin: 0; | ||
background-color: #fff; | ||
min-width: 200px; | ||
border: 1px solid #ccc; | ||
border-top: none; | ||
color: #000; | ||
`; | ||
|
||
const StyledOption = styled(OptionUnstyled)` | ||
list-style: none; | ||
padding: 4px 10px; | ||
margin: 0; | ||
border-bottom: 1px solid #ddd; | ||
cursor: default; | ||
&:last-of-type { | ||
border-bottom: none; | ||
} | ||
&.${optionUnstyledClasses.disabled} { | ||
color: #888; | ||
} | ||
&.${optionUnstyledClasses.selected} { | ||
background-color: rgba(25, 118, 210, 0.08); | ||
} | ||
&.${optionUnstyledClasses.highlighted} { | ||
background-color: #16d; | ||
color: #fff; | ||
} | ||
&.${optionUnstyledClasses.highlighted}.${optionUnstyledClasses.selected} { | ||
background-color: #05e; | ||
color: #fff; | ||
} | ||
&:hover:not(.${optionUnstyledClasses.disabled}) { | ||
background-color: #39e; | ||
} | ||
`; | ||
|
||
const StyledPopper = styled(PopperUnstyled)` | ||
z-index: 1; | ||
`; | ||
|
||
function CustomSelect(props) { | ||
const components = { | ||
Root: StyledButton, | ||
Listbox: StyledListbox, | ||
Popper: StyledPopper, | ||
...props.components, | ||
}; | ||
|
||
return <SelectUnstyled {...props} components={components} />; | ||
} | ||
|
||
CustomSelect.propTypes = { | ||
/** | ||
* The components used for each slot inside the Select. | ||
* Either a string to use a HTML element or a component. | ||
* @default {} | ||
*/ | ||
components: PropTypes.shape({ | ||
Listbox: PropTypes.elementType, | ||
Popper: PropTypes.elementType, | ||
Root: PropTypes.elementType, | ||
}), | ||
}; | ||
|
||
export default function UnstyledSelectsMultiple() { | ||
const [value, setValue] = React.useState(10); | ||
return ( | ||
<div> | ||
<CustomSelect value={value} onChange={setValue}> | ||
<StyledOption value={10}>Ten</StyledOption> | ||
<StyledOption value={20}>Twenty</StyledOption> | ||
<StyledOption value={30}>Thirty</StyledOption> | ||
</CustomSelect> | ||
|
||
<p>Selected value: {value}</p> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you decided to disable this on the whole project?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just for the demos. I don't think proptypes add anything valuable.
Currently, they were required for JS files, but not for TS and since we generate one from the other, it was tricky to make things right.