Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: implement design system selects
- Loading branch information
Showing
16 changed files
with
369 additions
and
124 deletions.
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
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
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
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 |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import { forwardRef } from "react"; | ||
import { Label as _Label } from "theme-ui"; | ||
|
||
export default function Label(props) { | ||
return <_Label {...props} />; | ||
} | ||
const Label = forwardRef((props, ref) => <_Label ref={ref} {...props} />); | ||
Label.displayName = "Label"; | ||
export default Label; |
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 |
---|---|---|
@@ -1,9 +1,11 @@ | ||
import { forwardRef } from "react"; | ||
import { Box } from "theme-ui"; | ||
|
||
export default function List(props) { | ||
return <Box as="ul" {...props} />; | ||
} | ||
const List = forwardRef((props, ref) => <Box ref={ref} as="ul" {...props} />); | ||
List.displayName = "List"; | ||
export default List; | ||
|
||
export function ListItem(props) { | ||
return <Box as="li" {...props} />; | ||
} | ||
export const ListItem = forwardRef((props, ref) => ( | ||
<Box ref={ref} as="li" {...props} /> | ||
)); | ||
ListItem.displayName = "ListItem"; |
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,51 @@ | ||
import lodashKebabCase from "lodash.kebabcase"; | ||
import lodashStartCase from "lodash.startcase"; | ||
|
||
export const zeroAddress = "0x0000000000000000000000000000000000000000"; | ||
|
||
export const ethereumAddressRegExp = /^0x[\dA-Fa-f]{40}$/; | ||
|
||
export const createEnum = (keys, parse) => { | ||
const _enum = keys.reduce( | ||
(acc, key, index) => { | ||
let extra; | ||
if (Array.isArray(key)) [key, extra] = key; | ||
|
||
const value = { | ||
key, | ||
index, | ||
camelCase: key[0].toLowerCase() + key.slice(1), | ||
kebabCase: lodashKebabCase(key), | ||
startCase: lodashStartCase(key), | ||
...extra, | ||
}; | ||
value.color = value.camelCase; | ||
value.toString = () => value.startCase; | ||
|
||
acc[key] = value; | ||
acc[index] = value; | ||
acc[value.camelCase] = value; | ||
acc[value.kebabCase] = value; | ||
acc[value.startCase] = value; | ||
return acc; | ||
}, | ||
{ | ||
parse: | ||
parse || | ||
((arrayOrKey) => | ||
Array.isArray(arrayOrKey) | ||
? arrayOrKey.reduce((acc, key) => { | ||
const value = _enum[key]; | ||
acc[key] = value; | ||
acc[value.index] = value; | ||
acc[value.camelCase] = value; | ||
acc[value.kebabCase] = value; | ||
acc[value.startCase] = value; | ||
return acc; | ||
}, {}) | ||
: _enum[arrayOrKey]), | ||
} | ||
); | ||
_enum.array = keys.map((_, index) => _enum[index]); | ||
return _enum; | ||
}; |
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 |
---|---|---|
@@ -1,9 +1,143 @@ | ||
import { Box, Select as _Select } from "theme-ui"; | ||
import { alpha } from "@theme-ui/color"; | ||
import { useSelect } from "downshift"; | ||
import { useRef } from "react"; | ||
import { usePopper } from "react-popper"; | ||
import { Box } from "theme-ui"; | ||
|
||
export default function Select(props) { | ||
return <_Select {...props} />; | ||
import Button from "./button"; | ||
import Label from "./label"; | ||
import List, { ListItem } from "./list"; | ||
|
||
const popperOptions = { | ||
modifiers: [ | ||
{ | ||
name: "sameWidth", | ||
enabled: true, | ||
phase: "beforeWrite", | ||
fn({ state }) { | ||
state.styles.popper.width = `${state.rects.reference.width}px`; | ||
}, | ||
requires: ["computeStyles"], | ||
effect: ({ state }) => { | ||
state.elements.popper.style.width = `${state.elements.reference.offsetWidth}px`; | ||
}, | ||
}, | ||
{ | ||
name: "offset", | ||
options: { | ||
offset: [0, 8], | ||
}, | ||
}, | ||
{ | ||
name: "preventOverflow", | ||
}, | ||
], | ||
}; | ||
function Icon({ item }) { | ||
return item.Icon ? ( | ||
<item.Icon | ||
sx={{ | ||
marginRight: 1, | ||
stroke: item.color, | ||
path: { fill: item.color }, | ||
}} | ||
/> | ||
) : null; | ||
} | ||
export default function Select({ items, onChange, value, label, ...rest }) { | ||
const { | ||
getItemProps, | ||
getLabelProps, | ||
getMenuProps, | ||
getToggleButtonProps, | ||
highlightedIndex, | ||
isOpen, | ||
selectedItem, | ||
} = useSelect({ | ||
items, | ||
onSelectedItemChange({ selectedItem: _selectedItem }) { | ||
onChange(_selectedItem); | ||
}, | ||
initialSelectedItem: value, | ||
}); | ||
|
||
const toggleButtonRef = useRef(); | ||
const menuRef = useRef(); | ||
const { | ||
styles: { popper: popperStyle }, | ||
attributes: { popper: popperAttributes }, | ||
} = usePopper(toggleButtonRef.current, menuRef.current, popperOptions); | ||
|
||
export function Option(props) { | ||
return <Box as="option" {...props} />; | ||
const border = isOpen ? "borderBottom" : "borderTop"; | ||
return ( | ||
<Box {...rest}> | ||
<Label | ||
{...getLabelProps({ | ||
variant: "forms.label.visuallyHidden", | ||
})} | ||
> | ||
{label} | ||
</Label> | ||
<Button | ||
{...getToggleButtonProps({ | ||
ref: toggleButtonRef, | ||
variant: "select", | ||
sx: { | ||
width: "100%", | ||
"::after": { | ||
[border]: "8px solid", | ||
[`${border}Color`]: "skeleton", | ||
borderLeft: "7px solid transparent", | ||
borderRight: "7px solid transparent", | ||
content: '""', | ||
position: "absolute", | ||
right: 2, | ||
top: "50%", | ||
transform: "translateY(-50%)", | ||
}, | ||
}, | ||
})} | ||
> | ||
<Icon item={selectedItem} /> | ||
{String(selectedItem)} | ||
</Button> | ||
<List | ||
{...getMenuProps({ | ||
ref: menuRef, | ||
style: popperStyle, | ||
variant: "select.list", | ||
sx: { | ||
boxShadow(theme) { | ||
return `0 6px 24px ${alpha("primary", 0.25)(theme)}`; | ||
}, | ||
}, | ||
...popperAttributes, | ||
})} | ||
> | ||
{isOpen && | ||
items.map((item, index) => ( | ||
<ListItem | ||
key={`${item}-${index}`} | ||
{...getItemProps({ | ||
variant: "select.list.item", | ||
sx: { | ||
backgroundColor: | ||
highlightedIndex === index && alpha("highlight", 0.06), | ||
...(selectedItem === item && { | ||
borderLeftColor: "highlight", | ||
borderLeftStyle: "solid", | ||
borderLeftWidth: 3, | ||
}), | ||
}, | ||
item, | ||
index, | ||
})} | ||
> | ||
<Icon item={item} /> | ||
{String(item)} | ||
</ListItem> | ||
))} | ||
</List> | ||
</Box> | ||
); | ||
} |
Oops, something went wrong.