Skip to content

Commit

Permalink
fix(typescript): adds TypeScript types to ChatButto & Skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
2nikhiltom committed Sep 3, 2024
1 parent 03051cf commit 156a191
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 51 deletions.
19 changes: 16 additions & 3 deletions packages/react/src/components/ChatButton/ChatButton.Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2022
* Copyright IBM Corp. 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -9,8 +9,21 @@ import PropTypes from 'prop-types';
import React from 'react';
import cx from 'classnames';
import { usePrefix } from '../../internal/usePrefix';

const ChatButtonSkeleton = ({ className, size, ...rest }) => {
export interface ChatButtonSkeletonProps {
/**
* Specify an optional className to add.
*/
className?: string;
/**
* Specify the size of the `ChatButtonSkeleton`, from the following list of sizes:
*/
size?: 'sm' | 'md' | 'lg';
}
const ChatButtonSkeleton = ({
className,
size,
...rest
}: ChatButtonSkeletonProps) => {
const prefix = usePrefix();
const skeletonClasses = cx(
className,
Expand Down
140 changes: 94 additions & 46 deletions packages/react/src/components/ChatButton/ChatButton.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,108 @@
/**
* Copyright IBM Corp. 2022
* Copyright IBM Corp. 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import React, { type ComponentType, type FunctionComponent } from 'react';
import PropTypes from 'prop-types';
import React from 'react';
import classnames from 'classnames';
import Button from '../Button';
import { usePrefix } from '../../internal/usePrefix';

const ChatButton = React.forwardRef(function ChatButton(
{
className,
children,
disabled,
isQuickAction,
isSelected,
kind,
renderIcon,
size,
...other
},
ref
) {
const prefix = usePrefix();
const classNames = classnames(className, {
[`${prefix}--chat-btn`]: true,
[`${prefix}--chat-btn--with-icon`]: renderIcon,
[`${prefix}--chat-btn--quick-action`]: isQuickAction,
[`${prefix}--chat-btn--quick-action--selected`]: isSelected,
});

const allowedSizes = ['sm', 'md', 'lg'];

if (isQuickAction) {
kind = 'ghost';
size = 'sm';
} else {
// Do not allow size larger than `lg`
size = allowedSizes.includes(size) ? size : 'lg';
}
export type ChatButtonKind =
| 'primary'
| 'secondary'
| 'danger'
| 'ghost'
| 'tertiary';
export type ChatButtonSize = 'sm' | 'md' | 'lg';

return (
<Button
disabled={disabled}
className={classNames}
kind={kind}
ref={ref}
size={size}
renderIcon={renderIcon}
{...other}>
{children}
</Button>
);
});
export interface ChatButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Provide the contents of your Select
*/
children?: React.ReactNode;
/**
* Specify an optional className to be applied to the node containing the label and the select box
*/
className?: string;
/**
* Specify whether the `ChatButton` should be disabled
*/
disabled?: boolean;
/**
* Specify whether the `ChatButton` should be rendered as a quick action button
*/
isQuickAction?: boolean;
/**
* Specify whether the quick action `ChatButton` should be rendered as selected. This disables the input
*/
isSelected?: boolean;
/**
* Specify the kind of `ChatButton` you want to create
*/
kind?: ChatButtonKind;
/**
* Optional prop to specify an icon to be rendered.
* Can be a React component class
*/
renderIcon?: ComponentType | FunctionComponent;
/**
* Specify the size of the `ChatButton`, from the following list of sizes:
*/
size?: ChatButtonSize;
}

const ChatButton = React.forwardRef<HTMLButtonElement, ChatButtonProps>(
function ChatButton(
{
className,
children,
disabled,
isQuickAction,
isSelected,
kind,
renderIcon,
size,
...other
}: ChatButtonProps,
ref
) {
const prefix = usePrefix();
const classNames = classnames(className, {
[`${prefix}--chat-btn`]: true,
[`${prefix}--chat-btn--with-icon`]: renderIcon,
[`${prefix}--chat-btn--quick-action`]: isQuickAction,
[`${prefix}--chat-btn--quick-action--selected`]: isSelected,
});

const allowedSizes: ChatButtonSize[] = ['sm', 'md', 'lg'];

if (isQuickAction) {
kind = 'ghost';
size = 'sm';
} else {
// Do not allow size larger than `lg`
size = allowedSizes.includes(size as ChatButtonSize) ? size : 'lg';
}

return (
<Button
disabled={disabled}
className={classNames}
kind={kind}
ref={ref}
size={size as ChatButtonSize}
renderIcon={renderIcon}
{...other}>
{children}
</Button>
);
}
);

ChatButton.propTypes = {
/**
Expand Down Expand Up @@ -98,6 +145,7 @@ ChatButton.propTypes = {
* Optional prop to specify an icon to be rendered.
* Can be a React component class
*/
// @ts-expect-error: PropTypes are not expressive enough to cover this case
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

/**
Expand Down
6 changes: 4 additions & 2 deletions packages/react/src/components/ChatButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/**
* Copyright IBM Corp. 2022
* Copyright IBM Corp. 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import ChatButton from './ChatButton';
import { type ChatButtonProps } from './ChatButton';
import { type ChatButtonSkeletonProps } from './ChatButton.Skeleton';

export default ChatButton;
export { ChatButton };
export { ChatButton, type ChatButtonProps, type ChatButtonSkeletonProps };
export { default as ChatButtonSkeleton } from './ChatButton.Skeleton';

0 comments on commit 156a191

Please sign in to comment.