Skip to content

Commit

Permalink
chore: implement design system selects
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras committed Oct 8, 2020
1 parent 4e35099 commit 4e08d7a
Show file tree
Hide file tree
Showing 16 changed files with 369 additions and 124 deletions.
3 changes: 2 additions & 1 deletion README.md
@@ -1,9 +1,10 @@
## (2020-10-07)
## (2020-10-08)

- chore: add code of conduct ([6859555](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/6859555))
- chore: add identicons ([45ddea1](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/45ddea1))
- chore: add issue templates ([6adcbee](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/6adcbee))
- chore: add more status icons ([3225e43](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/3225e43))
- chore: add share buttons to appeals ([4e35099](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/4e35099))
- chore: add social icons and fix font rendering ([b8e09b5](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/b8e09b5))
- chore: auto-detect Web3 call type ([15ae304](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/15ae304))
- chore: begin work on profile details page ([e4283ef](https://github.com/Proof-Of-Humanity/proof-of-humanity-web/commit/e4283ef))
Expand Down
35 changes: 16 additions & 19 deletions _pages/index/submission-filters.js
@@ -1,4 +1,4 @@
import { Card, Input, Option, Select, Text } from "@kleros/components";
import { Card, Input, Select, Text } from "@kleros/components";
import { Search } from "@kleros/icons";
import { useRouter } from "next/router";

Expand All @@ -10,9 +10,11 @@ export default function SubmissionFilters({ numberOfSubmissions }) {
<Card
sx={{ marginBottom: 2 }}
header={
<Text>
<Text as="span">{numberOfSubmissions}</Text> Profile
{Number(numberOfSubmissions) === 1 ? "" : "s"}
<Text sx={{ maxWidth: 150 }}>
{(numberOfSubmissions || numberOfSubmissions === 0) &&
`${numberOfSubmissions} Profile${
numberOfSubmissions === 1 ? "" : "s"
}`}
</Text>
}
headerSx={{ fontWeight: "bold", justifyContent: "flex-end" }}
Expand All @@ -34,26 +36,21 @@ export default function SubmissionFilters({ numberOfSubmissions }) {
}}
/>
<Select
sx={{ width: "205px" }}
value={
submissionStatusEnum.find(
(status) => status.kebabCase === router.query.status
).startCase
}
onChange={(event) => {
sx={{ width: "240px" }}
items={submissionStatusEnum.array}
onChange={({ kebabCase }) => {
const query = { ...router.query };
const status = submissionStatusEnum[event.target.value].kebabCase;
if (!status) delete query.status;
else query.status = status;
if (!kebabCase) delete query.status;
else query.status = kebabCase;
router.push({
query,
});
}}
>
{submissionStatusEnum.map((status) => (
<Option key={status.key}>{status.startCase}</Option>
))}
</Select>
value={submissionStatusEnum.array.find(
({ kebabCase }) => kebabCase === router.query.status
)}
label="Filter by status:"
/>
</Card>
);
}
Expand Up @@ -9,13 +9,15 @@ import {
NextLink,
Popup,
Text,
ethereumAddressRegExp,
useContract,
useWeb3,
zeroAddress,
} from "@kleros/components";
import { useEffect, useMemo, useState } from "react";
import { graphql, useFragment } from "relay-hooks";

import { challengeReasonEnum, ethereumAddressRegExp, zeroAddress } from "data";
import { challengeReasonEnum } from "data";

const challengeButtonFragments = {
contract: graphql`
Expand Down
Expand Up @@ -6,12 +6,11 @@ import {
Text,
useContract,
useWeb3,
zeroAddress,
} from "@kleros/components";
import { useMemo } from "react";
import { graphql, useFragment } from "relay-hooks";

import { zeroAddress } from "data";

const removeButtonFragments = {
contract: graphql`
fragment removeButtonContract on Contract {
Expand Down
6 changes: 3 additions & 3 deletions components/button.js
Expand Up @@ -32,9 +32,9 @@ const Button = forwardRef(
return `linear-gradient(90deg, ${primary} 0%, ${secondary} 100%)`;
},
position: "relative",
"&:focus": {
":focus": {
boxShadow({ colors: { text } }) {
return `0 0 2px ${text}`;
return `0 0 1px ${text}`;
},
},
...sx,
Expand All @@ -47,10 +47,10 @@ const Button = forwardRef(
<Text
ref={innerRef}
id={id && `${id}-text`}
variant={`buttons.${variant}`}
sx={{
alignItems: "center",
display: "flex",
justifyContent: "space-evenly",
minWidth: "100px",
}}
>
Expand Down
3 changes: 2 additions & 1 deletion components/index.js
Expand Up @@ -29,7 +29,7 @@ export { default as List, ListItem } from "./list";
export { default as Popup } from "./popup";
export { default as RelayProvider, useQuery } from "./relay-provider";
export { default as SVG } from "./svg";
export { default as Select, Option } from "./select";
export { default as Select } from "./select";
export { default as SocialIcons } from "./social-icons";
export { default as Text } from "./text";
export { default as Textarea } from "./textarea";
Expand All @@ -40,3 +40,4 @@ export { default as VotingHistory } from "./voting-history";
export { default as Web3Provider, useWeb3, useContract } from "./web3-provider";

export { NextLink, NextETHLink, createWrapConnection } from "./next-router";
export { zeroAddress, ethereumAddressRegExp, createEnum } from "./parsing";
7 changes: 4 additions & 3 deletions components/label.js
@@ -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;
14 changes: 8 additions & 6 deletions components/list.js
@@ -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";
51 changes: 51 additions & 0 deletions components/parsing.js
@@ -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;
};
144 changes: 139 additions & 5 deletions components/select.js
@@ -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>
);
}

0 comments on commit 4e08d7a

Please sign in to comment.