Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
fix: rewrite list
Browse files Browse the repository at this point in the history
  • Loading branch information
tatinacher committed May 5, 2021
1 parent 11d57da commit 1036c82
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 346 deletions.
2 changes: 1 addition & 1 deletion src/ui/atoms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { HeaderPanel } from './header-panel';
export { Heading } from './heading';
export { Input } from './input';
export { Label } from './label';
export { List } from './list';
export { ListItem, ListContainer } from './list';
export { Notification } from './notification';
export { Separator } from './separator';
export { Surface } from './surface';
Expand Down
243 changes: 78 additions & 165 deletions src/ui/atoms/list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,189 +1,102 @@
import * as React from 'react';
import styled, { StyledComponent } from 'styled-components';
import { Variant } from 'lib/types';
import { keyHandlerList, keyboardEventHandle } from 'lib';
interface List {
className?: string;
disabled?: boolean;
list: Array<{
left?: React.ReactNode;
right?: React.ReactNode;
text: React.ReactNode;
id: string;
disabled?: boolean;
onClick?: React.EventHandler<React.SyntheticEvent>;
}>;
}

const ListBase: React.FC<List & Variant> = ({
className,
list,
variant = 'default',
disabled = false,
}) => {
const tabIndex = disabled ? -1 : 0;
const itemListRef = React.useRef(null);

const onKeyDown = React.useCallback(
(event: React.KeyboardEvent) => {
const listNode = itemListRef.current;

if (!document || !listNode || event.key === 'Tab') {
return;
}

event.preventDefault();

const handlerList = keyHandlerList({
listNode,
});

keyboardEventHandle({
event,
keyHandler: handlerList,
});
},
[itemListRef],
);
return (
<ul
className={className}
data-disabled={disabled}
data-variant={variant}
onKeyDown={onKeyDown}
ref={itemListRef}
role="listbox"
tabIndex={tabIndex}
>
{list.map(({ left, right, text, id, onClick, disabled }) => (
<li data-disabled={disabled} data-type="list-item" key={id} onClick={onClick} tabIndex={-1}>
{left && <span data-icon="left">{left}</span>}
<span data-text="text">{text}</span>
{right && <span data-icon="right">{right}</span>}
</li>
))}
</ul>
);
};

export const List = styled(ListBase)`
--local-vertical: calc(1px * var(--woly-component-level) * var(--woly-main-level));
--local-horizontal: calc(
var(--woly-const-m) + (1px * var(--woly-main-level)) + var(--local-vertical)
);
--local-gap: var(--local-vertical);
--local-compensate: var(--woly-const-m);
--local-margin: var(--woly-border-width);
--local-color: var(--woly-canvas-text-default);
--local-background: var(--woly-shape-text-default);
--local-item-background: var(--woly-canvas-default);
--local-border: var(--woly-canvas-default);
box-sizing: border-box;
width: 100%;
outline: none;
padding: 0;
margin: 0;
border: var(--woly-border-width) solid var(--local-border);
list-style-type: none;
li[data-type='list-item'] {
display: flex;
align-items: center;

padding: var(--local-vertical) 0;
margin-bottom: var(--local-margin);
import { Box, Elements } from '../../elements/quarks';

font-size: var(--woly-font-size, 15px);
line-height: var(--woly-line-height, 24px);
color: var(--local-color);
background: var(--local-item-background);
cursor: pointer;
outline: none;
interface ElementsProps {
iconLeft?: React.ReactNode;
iconRight?: React.ReactNode;
text: string;
}

[data-text] {
display: flex;
flex: 1;
padding: 0 var(--local-horizontal);
}
interface ListItemProps {
as?: 'a' | 'li';
disabled?: boolean;
href?: string;
tabIndex?: number;
}

& > [data-text]:not(:only-child, :last-child) {
padding-right: 0;
}
const mapContainer = (properties: { columns: number } & Variant) => ({
'data-variant': properties.variant || 'secondary',
});

[data-icon] {
--local-icon-size: var(--woly-line-height);
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
const mapItem = (properties: ListItemProps & Variant) => ({
'data-variant': properties.variant || 'secondary',
'data-type': properties.as,
'data-disabled': properties.disabled,
});

width: var(--local-icon-size);
height: var(--local-icon-size);
export const ListContainer = styled.div.attrs(mapContainer)`
--local-gap: calc(var(--woly-border-width) * 2);
svg > path {
fill: var(--local-color);
}
}
display: grid;
grid-template-columns: 1fr;
gap: var(--local-gap);
background-color: var(--woly-canvas);
padding: 0;
margin: 0;
` as StyledComponent<'div', Record<string, unknown>, Variant>;

[data-icon='left'] {
padding: 0 0 0 calc(var(--local-horizontal) - var(--local-compensate));
}
/**
* Fix ListItemContainer after implementing box element
*/
const ListItemContainer = styled(Box).attrs(mapItem)`
--local-icon-color: var(--woly-canvas-text-default);
[data-icon='right'] {
padding: 0 calc(var(--local-horizontal) - var(--local-compensate)) 0 0;
}
cursor: pointer;
font-size: var(--woly-font-size);
line-height: var(--woly-line-height);
text-decoration: none;
color: var(--woly-canvas-text-default);
[data-icon='left'] ~ [data-text],
[data-text] ~ [data-icon='right'] {
padding-left: var(--local-gap);
}
list-style-type: none;
&:hover {
--local-item-background: var(--woly-canvas-disabled);
span {
svg > path {
fill: var(--local-icon-color);
}
&:focus {
box-shadow: 0 0 0 var(--woly-border-width) var(--woly-focus);
}
&:active {
--local-item-background: var(--woly-focus);
--local-color: var(--woly-shape-text-active);
}
&[data-disabled='true'] {
--local-color: var(--woly-canvas-text-disabled);
--local-item-background: var(--woly-canvas-disabled);
pointer-events: none;
}
[data-icon] {
--local-color: var(--woly-canvas-text-disabled);
}
}
&:hover {
background-color: var(--woly-canvas-disabled);
}
&:focus {
&[data-type='a']:focus-within,
&[data-type='li']:focus {
--local-icon-color: var(--woly-shape-text-active);
outline: none;
background-color: var(--woly-focus);
color: var(--woly-shape-text-active);
box-shadow: 0 0 0 var(--woly-border-width) var(--woly-focus);
}
&[data-disabled='true'] {
pointer-events: none;
li[data-type='list-item'] {
--local-color: var(--woly-canvas-text-disabled);
--local-item-background: var(--woly-canvas-disabled);
}
--local-icon-color: var(--woly-canvas-text-disabled);
[data-icon] {
--local-color: var(--woly-canvas-text-disabled);
}
color: var(--woly-canvas-text-disabled);
pointer-events: none;
}
` as StyledComponent<'ul', Record<string, unknown>, List & Variant>;
` as StyledComponent<'div', Record<string, unknown>, ListItemProps & Variant>;

export const ListItem: React.FC<ListItemProps & ElementsProps & Variant> = ({
as,
disabled = false,
href,
iconLeft,
iconRight,
tabIndex,
text,
variant = 'secondary',
}) => (
<ListItemContainer
as={as}
href={href}
disabled={disabled}
tabIndex={disabled ? -1 : tabIndex}
variant={variant}
>
<Elements text={text} iconLeft={iconLeft} iconRight={iconRight} variant={variant} />
</ListItemContainer>
);
Loading

0 comments on commit 1036c82

Please sign in to comment.