diff --git a/packages/react/src/components/StoreBadge/StoreBadge.api.mdx b/packages/react/src/components/StoreBadge/StoreBadge.api.mdx new file mode 100644 index 000000000..db8204352 --- /dev/null +++ b/packages/react/src/components/StoreBadge/StoreBadge.api.mdx @@ -0,0 +1,37 @@ +import { Meta } from '@storybook/blocks'; +import LinkTo from '@storybook/addon-links/react'; +import { TableInterface } from '~storybook/components/TableInterface'; + + + +# Dropzone API + +```js +import { StoreBadge } from '@elonkit/react'; +``` + +## Component name + +The name `ESStoreBadge` can be used when providing default props or style overrides in the theme. + +## Props + + + +
+ +## CSS + + + +
+ +## Demos + + diff --git a/packages/react/src/components/StoreBadge/StoreBadge.classes.ts b/packages/react/src/components/StoreBadge/StoreBadge.classes.ts new file mode 100644 index 000000000..10bb992a1 --- /dev/null +++ b/packages/react/src/components/StoreBadge/StoreBadge.classes.ts @@ -0,0 +1,34 @@ +import { generateUtilityClass, generateUtilityClasses } from '@mui/material'; + +export type StoreBadgeClasses = { + /** Styles applied to the root element. */ + root: string; + /** Styles applied to the root element if component disabled. */ + disabled: string; + /** Styles applied to the container element. */ + container: string; + /** Styles applied to the text element. */ + text: string; + + colorMonoA: string; + colorMonoB: string; + variantFilled: string; + variantOutlined: string; +}; + +export type StoreBadgeClassKey = keyof StoreBadgeClasses; + +export function getStoreBadgeUtilityClass(slot: string): string { + return generateUtilityClass('ESStoreBadge', slot); +} + +export const storeBadgeClasses: StoreBadgeClasses = generateUtilityClasses('ESStoreBadge', [ + 'root', + 'text', + 'disabled', + 'container', + 'colorMonoA', + 'colorMonoB', + 'variantFilled', + 'variantOutlined' +]); diff --git a/packages/react/src/components/StoreBadge/StoreBadge.stories.tsx b/packages/react/src/components/StoreBadge/StoreBadge.stories.tsx new file mode 100644 index 000000000..3a1288acd --- /dev/null +++ b/packages/react/src/components/StoreBadge/StoreBadge.stories.tsx @@ -0,0 +1,36 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { StoreBadge } from '.'; + +import { IconAppStore, IconAppStoreLogo } from '../../icons'; + +const meta: Meta = { + tags: ['autodocs'], + component: StoreBadge, + parameters: { + references: ['StoreBadge'] + }, + argTypes: { + variant: { + options: ['contained', 'outlined'], + control: { type: 'select' } + }, + color: { + options: ['monoA', 'monoB'], + control: { type: 'select' } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const Demo: Story = { + render: (args) => { + return ( + } upperText="Загрузите в" {...args}> + + + ); + } +}; diff --git a/packages/react/src/components/StoreBadge/StoreBadge.tsx b/packages/react/src/components/StoreBadge/StoreBadge.tsx new file mode 100644 index 000000000..a3e9f8ccf --- /dev/null +++ b/packages/react/src/components/StoreBadge/StoreBadge.tsx @@ -0,0 +1,110 @@ +import { StoreBadgeOwnProps, StoreBadgeProps, StoreBadgeTypeMap } from './StoreBadge.types'; + +import clsx from 'clsx'; +import { getStoreBadgeUtilityClass } from './StoreBadge.classes'; + +import { unstable_composeClasses as composeClasses } from '@mui/base'; + +import { styled, useThemeProps } from '@mui/material/styles'; +import { capitalize, Typography } from '@mui/material'; +import { OverridableComponent } from '@mui/material/OverridableComponent'; + +import { Button } from '../Button'; + +type StoreBadgeOwnerState = { + classes?: StoreBadgeOwnProps['classes']; + disabled?: StoreBadgeOwnProps['disabled']; + color: NonNullable; + variant: NonNullable; +}; + +const useUtilityClasses = (ownerState: StoreBadgeOwnerState) => { + const { classes, disabled, color, variant } = ownerState; + + const slots = { + root: ['root', disabled && 'disabled', `color${capitalize(color)}`, `variant${capitalize(variant)}`], + text: ['text'], + container: ['container'] + }; + + return composeClasses(slots, getStoreBadgeUtilityClass, classes); +}; + +const StoreBadgeRoot = styled(Button, { + name: 'ESStoreBadge', + slot: 'Root', + overridesResolver: (props, styles) => { + const { + ownerState: { disabled, checked, size, variant, color } + } = props; + return [ + styles.root, + disabled && styles.disabled, + checked && styles.checked, + styles[size], + styles[`color${capitalize(color)}`], + styles[`variant${capitalize(variant)}`] + ]; + } +})(({ theme }) => ({ + ...theme.typography.body100, + textTransform: 'none' +})) as typeof Button; + +const StoreBadgeText = styled(Typography, { + name: 'ESStoreBadge', + slot: 'Text', + overridesResolver: (props, styles) => styles.text +})(({ theme }) => ({ + ...theme.typography.micro, + textTransform: 'none' +})) as typeof Typography; + +const StoreBadgeContainer = styled('div', { + name: 'ESStoreBadge', + slot: 'Container', + overridesResolver: (props, styles) => styles.container +})(() => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + gap: '2px' +})); + +export const StoreBadge: OverridableComponent = (inProps: StoreBadgeProps) => { + const { + className, + disabled, + color = 'monoA', + variant = 'contained', + children, + startIcon, + upperText, + href, + sx, + ...props + } = useThemeProps({ + props: inProps, + name: 'ESStoreBadge' + }); + + const ownerState = { ...props, disabled, color, variant }; + const classes = useUtilityClasses(ownerState); + + return ( + + + {upperText} + {children} + + + ); +}; diff --git a/packages/react/src/components/StoreBadge/StoreBadge.types.ts b/packages/react/src/components/StoreBadge/StoreBadge.types.ts new file mode 100644 index 000000000..dd875cfff --- /dev/null +++ b/packages/react/src/components/StoreBadge/StoreBadge.types.ts @@ -0,0 +1,51 @@ +/* eslint-disable @typescript-eslint/ban-types */ + +import { ReactNode } from 'react'; + +import { StoreBadgeClasses } from './StoreBadge.classes'; + +import { SxProps, Theme } from '@mui/material'; +import { OverrideProps } from '@mui/material/OverridableComponent'; + +import { ExtendButtonTypeMap } from '../Button'; + +export interface StoreBadgeOwnProps { + children: ReactNode; + /** Class applied to the root element. */ + className?: string; + /** Override or extend the styles applied to the component. */ + classes?: Partial; + /** The system prop that allows defining system overrides as well as additional CSS styles. */ + sx?: SxProps; + /** + * The color of the component. + * @default 'monoA' + */ + color?: 'monoA' | 'monoB'; + /** + * The variant of the component. + * @default 'contained' + */ + variant: 'contained' | 'outlined'; + /** Element placed before the children. */ + startIcon?: ReactNode; + /** Text placed up the children. */ + upperText?: string; + /** The URL to link to when the button is clicked. */ + href?: string; + /** If `true`, the component is disabled. */ + disabled?: boolean; +} + +export type StoreBadgeTypeMap< + AdditionalProps = {}, + RootComponent extends React.ElementType = 'button' +> = ExtendButtonTypeMap<{ + props: AdditionalProps & StoreBadgeOwnProps; + defaultComponent: RootComponent; +}>; + +export type StoreBadgeProps< + RootComponent extends React.ElementType = StoreBadgeTypeMap['defaultComponent'], + AdditionalProps = {} +> = OverrideProps, RootComponent>; diff --git a/packages/react/src/components/StoreBadge/index.ts b/packages/react/src/components/StoreBadge/index.ts new file mode 100644 index 000000000..19bda6836 --- /dev/null +++ b/packages/react/src/components/StoreBadge/index.ts @@ -0,0 +1,3 @@ +export { StoreBadge } from './StoreBadge'; +export { StoreBadgeClasses, storeBadgeClasses, StoreBadgeClassKey } from './StoreBadge.classes'; +export { StoreBadgeProps } from './StoreBadge.types'; diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index c1da40d85..7f095fe7d 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -42,6 +42,7 @@ export * from './Sidenav'; export * from './SortingMenu'; export * from './Spinner'; export * from './Spinner'; +export * from './StoreBadge'; export * from './SvgIcon'; export * from './Swiper'; export * from './Swiper'; diff --git a/packages/react/src/icons/IconAppStore.tsx b/packages/react/src/icons/IconAppStore.tsx new file mode 100644 index 000000000..d263cfa05 --- /dev/null +++ b/packages/react/src/icons/IconAppStore.tsx @@ -0,0 +1,40 @@ +import { SvgIcon, SvgIconProps } from '../components/SvgIcon'; + +export const IconAppStore = (props: SvgIconProps) => { + return ( + + + + + + + + + + + ); +}; diff --git a/packages/react/src/icons/IconAppStoreLogo.tsx b/packages/react/src/icons/IconAppStoreLogo.tsx new file mode 100644 index 000000000..d38c4ae79 --- /dev/null +++ b/packages/react/src/icons/IconAppStoreLogo.tsx @@ -0,0 +1,12 @@ +import { SvgIcon, SvgIconProps } from '../components/SvgIcon'; + +export const IconAppStoreLogo = (props: SvgIconProps) => { + return ( + + + + ); +}; diff --git a/packages/react/src/icons/index.ts b/packages/react/src/icons/index.ts index af5db3480..5c570e975 100644 --- a/packages/react/src/icons/index.ts +++ b/packages/react/src/icons/index.ts @@ -8,6 +8,8 @@ export { IconAlertLc } from './IconAlertLc'; export { IconAlertW300 } from './IconAlertW300'; export { IconAlertW500 } from './IconAlertW500'; export { IconApple } from './IconApple'; +export { IconAppStore } from './IconAppStore'; +export { IconAppStoreLogo } from './IconAppStoreLogo'; export { IconArchiveArrowDown } from './IconArchiveArrowDown'; export { IconArrowCollapse } from './IconArrowCollapse'; export { IconArrowDownW300 } from './IconArrowDownW300'; diff --git a/packages/react/src/overrides.d.ts b/packages/react/src/overrides.d.ts index 8b137b774..7180addbe 100644 --- a/packages/react/src/overrides.d.ts +++ b/packages/react/src/overrides.d.ts @@ -242,6 +242,7 @@ import { SwiperProps } from './components/Swiper'; import { SwitchClassKey, SwitchProps } from './components/Switch'; +import { StoreBadgeClassKey, StoreBadgeProps } from './components/StoreBadge'; import { TabBarClassKey, TabBarItemClassKey, TabBarItemProps, TabBarProps } from './components/TabBar'; import { TableActionsClassKey, @@ -432,6 +433,7 @@ declare module '@mui/material/styles/props' { ESSvgIcon: SvgIconProps; ESSwiper: SwiperProps; ESSwitch: SwitchProps; + ESStoreBadge: StoreBadgeProps; ESSwiperButton: SwiperButtonProps; ESSwiperPagination: SwiperPaginationProps; ESTabBar: TabBarProps; @@ -558,6 +560,7 @@ declare module '@mui/material/styles/overrides' { ESSvgIcon: SvgIconClassKey; ESSwiper: SwiperClassKey; ESSwitch: SwitchClassKey; + ESStoreBadge: StoreBadgeClassKey; ESSwiperButton: SwiperButtonClassKey; ESSwiperPagination: SwiperPaginationClassKey; ESTabBar: TabBarClassKey; @@ -799,6 +802,10 @@ declare module '@mui/material/styles/components' { defaultProps?: ComponentsProps['ESSwitch']; styleOverrides?: ComponentsOverrides['ESSwitch']; }; + ESStoreBadge?: { + defaultProps?: ComponentsProps['ESStoreBadge']; + styleOverrides?: ComponentsOverrides['ESStoreBadge']; + }; ESSwiperButton?: { defaultProps?: ComponentsProps['ESSwiperButton']; styleOverrides?: ComponentsOverrides['ESSwiperButton'];