From 0484f2103732ffd8673d98834d8d43840212c9bd Mon Sep 17 00:00:00 2001 From: James Kiger Date: Wed, 15 Jan 2025 07:20:54 -0500 Subject: [PATCH 1/2] Cleanup and squash commits after rebasing to main --- jsapp/js/components/common/ActionIcon.tsx | 30 +++++ .../components/common/actionIcon.stories.tsx | 116 ++++++++++++++++++ jsapp/js/theme/kobo/ActionIcon.module.css | 7 ++ jsapp/js/theme/kobo/ActionIcon.ts | 38 ++++++ .../kobo/{menu.module.css => Menu.module.css} | 0 jsapp/js/theme/kobo/{menu.ts => Menu.ts} | 2 +- jsapp/js/theme/kobo/index.ts | 4 +- 7 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 jsapp/js/components/common/ActionIcon.tsx create mode 100644 jsapp/js/components/common/actionIcon.stories.tsx create mode 100644 jsapp/js/theme/kobo/ActionIcon.module.css create mode 100644 jsapp/js/theme/kobo/ActionIcon.ts rename jsapp/js/theme/kobo/{menu.module.css => Menu.module.css} (100%) rename jsapp/js/theme/kobo/{menu.ts => Menu.ts} (91%) diff --git a/jsapp/js/components/common/ActionIcon.tsx b/jsapp/js/components/common/ActionIcon.tsx new file mode 100644 index 0000000000..8964fd6c6c --- /dev/null +++ b/jsapp/js/components/common/ActionIcon.tsx @@ -0,0 +1,30 @@ +import { + ActionIcon as ActionIconMantine, + createPolymorphicComponent, +} from '@mantine/core'; +import type {ActionIconProps as ActionIconPropsMantine} from '@mantine/core/lib/components'; +import Icon, {IconSize} from './icon'; +import type {IconName} from 'jsapp/fonts/k-icons'; +import {forwardRef} from 'react'; + +export interface ActionIconProps extends Omit { + iconName: IconName; + size: 'sm' | 'md' | 'lg'; +} + +const ActionIcon = forwardRef( + ({iconName, ...props}, ref) => { + // Currently, our icon sizes only use a single letter instead of + // Mantine's 'sm', 'md', etc. So here we grab the first letter. + const iconSize = props.size[0] as IconSize; + return ( + + + + ); + } +); + +export default createPolymorphicComponent<'button', ActionIconProps>( + ActionIcon +); diff --git a/jsapp/js/components/common/actionIcon.stories.tsx b/jsapp/js/components/common/actionIcon.stories.tsx new file mode 100644 index 0000000000..b9bd117d85 --- /dev/null +++ b/jsapp/js/components/common/actionIcon.stories.tsx @@ -0,0 +1,116 @@ +import React from 'react'; +import type {Meta, StoryObj} from '@storybook/react'; +import {IconNames} from 'jsapp/fonts/k-icons'; +import ActionIcon, {type ActionIconProps} from './ActionIcon'; + +const actionIconVariants: Array = [ + 'filled', + 'light', + + //// Custom: + 'danger', + 'danger-secondary', + 'transparent', +]; + +const actionIconSizes: Array = [ + 'sm', + 'md', + 'lg', +]; + +export default { + title: 'common/Action Icon', + component: ActionIcon, + argTypes: { + variant: { + description: 'Variant of action icon', + options: actionIconVariants, + control: 'select', + }, + size: { + description: 'Size of action icon', + options: actionIconSizes, + control: 'radio', + }, + iconName: { + description: 'Icon', + options: Object.keys(IconNames), + control: {type: 'select'}, + }, + disabled: {control: 'boolean'}, + loading: {control: 'boolean'}, + }, +} as Meta; + +type Story = StoryObj; + +export const Filled: Story = { + args: { + variant: 'filled', + size: 'md', + iconName: 'edit', + }, +}; + +export const Light: Story = { + args: { + variant: 'light', + size: 'md', + iconName: 'edit', + }, +}; + +export const Transparent: Story = { + args: { + variant: 'transparent', + size: 'md', + iconName: 'more', + }, +}; + +export const Danger: Story = { + args: { + variant: 'danger', + size: 'md', + iconName: 'trash', + }, +}; + +export const DangerSecondary: Story = { + args: { + variant: 'danger-secondary', + size: 'lg', + iconName: 'trash', + }, +}; + +export const AllIconStyles = () => ( +
+ {actionIconVariants.map((variant) => + actionIconSizes.map((size) => { + const actionIconProps: ActionIconProps = { + variant, + size: size, + iconName: 'more', + }; + return ( + <> + + + + + ); + }) + )} +
+); diff --git a/jsapp/js/theme/kobo/ActionIcon.module.css b/jsapp/js/theme/kobo/ActionIcon.module.css new file mode 100644 index 0000000000..4b2534b16b --- /dev/null +++ b/jsapp/js/theme/kobo/ActionIcon.module.css @@ -0,0 +1,7 @@ +.root { + &[data-disabled] { + color: var(--ai-color); + background: var(--ai-bg); + opacity: 0.5; + } +} diff --git a/jsapp/js/theme/kobo/ActionIcon.ts b/jsapp/js/theme/kobo/ActionIcon.ts new file mode 100644 index 0000000000..bf258143d5 --- /dev/null +++ b/jsapp/js/theme/kobo/ActionIcon.ts @@ -0,0 +1,38 @@ +import {rem, ActionIcon} from '@mantine/core'; +import classes from './ActionIcon.module.css'; + +export const ActionIconThemeKobo = ActionIcon.extend({ + classNames: classes, + vars: (theme, props) => { + return { + root: { + '--ai-size-sm': rem(28), + '--ai-size-md': rem(32), + '--ai-size-lg': rem(38), + + ...(props.variant === 'filled' && { + '--ai-hover': theme.colors.blue[5], + }), + ...(props.variant === 'light' && { + '--ai-color': theme.colors.blue[4], + '--ai-bg': theme.colors.blue[9], + '--ai-hover': theme.colors.blue[8], + }), + ...(props.variant === 'transparent' && { + '--ai-color': theme.colors.blue[4], + '--ai-hover-color': theme.colors.blue[5], + }), + ...(props.variant === 'danger' && { + '--ai-color': 'var(--mantine-color-white)', + '--ai-bg': theme.colors.red[6], + '--ai-hover': theme.colors.red[5], + }), + ...(props.variant === 'danger-secondary' && { + '--ai-color': theme.colors.red[5], + '--ai-bg': theme.colors.red[9], + '--ai-hover': theme.colors.red[8], + }), + }, + }; + }, +}); diff --git a/jsapp/js/theme/kobo/menu.module.css b/jsapp/js/theme/kobo/Menu.module.css similarity index 100% rename from jsapp/js/theme/kobo/menu.module.css rename to jsapp/js/theme/kobo/Menu.module.css diff --git a/jsapp/js/theme/kobo/menu.ts b/jsapp/js/theme/kobo/Menu.ts similarity index 91% rename from jsapp/js/theme/kobo/menu.ts rename to jsapp/js/theme/kobo/Menu.ts index 82e5ee6dc7..16b7008d89 100644 --- a/jsapp/js/theme/kobo/menu.ts +++ b/jsapp/js/theme/kobo/Menu.ts @@ -1,5 +1,5 @@ import {Menu} from '@mantine/core'; -import classes from './menu.module.css'; +import classes from './Menu.module.css'; declare module '@mantine/core' { export interface MenuItemProps { diff --git a/jsapp/js/theme/kobo/index.ts b/jsapp/js/theme/kobo/index.ts index 7176147f21..fb969c26fa 100644 --- a/jsapp/js/theme/kobo/index.ts +++ b/jsapp/js/theme/kobo/index.ts @@ -1,8 +1,9 @@ import {createTheme, rem} from '@mantine/core'; +import {ActionIconThemeKobo} from './ActionIcon'; import {ButtonThemeKobo} from './Button'; import {TableThemeKobo} from './Table'; import {TooltipThemeKobo} from './Tooltip'; -import {MenuThemeKobo} from './menu'; +import {MenuThemeKobo} from './Menu'; export const themeKobo = createTheme({ primaryColor: 'blue', @@ -87,6 +88,7 @@ export const themeKobo = createTheme({ }, components: { + ActionIcon: ActionIconThemeKobo, Button: ButtonThemeKobo, Menu: MenuThemeKobo, Tooltip: TooltipThemeKobo, From 6ccc8657979b78369c1218ec0132f62f96a07263 Mon Sep 17 00:00:00 2001 From: James Kiger Date: Mon, 20 Jan 2025 11:17:57 -0500 Subject: [PATCH 2/2] Remove polymorphic component creation --- jsapp/js/components/common/ActionIcon.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/jsapp/js/components/common/ActionIcon.tsx b/jsapp/js/components/common/ActionIcon.tsx index 8964fd6c6c..65a2f8ef49 100644 --- a/jsapp/js/components/common/ActionIcon.tsx +++ b/jsapp/js/components/common/ActionIcon.tsx @@ -1,6 +1,5 @@ import { ActionIcon as ActionIconMantine, - createPolymorphicComponent, } from '@mantine/core'; import type {ActionIconProps as ActionIconPropsMantine} from '@mantine/core/lib/components'; import Icon, {IconSize} from './icon'; @@ -25,6 +24,4 @@ const ActionIcon = forwardRef( } ); -export default createPolymorphicComponent<'button', ActionIconProps>( - ActionIcon -); +export default ActionIcon