generated from 8iq/nodejs-hackathon-boilerplate-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui): DOMA-8920 added IconButton (#4667)
* feat(ui): DOMA-8920 added IconButton * feat(ui): DOMA-8920 added pressed style * refactor(ui): DOMA-8920 some refactor * fix(ui): DOMA-8920 try fix import * fix(ui): DOMA-8920 try fix import * fix(ui): DOMA-8920 try fix import * refactor(ui): DOMA-8920 moved IconButton to Button.Icon * fix(ui): DOMA-8920 removed unused files * feat(ui): DOMA-8920 remove prop focus * refactor(condo): DOMA-8920 refactored after review * refactor(ui): DOMA-8920 refactored after review. Removed "pressed" prop
- Loading branch information
Showing
9 changed files
with
234 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { | ||
Button as DefaultButton, | ||
ButtonProps as DefaultButtonProps, | ||
} from 'antd' | ||
import classNames from 'classnames' | ||
import React, { useCallback } from 'react' | ||
|
||
import { sendAnalyticsClickEvent, extractChildrenContent } from '../../_utils/analytics' | ||
import { BUTTON_CLASS_PREFIX } from '../button' | ||
|
||
const ICON_BUTTON_CLASS_PREFIX = 'condo-icon-btn' | ||
|
||
type CondoIconButtonProps = { | ||
size?: 'small' | 'medium' | ||
} | ||
|
||
export type IconButtonProps = Omit<DefaultButtonProps, 'shape' | 'size' | 'style' | 'ghost' | 'type' | 'prefix' | 'prefixCls' | 'icon' | 'danger' | 'block'> | ||
& CondoIconButtonProps | ||
|
||
const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>> = React.forwardRef((props, ref) => { | ||
const { className, children, onClick, id, size, ...rest } = props | ||
const mergedSize = size || 'medium' | ||
const ariaLabel = rest['aria-label'] | ||
const classes = classNames( | ||
{ | ||
[BUTTON_CLASS_PREFIX]: true, | ||
[`${ICON_BUTTON_CLASS_PREFIX}-${mergedSize}`]: mergedSize, | ||
}, | ||
className, | ||
) | ||
|
||
const wrappedContent = children | ||
? <span className={`${ICON_BUTTON_CLASS_PREFIX}-content`}>{children}</span> | ||
: null | ||
|
||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement> & React.MouseEvent<HTMLAnchorElement>) => { | ||
const stringContent = extractChildrenContent(children) || ariaLabel | ||
if (stringContent || id) { | ||
sendAnalyticsClickEvent('IconButton', { value: stringContent, id }) | ||
} | ||
|
||
if (onClick) { | ||
onClick(event) | ||
} | ||
}, [ariaLabel, children, id, onClick]) | ||
|
||
return ( | ||
<DefaultButton | ||
{...rest} | ||
id={id} | ||
icon={wrappedContent} | ||
prefixCls={ICON_BUTTON_CLASS_PREFIX} | ||
className={classes} | ||
ref={ref} | ||
type='default' | ||
onClick={handleClick} | ||
/> | ||
) | ||
}) | ||
|
||
IconButton.displayName = 'IconButton' | ||
|
||
export { | ||
IconButton, | ||
} |
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,111 @@ | ||
@import (reference) "@open-condo/ui/src/tokens/variables.less"; | ||
@import (reference) "@open-condo/ui/src/components/style/mixins/button"; | ||
@import (reference) "@open-condo/ui/src/components/style/mixins/transition"; | ||
|
||
@condo-icon-button-focus-outline-width: @condo-global-border-width-default * 4; | ||
@condo-icon-button-focus-visible-outline-width: @condo-global-border-width-default * 2; | ||
@condo-icon-button-focus-outline-border-radius-small: @condo-global-border-radius-medium; | ||
@condo-icon-button-focus-outline-border-radius-medium: @condo-global-border-radius-large; | ||
@condo-icon-button-border-radius-small: @condo-global-border-radius-small; | ||
@condo-icon-button-border-radius-medium: @condo-global-border-radius-medium; | ||
@condo-icon-button-padding-small: 2px; | ||
@condo-icon-button-padding-medium: 8px; | ||
|
||
.condo-icon-btn { | ||
width: auto; | ||
min-width: inherit; | ||
height: auto; | ||
padding: @condo-icon-button-padding-medium; | ||
background-color: transparent; | ||
border: none; | ||
border-radius: @condo-icon-button-border-radius-medium; | ||
.condo-transition(background); | ||
|
||
span { | ||
position: relative; | ||
z-index: 1; | ||
} | ||
|
||
// After layer is used to show gradient outline on tab-focusing | ||
&:focus-visible::after { | ||
box-sizing: border-box; | ||
background: @condo-global-color-brand-gradient-5 border-box; | ||
border: @condo-icon-button-focus-visible-outline-width solid transparent; | ||
opacity: 1; | ||
mask: linear-gradient(#111 0 0) padding-box, linear-gradient(#fff 0 0); | ||
-webkit-mask-composite: xor; | ||
mask-composite: exclude; | ||
} | ||
|
||
&::before { | ||
.condo-btn-layer(0px); | ||
|
||
background: @condo-global-color-brand-gradient-1; | ||
opacity: 0; | ||
.condo-transition(opacity); | ||
} | ||
|
||
.condo-icon-btn-content { | ||
display: inline-flex; | ||
color: @condo-global-color-black; | ||
.condo-transition(color); | ||
|
||
svg { | ||
color: @condo-global-color-black; | ||
fill: currentcolor; | ||
.condo-transition(color); | ||
} | ||
} | ||
|
||
&:focus::after { | ||
.condo-btn-layer(-@condo-icon-button-focus-outline-width); | ||
|
||
border-radius: @condo-icon-button-focus-outline-border-radius-medium; | ||
} | ||
|
||
&:disabled { | ||
background-color: transparent; | ||
|
||
.condo-icon-btn-content { | ||
opacity: @condo-global-opacity-disabled; | ||
} | ||
|
||
&:hover { | ||
background-color: transparent; | ||
} | ||
} | ||
|
||
&:not(:disabled):hover { | ||
&::before { | ||
opacity: 1; | ||
} | ||
|
||
.condo-icon-btn-content { | ||
color: @condo-global-color-green-5; | ||
|
||
svg { | ||
color: @condo-global-color-green-5; | ||
} | ||
} | ||
} | ||
|
||
&:not(:disabled):active, | ||
&:not(:disabled):active:hover { | ||
.condo-icon-btn-content { | ||
color: @condo-global-color-green-7; | ||
|
||
svg { | ||
color: @condo-global-color-green-7; | ||
} | ||
} | ||
} | ||
|
||
&.condo-icon-btn-small { | ||
padding: @condo-icon-button-padding-small; | ||
border-radius: @condo-icon-button-border-radius-small; | ||
|
||
&:focus::after { | ||
border-radius: @condo-icon-button-focus-outline-border-radius-small; | ||
} | ||
} | ||
} |
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,17 @@ | ||
import { Button } from './button' | ||
import './style.less' | ||
import './icon/style.less' | ||
|
||
import { Button as InternalButton } from './button' | ||
import { IconButton } from './icon/iconButton' | ||
|
||
export type { ButtonProps } from './button' | ||
export type { IconButtonProps } from './icon/iconButton' | ||
|
||
type CombinedButtonType = typeof InternalButton & { | ||
Icon: typeof IconButton | ||
} | ||
|
||
const Button = InternalButton as CombinedButtonType | ||
Button.Icon = IconButton | ||
|
||
export { Button } |
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
File renamed without changes.
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
File renamed without changes.
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,42 @@ | ||
import { ComponentStory, ComponentMeta } from '@storybook/react' | ||
import React from 'react' | ||
|
||
import * as condoIcons from '@open-condo/icons' | ||
import { Button as Component } from '@open-condo/ui/src' | ||
|
||
const { Trash } = condoIcons | ||
|
||
const icons = Object.assign({}, ...Object.entries(condoIcons).map(([key, Icon]) => ({ | ||
[`${key}-small`]: <Icon size='small'/>, | ||
[`${key}-medium`]: <Icon size='medium'/>, | ||
[`${key}-large`]: <Icon size='large'/>, | ||
}))) | ||
|
||
export default { | ||
title: 'Components/Button', | ||
component: Component.Icon, | ||
args: { | ||
children: <Trash size='medium' />, | ||
disabled: false, | ||
size: 'medium', | ||
}, | ||
argTypes: { | ||
size: { control: 'select', options: ['small', 'medium'] }, | ||
children: { | ||
options: Object.keys(icons), | ||
mapping: icons, | ||
control: { | ||
type: 'select', | ||
}, | ||
}, | ||
disabled: { control: 'boolean', default: false }, | ||
onClick: { control: false }, | ||
href: { control: false }, | ||
target: { control: false }, | ||
htmlType: { defaultValue: 'button' }, | ||
}, | ||
} as ComponentMeta<typeof Component.Icon> | ||
|
||
const Template: ComponentStory<typeof Component.Icon> = (props) => <Component.Icon {...props}/> | ||
|
||
export const IconButton = Template.bind({}) |