From 66f5b5ed7d2f57b812cd87da11a7b90f396860ef Mon Sep 17 00:00:00 2001 From: Tatiana Cherednichenko Date: Wed, 5 May 2021 18:31:29 +0300 Subject: [PATCH] fix: rewrite Chip on box-model --- src/lib/box-styles.tsx | 5 + src/ui/atoms/chip/index.tsx | 197 ++++++++---------------------------- src/ui/atoms/chip/usage.mdx | 162 +++++++++++++++++++---------- 3 files changed, 158 insertions(+), 206 deletions(-) diff --git a/src/lib/box-styles.tsx b/src/lib/box-styles.tsx index e19b9260..88bb209b 100644 --- a/src/lib/box-styles.tsx +++ b/src/lib/box-styles.tsx @@ -6,6 +6,11 @@ export const Global = styled.div` font-family: 'Helvetica Neue', sans-serif; } + button { + padding: 0; + margin: 0; + } + --palette-snow-1000: #000000; --palette-snow-500: #c0c0c0; --palette-snow-300: #e5e5e5; diff --git a/src/ui/atoms/chip/index.tsx b/src/ui/atoms/chip/index.tsx index e50868fa..b96df0c5 100644 --- a/src/ui/atoms/chip/index.tsx +++ b/src/ui/atoms/chip/index.tsx @@ -1,197 +1,90 @@ import * as React from 'react'; import styled, { StyledComponent } from 'styled-components'; import { Variant } from 'lib/types'; - -/** - * --woly-rounding — in pixels - * --woly-font-size - * --woly-line-height - * --woly-border-width - * - * --woly-background - * --woly-border - * --woly-color - * - * --woly-background-hover - * --woly-border-hover - * --woly-color-hover - * - * --woly-background-focus - * --woly-border-focus - * --woly-color-focus - * - * --woly-background-disabled - * --woly-border-disabled - * --woly-color-disabled - * - */ +import { box } from 'ui/elements/quarks'; interface ChipProps { - action?: React.ReactNode; children?: string; className?: string; disabled?: boolean; - icon?: React.ReactNode; - onActionClick?: (event: React.MouseEvent) => void; - onClick?: (event: React.MouseEvent) => void; + leftIcon?: React.ReactNode; + onClick?: React.EventHandler; + rightIcon?: React.ReactNode; } const ChipBase: React.FC = ({ - action, children, className, disabled, - icon, - onActionClick, + leftIcon, onClick, + rightIcon, variant = 'secondary', }) => { const chipRole = onClick ? 'button' : 'div'; - const chipTabIndex = onClick ? 1 : 0; + const chipTabIndex = onClick ? 0 : -1; + + const onKeyDown = React.useCallback( + (event) => { + if (event.key === 'Enter' && onClick) { + onClick(event); + } + }, + [onClick], + ); return ( -
-
- {icon &&
{icon}
} +
+ {leftIcon && ( +
+ {leftIcon} +
+ )} +
{children} - {action && ( - <> - -
- - )}
+ {rightIcon &&
{rightIcon}
}
); }; export const Chip = styled(ChipBase)` - --woly-vertical: calc(1px * var(--woly-component-level) * var(--woly-main-level)); - --woly-horizontal: calc( - var(--woly-const-m) + (1px * var(--woly-main-level)) + var(--woly-vertical) - ); - --woly-line-height: 24px; - - position: relative; + ${box} + --local-background: var(--woly-shape-default); + --local-icon-size: var(--woly-line-height); + --local-color: var(--woly-shape-text-default); box-sizing: border-box; - display: flex; align-items: center; + background-color: var(--local-background); + color: var(--local-color); + border-radius: var(--woly-rounding); + font-size: var(--woly-font-size); + outline: none; - background-color: var(--woly-background, #b0a3f4); - color: var(--woly-color, #ffffff); - - border-radius: var(--woly-rounding, 3px); - - [role] { - width: 100%; - - display: flex; - align-items: center; - justify-content: center; - - font-size: var(--woly-font-size, 12px); - line-height: var(--woly-line-height, 20px); - - border-radius: var(--woly-rounding, 3px); - - padding: 0 var(--woly-horizontal, 6px); - + [data-text] { outline: none; + line-height: var(--woly-line-height); } - [role='button']:active { - color: var(--woly-color-focus, #ffffff); - background-color: var(--woly-background-focus, #9381f1); - border-color: var(--woly-border-focus, transparent); - } - - [role='button']:focus { - box-shadow: 0 0 0 var(--woly-border-width) var(--woly-border-focus, #9381f1); + &[role='button']:focus-within { + --local-background: var(--woly-focus); + box-shadow: 0 0 0 var(--woly-border-width) var(--woly-shape-default); } - [role='button']:hover { - color: var(--woly-color-hover, #ffffff); - background-color: var(--woly-background-hover, #9381f1); - opacity: 0.5; - border-color: var(--woly-border-hover, transparent); - outline: none; + &[role='button']:hover { + --local-background: var(--woly-shape-hover); } &[data-disabled='true'] { - color: var(--woly-color-disabled, #c0c0c0); - background: var(--woly-background-disabled, #f5f5f5); - border-color: var(--woly-background-disabled, transparent); - pointer-events: none; + --local-background: var(--woly-shape-disabled); + --local-text: var(--woly-shape-text-disabled); - [data-icon] { - svg > path { - fill: var(--woly-color, #c0c0c0); - } - } + pointer-events: none; } - [data-icon], - [data-type='stub'] { + [data-icon] { + --woly-component-level: 0; display: flex; - align-items: center; - justify-content: center; - - width: var(--woly-line-height, 24px); - height: var(--woly-line-height, 24px); - - background: var(--woly-background-disabled, transparent); - - border-color: var(--woly-border, transparent); - border-style: solid; - border-width: var(--woly-border-width); - border-radius: var(--woly-rounding, 3px); - - outline: none; - - svg > path { - fill: var(--woly-color, #ffffff); - } - } - - [data-type='stub'] { - visibility: hidden; - position: static; - flex-shrink: 0; - } - - [data-icon='right'] { - position: absolute; - right: 0; - z-index: 1; - top: 50%; - transform: translateY(-50%); - - &:hover { - background-color: var(--woly-background-hover, #9381f1); - opacity: 0.5; - } - - &:active { - background-color: var(--woly-background-hover, #9381f1); - } - - &:focus { - box-shadow: 0 0 0 var(--woly-border-width) var(--woly-border-focus, #9381f1); - } } ` as StyledComponent<'div', Record, ChipProps & Variant>; diff --git a/src/ui/atoms/chip/usage.mdx b/src/ui/atoms/chip/usage.mdx index ebd60fa0..3d28e135 100644 --- a/src/ui/atoms/chip/usage.mdx +++ b/src/ui/atoms/chip/usage.mdx @@ -6,7 +6,8 @@ package: 'woly' import { Chip } from './index'; import { CloseIcon, PlusIcon } from 'icons'; -import { Playground } from 'box-styles' +import { ButtonIcon } from 'ui' +import { block, Playground } from 'box-styles' `Chip` is used for categorizing or markup. Chips allow users to enter information, make selections, filter content, or trigger actions. @@ -27,7 +28,9 @@ As a standalone component, the most common use will be in some form of input, so ### Example - Simple Chip + + Simple Chip + ### Clickable @@ -39,25 +42,55 @@ In case when chip is clickable, it defined change appearance on focus, hover, an If chip consists another clickable component (eg button), this property defined will display a component which changes appearance on hover. - console.info('click')}> - Cklicked Chip - - } - onActionClick={() => console.info('ActionIcon clicked')} - > - Cklicked Icon - - console.info('click')} - action={} - onActionClick={() => console.info('ActionIcon clicked')} - disabled - > - Disabled Chip - + + console.info('click')} + rightIcon={ + } + onClick={() => console.info('CloseIcon clicked')} + variant="primary" + filled + /> + } + > + Clicked Chip + + + + console.info('click')} + variant="primary" + rightIcon={ + } + onClick={() => console.info('CloseIcon clicked')} + variant="primary" + filled + /> + } + > + Clicked Icon + + + + } + onClick={() => console.info('CloseIcon clicked')} + variant="primary" + filled + disabled + /> + } + > + Disabled Chip + + ### Icons/Buttons @@ -67,31 +100,51 @@ Chip can be used with icon on the left side or button on the right side. Even chip can be used with both options. - }> - Chip with Icon - - } onClick={() => console.info('click')}> - Cklicked Chip - - } - onClick={() => console.info('click')} - action={} - onActionClick={() => console.info('ActionIcon clicked')} - > - Cklicked Icon - - } - onClick={() => console.info('click')} - action={} - onActionClick={() => console.info('ActionIcon clicked')} - disabled - > - Disabled Chip - + + }> + Chip with Icon + + + + } onClick={() => console.info('click')}> + Clicked Chip + + + + } + onClick={() => console.info('click')} + rightIcon={ + } + onClick={(event) => console.info('CloseIcon clicked')} + variant="primary" + filled + /> + } + > + Clicked Icon + + + + } + disabled + rightIcon={ + } + onClick={(event) => console.info('CloseIcon clicked')} + variant="primary" + filled + disabled + /> + } + > + Disabled Chip + + ### Kinds @@ -102,11 +155,12 @@ Even chip can be used with both options. ### Props -| Name | Type | Default | Description | -| --------------- | ------------------------------------- | ------------- | -------------------------------------------------- | -| `children` | `string` | | Text inside chip | -| `action` | `React.ReactNode` | `null` | Icon to show on the right side of the text | -| `onActionClick` | `React.MouseEvent` | `null` | Callback when chip is clicked | -| `onClick` | `React.MouseEvent` | `null` | Callback when chip is clicked | -| `variant` | `string` | `'secondary'` | Variant prop to style Chip component | -| `...` | `HTMLButtonElement` | `{}` | Other props are inherited from `HTMLButtonElement` | +| Name | Type | Default | Description | +| ----------- | ---------------------------------- | ------------- | -------------------------------------------------- | +| `children` | `string` | | Text inside chip | +| `disabled` | `boolean` | | Attribute to disable chip | +| `leftIcon` | `React.ReactNode` | `null` | Icon to show on the left side of the text | +| `onClick` | `React.MouseEvent` | `null` | Callback when chip is clicked | +| `rightIcon` | `React.ReactNode` | `null` | Icon to show on the right side of the text | +| `variant` | `string` | `'secondary'` | Variant prop to style Chip component | +| `...` | `HTMLButtonElement` | `{}` | Other props are inherited from `HTMLButtonElement` |