Skip to content

Commit

Permalink
Merge pull request #139 from 8845musign/receive-icon-key
Browse files Browse the repository at this point in the history
Allow icon prop to be specified by name
  • Loading branch information
takanorip authored Nov 7, 2024
2 parents c6ea851 + 68ff171 commit 3544a30
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 16 deletions.
8 changes: 4 additions & 4 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { clsx } from 'clsx';
import { type CSSProperties, forwardRef } from 'react';
import styles from './Button.module.css';
import { VariantIcon } from './VariantIcon';
import { useIcon } from './useIcon';
import { marginVariables } from '../../utils/style';
import type { ButtonProps } from './ButtonTypes';

Expand Down Expand Up @@ -34,9 +34,9 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
},
ref,
) => {
const icon = _icon === 'default' ? <VariantIcon variant={variant} /> : _icon;
const fixedIcon = _fixedIcon === 'default' ? <VariantIcon variant={variant} /> : _fixedIcon;
const suffixIcon = _suffixIcon === 'default' ? <VariantIcon variant={variant} /> : _suffixIcon;
const icon = useIcon(_icon, variant);
const fixedIcon = useIcon(_fixedIcon, variant);
const suffixIcon = useIcon(_suffixIcon, variant);
const cls = clsx({
[styles.button]: true,
[styles[variant]]: true,
Expand Down
7 changes: 4 additions & 3 deletions src/components/Button/ButtonTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CustomDataAttributeProps } from '../../types/attributes';
import { IconName } from '../../types/icon';
import type { MarginProps } from '../../types/style';
import type { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactElement, ReactNode } from 'react';

Expand Down Expand Up @@ -34,15 +35,15 @@ export type BaseProps = {
/**
* アイコン
*/
icon?: 'default' | ReactNode;
icon?: 'default' | ReactElement | IconName;
/**
* Fixedアイコン
*/
fixedIcon?: 'default' | ReactNode;
fixedIcon?: 'default' | ReactElement | IconName;
/**
* 後方配置のアイコン
*/
suffixIcon?: 'default' | ReactNode;
suffixIcon?: 'default' | ReactElement | IconName;
/**
* ラベルの折り返しを指定
*/
Expand Down
8 changes: 4 additions & 4 deletions src/components/Button/LinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import clsx from 'clsx';
import { cloneElement, CSSProperties, forwardRef } from 'react';
import styles from './Button.module.css';
import { VariantIcon } from './VariantIcon';
import { useIcon } from './useIcon';
import { marginVariables } from '../../utils/style';
import type { LinkButtonProps } from './ButtonTypes';
import type { ReactNode } from 'react';
Expand Down Expand Up @@ -31,9 +31,9 @@ export const LinkButton = forwardRef<HTMLAnchorElement, LinkButtonProps>(
},
forwardedRef,
) => {
const icon = _icon === 'default' ? <VariantIcon variant={variant} /> : _icon;
const fixedIcon = _fixedIcon === 'default' ? <VariantIcon variant={variant} /> : _fixedIcon;
const suffixIcon = _suffixIcon === 'default' ? <VariantIcon variant={variant} /> : _suffixIcon;
const icon = useIcon(_icon, variant);
const fixedIcon = useIcon(_fixedIcon, variant);
const suffixIcon = useIcon(_suffixIcon, variant);
const cls = clsx({
[styles.button]: true,
[styles[variant]]: true,
Expand Down
16 changes: 16 additions & 0 deletions src/components/Button/useIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useMemo } from 'react';
import { VariantIcon } from './VariantIcon';
import { Icon } from '../Icon/Icon';
import type { ButtonProps } from './ButtonTypes';

export function useIcon(icon: ButtonProps['icon'], variant: ButtonProps['variant']) {
return useMemo(() => {
if (icon === 'default') {
return <VariantIcon variant={variant} />;
} else if (typeof icon === 'string') {
return <Icon icon={icon}></Icon>;
} else {
return icon;
}
}, [icon, variant]);
}
5 changes: 2 additions & 3 deletions src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as Icons from '@ubie/ubie-icons';
import styles from './Icon.module.css';
import { CustomDataAttributeProps } from '../../types/attributes';
import { IconName } from '../../types/icon';
import { TextColor } from '../../types/style';
import { colorVariable } from '../../utils/style';
import type { CSSProperties, FC } from 'react';

type Icon = keyof typeof Icons;

type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';

const toIconSizeEmValue = (size: IconSize): string => {
Expand Down Expand Up @@ -38,7 +37,7 @@ type Props = {
/**
* アイコンの種類
*/
icon: Icon;
icon: IconName;
/**
* 色。指定しない場合はinheritとなり、親要素のcolorプロパティを継承します
*/
Expand Down
12 changes: 10 additions & 2 deletions src/components/LinkCard/LinkCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import clsx from 'clsx';
import { cloneElement, forwardRef, isValidElement } from 'react';
import styles from './LinkCard.module.css';
import { CustomDataAttributeProps } from '../../types/attributes';
import { IconName } from '../../types/icon';
import { Icon } from '../Icon/Icon';
import type { ComponentType, ReactElement, ReactNode } from 'react';

type IconProp = ComponentType | ReactElement | IconName;

type Props = {
/**
* 遷移先URL
Expand Down Expand Up @@ -37,19 +41,23 @@ type Props = {
/**
* アイコン
*/
icon?: ComponentType | ReactElement;
icon?: IconProp;
} & CustomDataAttributeProps;

// ref https://github.com/microsoft/TypeScript/issues/53178
const _isValidElement = (el: ComponentType | ReactElement): el is ReactElement => {
return isValidElement(el);
};

const renderPropIcon = (icon: ComponentType | ReactElement) => {
const renderPropIcon = (icon: IconProp) => {
if (icon == null) {
return null;
}

if (typeof icon === 'string') {
return <Icon icon={icon} />;
}

if (_isValidElement(icon)) {
return icon;
}
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ export { Text } from './components/Text/Text';
export { TextArea } from './components/TextArea/TextArea';
export { Stack } from './components/Stack/Stack';
export { Toggle } from './components/Toggle/Toggle';

export type { IconName } from './types/icon';
34 changes: 34 additions & 0 deletions src/stories/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ export const WithIcon: Story = {
</div>
</dd>
</Stack>

<Stack spacing="lg" as="dl">
<dt style={{ fontWeight: 'bold' }}>Name specification</dt>
<dd style={{ margin: 0 }}>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', gap: '32px' }}>
<Button icon="BlankLinkIcon" {...defaultArgs}>
Icon
</Button>
<Button suffixIcon="BlankLinkIcon" {...defaultArgs}>
Suffix Icon
</Button>
<Button fixedIcon="BlankLinkIcon" {...defaultArgs}>
Fixed Icon
</Button>
</div>
</dd>
</Stack>

<Stack spacing="lg" as="dl">
<dt style={{ fontWeight: 'bold' }}>Auth Icon</dt>
<dd style={{ margin: 0 }}>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', gap: '32px' }}>
<Button variant="authGoogle" icon="default" {...defaultArgs}>
Icon
</Button>
<Button variant="authGoogle" suffixIcon="default" {...defaultArgs}>
Suffix Icon
</Button>
<Button variant="authGoogle" fixedIcon="default" {...defaultArgs}>
Fixed Icon
</Button>
</div>
</dd>
</Stack>
</Stack>
),
args: defaultArgs,
Expand Down
34 changes: 34 additions & 0 deletions src/stories/LinkButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,40 @@ export const WithIcon: Story = {
</div>
</dd>
</Stack>

<Stack spacing="lg" as="dl">
<dt style={{ fontWeight: 'bold' }}>Name specification</dt>
<dd style={{ margin: 0 }}>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', gap: '32px' }}>
<LinkButton icon="BlankLinkIcon" {...defaultArgs}>
Icon
</LinkButton>
<LinkButton suffixIcon="BlankLinkIcon" {...defaultArgs}>
Suffix Icon
</LinkButton>
<LinkButton fixedIcon="BlankLinkIcon" {...defaultArgs}>
Fixed Icon
</LinkButton>
</div>
</dd>
</Stack>

<Stack spacing="lg" as="dl">
<dt style={{ fontWeight: 'bold' }}>Auth Icon</dt>
<dd style={{ margin: 0 }}>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', gap: '32px' }}>
<LinkButton variant="authGoogle" icon="default" {...defaultArgs}>
Icon
</LinkButton>
<LinkButton variant="authGoogle" suffixIcon="default" {...defaultArgs}>
Suffix Icon
</LinkButton>
<LinkButton variant="authGoogle" fixedIcon="default" {...defaultArgs}>
Fixed Icon
</LinkButton>
</div>
</dd>
</Stack>
</Stack>
),
};
Expand Down
11 changes: 11 additions & 0 deletions src/stories/LinkCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,14 @@ export const CustomDataAttribute: Story = {
'data-test-id': 'link-card-custom-attribute',
},
};

export const VariousWaysToSpecifyIcon: Story = {
render: (args) => (
<Stack spacing="md">
<LinkCard {...args} href="https://vitals.ubie.life/" icon="HospitalIcon" title="Icon Name" />
<LinkCard {...args} href="https://vitals.ubie.life/" icon={<HospitalIcon />} title="RectElement" />
<LinkCard {...args} href="https://vitals.ubie.life/" icon={HospitalIcon} title="ComponentType" />
</Stack>
),
args: defaultArgs,
};
3 changes: 3 additions & 0 deletions src/types/icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as Icons from '@ubie/ubie-icons';

export type IconName = keyof typeof Icons;

0 comments on commit 3544a30

Please sign in to comment.