From ada2264cee7dc9645376460bfff134d474c7c714 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Thu, 2 Oct 2025 10:03:53 +0300 Subject: [PATCH 1/9] feat(button): added BaseButtonCandidate --- jest.config.mjs | 2 + package.json | 2 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- packages/button/src/Component.responsive.tsx | 4 +- packages/button/src/Component.test.tsx | 41 +- ...button-mobile-view-sizes-sprite-3-snap.png | 4 +- ...creenshots-views-and-block-sprite-snap.png | 2 +- .../button-view-sizes-sprite-3-snap.png | 4 +- ...shots-hover-state-view-4-colors-1-snap.png | 2 +- ...ots-pressed-state-view-4-colors-0-snap.png | 4 +- ...ots-pressed-state-view-4-colors-1-snap.png | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 52 +- .../base-button-candidate/Component.tsx | 79 ++ .../base-button-candidate/index.module.css | 32 + .../components/base-button-candidate/index.ts | 2 + .../components/base-button-candidate/types.ts | 96 ++ .../src/components/base-button/Component.tsx | 240 ++--- .../components/base-button/default.module.css | 214 ++-- .../components/base-button/index.module.css | 322 ++---- .../base-button/inverted.module.css | 211 ++-- .../components/button-component/Component.tsx | 54 + .../button-component/index.module.css | 17 + .../src/components/button-component/index.ts | 1 + .../components/button-content/component.tsx | 28 + .../button-content/index.module.css | 8 + .../src/components/button-content/index.ts | 1 + .../button/src/desktop/Component.desktop.tsx | 10 +- .../src/desktop/default.desktop.module.css | 121 +-- .../button/src/desktop/desktop.module.css | 35 +- .../src/desktop/inverted.desktop.module.css | 122 +-- .../button/src/mobile/Component.mobile.tsx | 10 +- .../src/mobile/default.mobile.module.css | 111 +- .../src/mobile/inverted.mobile.module.css | 111 +- packages/button/src/mobile/mobile.module.css | 35 +- packages/button/src/shared/hooks.ts | 24 + packages/button/src/shared/index.ts | 1 + packages/button/src/typings.ts | 95 +- packages/button/src/vars.css | 3 + .../src/__snapshots__/Component.test.tsx.snap | 260 ++--- .../src/__snapshots__/Component.test.tsx.snap | 128 +-- .../src/__snapshots__/Component.test.tsx.snap | 956 +++++++++--------- .../__snapshots__/Component.test.tsx.snap | 16 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 12 +- .../src/__snapshots__/Component.test.tsx.snap | 108 +- .../src/Component.test.tsx | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 72 +- .../src/__snapshots__/Component.test.tsx.snap | 18 +- .../src/__snapshots__/Component.test.tsx.snap | 18 +- .../src/__snapshots__/Component.test.tsx.snap | 12 +- .../src/__snapshots__/Component.test.tsx.snap | 16 +- .../src/__snapshots__/Component.test.tsx.snap | 8 +- .../src/__snapshots__/component.test.tsx.snap | 12 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- .../src/__snapshots__/component.test.tsx.snap | 136 +-- .../src/__snapshots__/component.test.tsx.snap | 88 +- .../src/__snapshots__/component.test.tsx.snap | 4 +- packages/picker-button/src/Component.test.tsx | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 36 +- packages/plate/src/Component.test.tsx | 6 +- .../src/__snapshots__/Component.test.tsx.snap | 16 +- packages/vars/src/mixins.css | 13 + postcss.config.js | 2 +- tools/postcss/postcss-each.cjs | 78 ++ yarn.lock | 24 +- 65 files changed, 2142 insertions(+), 2021 deletions(-) create mode 100644 packages/button/src/components/base-button-candidate/Component.tsx create mode 100644 packages/button/src/components/base-button-candidate/index.module.css create mode 100644 packages/button/src/components/base-button-candidate/index.ts create mode 100644 packages/button/src/components/base-button-candidate/types.ts create mode 100644 packages/button/src/components/button-component/Component.tsx create mode 100644 packages/button/src/components/button-component/index.module.css create mode 100644 packages/button/src/components/button-component/index.ts create mode 100644 packages/button/src/components/button-content/component.tsx create mode 100644 packages/button/src/components/button-content/index.module.css create mode 100644 packages/button/src/components/button-content/index.ts create mode 100644 packages/button/src/shared/hooks.ts create mode 100644 tools/postcss/postcss-each.cjs diff --git a/jest.config.mjs b/jest.config.mjs index 1851966fd4..fcfd62f029 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -56,6 +56,8 @@ const [initialProjectOptions] = [ moduleNameMapper: { ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: '/' }), '^.+\\.css$': 'identity-obj-proxy', + // TODO remove test + 'postcss-each': path.join(import.meta.dirname, 'tools/postcss/postcss-each.cjs'), }, testPathIgnorePatterns: IGNORED_PACKAGES.map((pkg) => { const relativeDir = path.relative(import.meta.dirname, resolveInternal(pkg)); diff --git a/package.json b/package.json index a49a95cc43..1794900989 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,6 @@ "postcss-color-mod-function": "^4.1.1", "postcss-custom-media": "^8.0.2", "postcss-custom-properties": "^12.1.10", - "postcss-each": "^1.1.0", "postcss-export-custom-variables": "^1.0.0", "postcss-for": "^2.1.1", "postcss-import": "^16.1.1", @@ -154,6 +153,7 @@ "postcss-mixins": "^7.0.3", "postcss-modules": "^6.0.1", "postcss-preset-env": "^7.8.3", + "postcss-simple-vars": "^7.0.1", "prettier": "~3.6.2", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.1", diff --git a/packages/attach/src/__snapshots__/Component.test.tsx.snap b/packages/attach/src/__snapshots__/Component.test.tsx.snap index e6274801c6..beeae5e8c4 100644 --- a/packages/attach/src/__snapshots__/Component.test.tsx.snap +++ b/packages/attach/src/__snapshots__/Component.test.tsx.snap @@ -6,11 +6,11 @@ exports[`Attach Snapshots tests should match snapshot 1`] = ` class="component size-48" >
@@ -206,11 +210,11 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with error prop 1`] = ` class="component" >
diff --git a/packages/pass-code/src/__snapshots__/component.test.tsx.snap b/packages/pass-code/src/__snapshots__/component.test.tsx.snap index 0fdc1d4e03..8f8164dda9 100644 --- a/packages/pass-code/src/__snapshots__/component.test.tsx.snap +++ b/packages/pass-code/src/__snapshots__/component.test.tsx.snap @@ -53,101 +53,105 @@ exports[`PassCode Snapshot tests should match snapshot with code length 1`] = ` class="component" >
@@ -179,101 +183,105 @@ exports[`PassCode Snapshot tests should match snapshot with unknown code length class="component" >
diff --git a/packages/password-input/src/__snapshots__/component.test.tsx.snap b/packages/password-input/src/__snapshots__/component.test.tsx.snap index 3c73293a09..d13456d044 100644 --- a/packages/password-input/src/__snapshots__/component.test.tsx.snap +++ b/packages/password-input/src/__snapshots__/component.test.tsx.snap @@ -26,12 +26,12 @@ exports[`PasswordInput snapshots tests should match snapshot 1`] = ` class="addons rightAddons rightAddons size-48" >
@@ -969,30 +961,26 @@ exports[`CalendarRange Display tests should match snapshot 1`] = ` >
diff --git a/packages/calendar/src/__snapshots__/Component.test.tsx.snap b/packages/calendar/src/__snapshots__/Component.test.tsx.snap index 0a25776e18..e838544e3c 100644 --- a/packages/calendar/src/__snapshots__/Component.test.tsx.snap +++ b/packages/calendar/src/__snapshots__/Component.test.tsx.snap @@ -3386,30 +3386,26 @@ exports[`Calendar Display tests should match selectorView="month-only" snapshot >
diff --git a/packages/calendar/src/components/period-slider/__snapshots__/Component.test.tsx.snap b/packages/calendar/src/components/period-slider/__snapshots__/Component.test.tsx.snap index b28330d84e..e8d5541a91 100644 --- a/packages/calendar/src/components/period-slider/__snapshots__/Component.test.tsx.snap +++ b/packages/calendar/src/components/period-slider/__snapshots__/Component.test.tsx.snap @@ -9,31 +9,27 @@ exports[`PeriodSlider empty PeriodSlider empty PeriodSlider default title snapsh > @@ -83,31 +75,27 @@ exports[`PeriodSlider empty PeriodSlider empty PeriodSlider specific title snaps > diff --git a/packages/file-upload-item-v1/src/__snapshots__/Component.test.tsx.snap b/packages/file-upload-item-v1/src/__snapshots__/Component.test.tsx.snap index 3b6367ee51..d7abe06542 100644 --- a/packages/file-upload-item-v1/src/__snapshots__/Component.test.tsx.snap +++ b/packages/file-upload-item-v1/src/__snapshots__/Component.test.tsx.snap @@ -51,57 +51,49 @@ exports[`FileUploadItemV1 Snapshots tests should match snapshot 1`] = `
- - - - - + + @@ -154,57 +146,49 @@ exports[`FileUploadItemV1 Snapshots tests should match snapshot 1`] = ` - - - - - + + diff --git a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png index 55c90c17e8..33ff2c237a 100644 --- a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png +++ b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e53491bfb3fc6f57e699eb2c415dbcb9f83afb4df39ca93933ba24df1fe97ac -size 746 +oid sha256:62097e0415d97675a2f7450354d02030659f8f27758cf13087b9c659efd39b6c +size 666 diff --git a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png index b6e213019c..47efd91ae2 100644 --- a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png +++ b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67d0e1565e1e3c8b6453dfbe05895aee84aae9c28dd30fbc55eab831ab0a6d0b -size 623 +oid sha256:0fc8bbcebdb89d7e81c629a0d947c3fe8892af7bdc60225f8d0fd5a200ceae17 +size 711 diff --git a/packages/icon-button/src/__snapshots__/Component.test.tsx.snap b/packages/icon-button/src/__snapshots__/Component.test.tsx.snap index dd4f1958b5..f61acf4182 100644 --- a/packages/icon-button/src/__snapshots__/Component.test.tsx.snap +++ b/packages/icon-button/src/__snapshots__/Component.test.tsx.snap @@ -7,43 +7,9 @@ exports[`IconButton Href tests should set \`href\` attribute and be link 1`] = `
- - - - - - - - -
- , - "container":
- - + +
+ , + "container":
+ + + + +
, @@ -125,40 +117,8 @@ exports[`IconButton Snapshots tests should match snapshot 1`] = ` "baseElement":
-
- , - "container":
- +
+ , + "container":
+
, diff --git a/packages/icon-button/src/components/base-icon-button/Component.tsx b/packages/icon-button/src/components/base-icon-button/Component.tsx index f1e7ae525a..6c73587751 100644 --- a/packages/icon-button/src/components/base-icon-button/Component.tsx +++ b/packages/icon-button/src/components/base-icon-button/Component.tsx @@ -1,8 +1,9 @@ import React, { forwardRef, type ReactElement } from 'react'; import cn from 'classnames'; -import { ButtonDesktop } from '@alfalab/core-components-button/desktop'; -import { ButtonMobile } from '@alfalab/core-components-button/mobile'; +import { BaseButtonCandidate } from '@alfalab/core-components-button/components/base-button-candidate'; +import { ButtonContent } from '@alfalab/core-components-button/components/button-content'; +import { useLoading } from '@alfalab/core-components-button/shared'; import { type IconButtonProps } from '../../types/icon-button-props'; @@ -13,14 +14,14 @@ import invertedColors from './inverted.module.css'; const colorStyles = { default: defaultColors, inverted: invertedColors, -}; +} as const; -type BaseIconButtonProps = { - client: 'desktop' | 'mobile'; - clientStyles: Record; -}; - -export const BaseIconButton = forwardRef( +export const BaseIconButton = forwardRef< + HTMLButtonElement, + IconButtonProps & { + clientStyles: Record; + } +>( ( { className, @@ -30,36 +31,40 @@ export const BaseIconButton = forwardRef { - const Component = client === 'desktop' ? ButtonDesktop : ButtonMobile; + const loading = useLoading(loadingFromProps); return ( - {React.isValidElement(Icon) ? ( - React.cloneElement(Icon as ReactElement<{ className?: string }>, { + React.cloneElement(Icon, { className: cn( styles.icon, (Icon as ReactElement<{ className?: string }>).props.className, @@ -69,7 +74,7 @@ export const BaseIconButton = forwardRef )} - + ); }, ); diff --git a/packages/icon-button/src/components/base-icon-button/default.module.css b/packages/icon-button/src/components/base-icon-button/default.module.css index 231494d1f5..3620310b2c 100644 --- a/packages/icon-button/src/components/base-icon-button/default.module.css +++ b/packages/icon-button/src/components/base-icon-button/default.module.css @@ -36,60 +36,70 @@ &.primary { color: var(--icon-button-primary-base-color); - @mixin hover { - color: var(--icon-button-primary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-primary-hover-color); + } - &:active { - color: var(--icon-button-primary-active-color); + &:active { + color: var(--icon-button-primary-active-color); + } } } &.secondary { color: var(--icon-button-secondary-base-color); - @mixin hover { - color: var(--icon-button-secondary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-secondary-hover-color); + } - &:active { - color: var(--icon-button-secondary-active-color); + &:active { + color: var(--icon-button-secondary-active-color); + } } } &.transparent { color: var(--icon-button-transparent-base-color); - @mixin hover { - color: var(--icon-button-transparent-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-transparent-hover-color); + } - &:active { - color: var(--icon-button-transparent-active-color); + &:active { + color: var(--icon-button-transparent-active-color); + } } } &.negative { color: var(--icon-button-negative-base-color); - @mixin hover { - color: var(--icon-button-negative-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-negative-hover-color); + } - &:active { - color: var(--icon-button-negative-active-color); + &:active { + color: var(--icon-button-negative-active-color); + } } } &.tertiary { color: var(--icon-button-tertiary-base-color); - @mixin hover { - color: var(--icon-button-tertiary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-tertiary-hover-color); + } - &:active { - color: var(--icon-button-tertiary-active-color); + &:active { + color: var(--icon-button-tertiary-active-color); + } } } @@ -97,87 +107,105 @@ &.primary { color: var(--color-light-text-primary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.secondary { color: var(--color-light-text-secondary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.negative { color: var(--color-light-text-negative); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.tertiary { color: var(--color-light-text-tertiary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } } - &.component:disabled { - &.primary { - color: var(--icon-button-primary-disabled-color); + &.component { + @mixin disabled { + &.primary { + color: var(--icon-button-primary-disabled-color); - &.loader { - color: var(--icon-button-primary-base-color); + &.loader { + color: var(--icon-button-primary-base-color); + } } - } - &.secondary { - color: var(--icon-button-secondary-disabled-color); + &.secondary { + color: var(--icon-button-secondary-disabled-color); - &.loader { - color: var(--icon-button-secondary-base-color); + &.loader { + color: var(--icon-button-secondary-base-color); + } } - } - &.negative { - color: var(--icon-button-negative-disabled-color); + &.transparent { + color: var(--icon-button-transparent-disabled-color); - &.loader { - color: var(--icon-button-negative-base-color); + &.loader { + color: var(--icon-button-transparent-base-color); + } } - } - &.tertiary { - color: var(--icon-button-tertiary-disabled-color); + &.negative { + color: var(--icon-button-negative-disabled-color); - &.loader { - color: var(--icon-button-tertiary-base-color); + &.loader { + color: var(--icon-button-negative-base-color); + } } - } - &.transparentBg { - background: transparent; + &.tertiary { + color: var(--icon-button-tertiary-disabled-color); + + &.loader { + color: var(--icon-button-tertiary-base-color); + } + } + + &.transparentBg { + background: transparent; + } } } } diff --git a/packages/icon-button/src/components/base-icon-button/index.module.css b/packages/icon-button/src/components/base-icon-button/index.module.css index 4b997d4782..222e9b6081 100644 --- a/packages/icon-button/src/components/base-icon-button/index.module.css +++ b/packages/icon-button/src/components/base-icon-button/index.module.css @@ -1,6 +1,16 @@ @import '@alfalab/core-components-vars/src/no-typography-index.css'; @import '../../vars.css'; +.component { + position: relative; + + /* Loading */ + + &.loading > *:not(.loader) { + opacity: 0; + } +} + .size-24 { width: var(--icon-button-xxs-size); height: var(--icon-button-xxs-size); diff --git a/packages/icon-button/src/components/base-icon-button/inverted.module.css b/packages/icon-button/src/components/base-icon-button/inverted.module.css index 0b6f20d65e..81727ecd37 100644 --- a/packages/icon-button/src/components/base-icon-button/inverted.module.css +++ b/packages/icon-button/src/components/base-icon-button/inverted.module.css @@ -66,60 +66,70 @@ &.primary { color: var(--icon-button-inverted-primary-base-color); - @mixin hover { - color: var(--icon-button-inverted-primary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-primary-hover-color); + } - &:active { - color: var(--icon-button-inverted-primary-active-color); + &:active { + color: var(--icon-button-inverted-primary-active-color); + } } } &.secondary { color: var(--icon-button-inverted-secondary-base-color); - @mixin hover { - color: var(--icon-button-inverted-secondary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-secondary-hover-color); + } - &:active { - color: var(--icon-button-inverted-secondary-active-color); + &:active { + color: var(--icon-button-inverted-secondary-active-color); + } } } &.transparent { color: var(--icon-button-inverted-transparent-base-color); - @mixin hover { - color: var(--icon-button-inverted-transparent-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-transparent-hover-color); + } - &:active { - color: var(--icon-button-inverted-transparent-active-color); + &:active { + color: var(--icon-button-inverted-transparent-active-color); + } } } &.negative { color: var(--icon-button-inverted-negative-base-color); - @mixin hover { - color: var(--icon-button-inverted-negative-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-negative-hover-color); + } - &:active { - color: var(--icon-button-inverted-negative-active-color); + &:active { + color: var(--icon-button-inverted-negative-active-color); + } } } &.tertiary { color: var(--icon-button-inverted-tertiary-base-color); - @mixin hover { - color: var(--icon-button-inverted-tertiary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-tertiary-hover-color); + } - &:active { - color: var(--icon-button-inverted-tertiary-active-color); + &:active { + color: var(--icon-button-inverted-tertiary-active-color); + } } } @@ -127,87 +137,105 @@ &.primary { color: var(--color-light-text-primary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.secondary { color: var(--color-light-text-secondary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.negative { color: var(--color-light-text-negative-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.tertiary { color: var(--color-light-text-tertiary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } } - &.component:disabled { - &.primary { - color: var(--icon-button-inverted-primary-disabled-color); + &.component { + @mixin disabled { + &.primary { + color: var(--icon-button-inverted-primary-disabled-color); - &.loader { - color: var(--icon-button-inverted-primary-base-color); + &.loader { + color: var(--icon-button-inverted-primary-base-color); + } } - } - &.secondary { - color: var(--icon-button-inverted-secondary-disabled-color); + &.secondary { + color: var(--icon-button-inverted-secondary-disabled-color); - &.loader { - color: var(--icon-button-inverted-secondary-base-color); + &.loader { + color: var(--icon-button-inverted-secondary-base-color); + } } - } - &.negative { - color: var(--icon-button-inverted-negative-disabled-color); + &.transparent { + color: var(--icon-button-inverted-transparent-disabled-color); - &.loader { - color: var(--icon-button-inverted-negative-base-color); + &.loader { + color: var(--icon-button-inverted-transparent-base-color); + } } - } - &.tertiary { - color: var(--icon-button-inverted-tertiary-disabled-color); + &.negative { + color: var(--icon-button-inverted-negative-disabled-color); - &.loader { - color: var(--icon-button-inverted-tertiary-base-color); + &.loader { + color: var(--icon-button-inverted-negative-base-color); + } } - } - &.transparentBg { - background: transparent; + &.tertiary { + color: var(--icon-button-inverted-tertiary-disabled-color); + + &.loader { + color: var(--icon-button-inverted-tertiary-base-color); + } + } + + &.transparentBg { + background: transparent; + } } } } diff --git a/packages/icon-button/src/desktop/Component.desktop.tsx b/packages/icon-button/src/desktop/Component.desktop.tsx index 0a3a29e900..a30cef0621 100644 --- a/packages/icon-button/src/desktop/Component.desktop.tsx +++ b/packages/icon-button/src/desktop/Component.desktop.tsx @@ -8,9 +8,7 @@ import clientStyles from './desktop.module.css'; export type IconButtonDesktopProps = IconButtonProps; export const IconButtonDesktop = forwardRef( - (props, ref) => ( - - ), + (props, ref) => , ); IconButtonDesktop.displayName = 'IconButtonDesktop'; diff --git a/packages/icon-button/src/mobile/Component.mobile.tsx b/packages/icon-button/src/mobile/Component.mobile.tsx index eee2df61c5..9dcb03211c 100644 --- a/packages/icon-button/src/mobile/Component.mobile.tsx +++ b/packages/icon-button/src/mobile/Component.mobile.tsx @@ -8,9 +8,7 @@ import clientStyles from './mobile.module.css'; export type IconButtonMobileProps = IconButtonProps; export const IconButtonMobile = forwardRef( - (props, ref) => ( - - ), + (props, ref) => , ); IconButtonMobile.displayName = 'IconButtonMobile'; diff --git a/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap b/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap index 3fd4eabf86..c9518b355d 100644 --- a/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap +++ b/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap @@ -145,29 +145,25 @@ exports[`InputAutocompleteMobile Snapshots tests should match snapshot in open s > diff --git a/packages/modal/src/__snapshots__/Component.test.tsx.snap b/packages/modal/src/__snapshots__/Component.test.tsx.snap index d1b68c45c2..45c754f057 100644 --- a/packages/modal/src/__snapshots__/Component.test.tsx.snap +++ b/packages/modal/src/__snapshots__/Component.test.tsx.snap @@ -74,29 +74,25 @@ exports[`ModalDesktop snapshots tests should match snapshot 1`] = ` > @@ -212,29 +208,25 @@ exports[`ModalMobile snapshots tests should match snapshot 1`] = ` > diff --git a/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap b/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap index 0488d5913b..6ce1f0ddc3 100644 --- a/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap +++ b/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap @@ -66,30 +66,26 @@ exports[`Navigation Bar Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/notification-manager/src/__snapshots__/component.test.tsx.snap b/packages/notification-manager/src/__snapshots__/component.test.tsx.snap index 6481b45f91..a0232741ef 100644 --- a/packages/notification-manager/src/__snapshots__/component.test.tsx.snap +++ b/packages/notification-manager/src/__snapshots__/component.test.tsx.snap @@ -57,29 +57,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > @@ -120,29 +116,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > @@ -183,29 +175,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/notification/src/__snapshots__/Component.test.tsx.snap b/packages/notification/src/__snapshots__/Component.test.tsx.snap index 6d04068aee..35ee8baeab 100644 --- a/packages/notification/src/__snapshots__/Component.test.tsx.snap +++ b/packages/notification/src/__snapshots__/Component.test.tsx.snap @@ -67,29 +67,25 @@ exports[`Notification Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css index 60277952b2..8825bb539f 100644 --- a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css +++ b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css @@ -6,64 +6,54 @@ justify-content: center; align-items: center; padding: var(--gap-0); -} - -.button.button { - @mixin action_component_secondary; - border-radius: var(--border-radius-circle); - padding: var(--gap-0); - min-width: 64px; - width: 64px; - height: 64px; - text-align: center; + .button.button { + @mixin action_component_secondary; - & > span { - vertical-align: middle; + border-radius: var(--border-radius-circle); + width: 64px; + height: 64px; + text-align: center; - & > * { + & > span { vertical-align: middle; - } - } -} - -.secondary.secondary { - color: var(--color-light-text-primary); - background: var(--button-bg-color); - - &:hover { - color: var(--color-light-text-primary); - } - - &:active { - background: var(--button-bg-color-active); - } -} -.ghost.ghost { - color: var(--color-light-text-primary); - - &:hover { - color: var(--color-light-text-primary); - } + & > * { + vertical-align: middle; + } + } - &:active { - background: var(--button-bg-color-active); - } -} + &.secondary.secondary { + padding: var(--gap-0); + min-width: 64px; + color: var(--color-light-text-primary); + background: var(--button-bg-color); + + @mixin not-disabled { + @mixin hover { + color: var(--color-light-text-primary); + } + + &:active { + background: var(--button-bg-color-active); + } + } + } -@media screen and (min-width: 360px) { - .button.button { - min-width: 76px; - height: 76px; - width: 76px; - } -} + @media screen and (min-width: 360px) { + & { + min-width: 76px; + height: 76px; + width: 76px; + } + } -@media screen and (min-width: 390px) { - .button.button { - min-width: 86px; - width: 86px; - height: 86px; + @media screen and (min-width: 390px) { + & { + min-width: 86px; + width: 86px; + height: 86px; + } + } } } diff --git a/packages/password-input/src/__snapshots__/component.test.tsx.snap b/packages/password-input/src/__snapshots__/component.test.tsx.snap index d13456d044..3f4caf118e 100644 --- a/packages/password-input/src/__snapshots__/component.test.tsx.snap +++ b/packages/password-input/src/__snapshots__/component.test.tsx.snap @@ -26,35 +26,31 @@ exports[`PasswordInput snapshots tests should match snapshot 1`] = ` class="addons rightAddons rightAddons size-48" > diff --git a/packages/picker-button/src/__snapshots__/Component.test.tsx.snap b/packages/picker-button/src/__snapshots__/Component.test.tsx.snap index 2ca8b8b20d..7cbf92c527 100644 --- a/packages/picker-button/src/__snapshots__/Component.test.tsx.snap +++ b/packages/picker-button/src/__snapshots__/Component.test.tsx.snap @@ -360,29 +360,25 @@ exports[`Snapshots tests should display opened correctly 4`] = ` > @@ -851,29 +847,25 @@ exports[`Snapshots tests should display opened correctly 6`] = ` > diff --git a/packages/side-panel/src/__snapshots__/Component.test.tsx.snap b/packages/side-panel/src/__snapshots__/Component.test.tsx.snap index cb3dc71511..680d68fbd0 100644 --- a/packages/side-panel/src/__snapshots__/Component.test.tsx.snap +++ b/packages/side-panel/src/__snapshots__/Component.test.tsx.snap @@ -77,29 +77,25 @@ exports[`SidePanelDesktop snapshots tests should match snapshot 1`] = ` > @@ -219,29 +215,25 @@ exports[`SidePanelMobile snapshots tests should match snapshot 1`] = ` > diff --git a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png index 94414b101d..6ed6644efb 100644 --- a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png +++ b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb8a7a4914c0da52cce4e63438175e19b66ab1bafaab4cff36c044499491bb0d -size 8366 +oid sha256:f573d006f58e13148821d3e1db35ce2e16046574e1f517b73f5d799e0a3fd80f +size 8620 diff --git a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png index aadc46fd73..eeede83270 100644 --- a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png +++ b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7feb7bee476ec0ef0f8adb3b164ac067c576f8811846ac903f164295b3944836 -size 8410 +oid sha256:b9310a20e865debea20542198c0592f26af7c7a07e1148fcde2f741d94e0b36c +size 8659 From 277f570afccacc6945257190e24fea3ea9ad702e Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Tue, 7 Oct 2025 15:45:02 +0300 Subject: [PATCH 3/9] refactor(pass-code-v1): used BaseButtonCandidate --- .../src/__snapshots__/component.test.tsx.snap | 588 +++++------------- packages/pass-code-v1/src/component.test.tsx | 2 +- .../src/components/KeyPad/Component.tsx | 6 +- .../src/components/KeyPadButton/Component.tsx | 42 +- .../components/KeyPadButton/index.module.css | 69 +- 5 files changed, 220 insertions(+), 487 deletions(-) diff --git a/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap b/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap index 97a9d3d703..eccff4798d 100644 --- a/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap +++ b/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap @@ -35,147 +35,67 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with code length 1`] =
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
+ 0 +
@@ -206,177 +126,89 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with error prop 1`] = `
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
-
+ -
+ + + +
@@ -404,147 +236,67 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with unknown code lengt
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
+ 0 +
diff --git a/packages/pass-code-v1/src/component.test.tsx b/packages/pass-code-v1/src/component.test.tsx index 697ce3c939..ce3f89adc7 100644 --- a/packages/pass-code-v1/src/component.test.tsx +++ b/packages/pass-code-v1/src/component.test.tsx @@ -39,7 +39,7 @@ describe('PassCodeV1', () => { const { getByText } = render(); - const button = getByText(pressedDigit).parentNode as HTMLButtonElement; + const button = getByText(pressedDigit) as HTMLButtonElement; fireEvent.click(button); diff --git a/packages/pass-code-v1/src/components/KeyPad/Component.tsx b/packages/pass-code-v1/src/components/KeyPad/Component.tsx index 3f0a5c6c3b..cbd8c5f5a5 100644 --- a/packages/pass-code-v1/src/components/KeyPad/Component.tsx +++ b/packages/pass-code-v1/src/components/KeyPad/Component.tsx @@ -81,10 +81,14 @@ export const KeyPad: React.FC = ({ return
; } + const handleDigitClick = () => { + onClick(digit); + }; + return ( = { +export type KeyPadButtonProps = { /** * Вид кнопки. */ - view: ButtonMobileProps['view']; + view: 'secondary' | 'text'; /** * Значение. */ - children: T; + children?: ReactNode; /** * Дополнительный класс. @@ -29,7 +29,7 @@ export type KeyPadButtonProps = { /** * Коллбэк нажатия на кнопку. */ - onClick?: (payload: T) => void; + onClick?: () => void; /** * Идентификатор для систем автоматизированного тестирования. @@ -37,24 +37,18 @@ export type KeyPadButtonProps = { dataTestId?: string; }; -export function KeyPadButton({ - children, - onClick, - className, +export const KeyPadButton: FC = ({ view = 'secondary', buttonClassName, + children, dataTestId, -}: KeyPadButtonProps) { - return ( -
- onClick?.(children)} - dataTestId={dataTestId} - > - {children} - -
- ); -} + onClick, +}) => ( + + {children} + +); diff --git a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css index 8825bb539f..57c7c16ea9 100644 --- a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css +++ b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css @@ -2,58 +2,41 @@ @import '../../vars.css'; .component { - display: flex; - justify-content: center; - align-items: center; - padding: var(--gap-0); + @mixin action_component_secondary; - .button.button { - @mixin action_component_secondary; + border-radius: var(--border-radius-circle); + width: 64px; + height: 64px; - border-radius: var(--border-radius-circle); - width: 64px; - height: 64px; - text-align: center; + justify-content: center; + align-items: center; + color: var(--color-light-text-primary); - & > span { - vertical-align: middle; + &.secondary { + background: var(--button-bg-color); - & > * { - vertical-align: middle; - } + &:active { + background: var(--button-bg-color-active); } + } - &.secondary.secondary { - padding: var(--gap-0); - min-width: 64px; - color: var(--color-light-text-primary); - background: var(--button-bg-color); - - @mixin not-disabled { - @mixin hover { - color: var(--color-light-text-primary); - } - - &:active { - background: var(--button-bg-color-active); - } - } + &.text { + @mixin hover { + color: var(--color-light-text-primary-hover); } - @media screen and (min-width: 360px) { - & { - min-width: 76px; - height: 76px; - width: 76px; - } + &:active { + color: var(--color-light-text-primary-press); } + } - @media screen and (min-width: 390px) { - & { - min-width: 86px; - width: 86px; - height: 86px; - } - } + @media screen and (min-width: 360px) { + height: 76px; + width: 76px; + } + + @media screen and (min-width: 390px) { + width: 86px; + height: 86px; } } From a8f43e21f34e6e902514bcbf470eeeeac3330019 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Tue, 7 Oct 2025 20:06:50 +0300 Subject: [PATCH 4/9] refactor(pass-code): used BaseButtonCandidate --- .../src/__snapshots__/component.test.tsx.snap | 160 +++++------------- packages/pass-code/src/component.test.tsx | 2 +- .../src/components/KeyPad/Component.tsx | 10 +- .../src/components/KeyPadButton/Component.tsx | 62 +++---- .../components/KeyPadButton/index.module.css | 27 +-- .../pass-code/src/docs/Component.stories.tsx | 6 +- packages/pass-code/src/docs/description.mdx | 16 +- 7 files changed, 82 insertions(+), 201 deletions(-) diff --git a/packages/pass-code/src/__snapshots__/component.test.tsx.snap b/packages/pass-code/src/__snapshots__/component.test.tsx.snap index 8f8164dda9..800ae4abd7 100644 --- a/packages/pass-code/src/__snapshots__/component.test.tsx.snap +++ b/packages/pass-code/src/__snapshots__/component.test.tsx.snap @@ -53,105 +53,65 @@ exports[`PassCode Snapshot tests should match snapshot with code length 1`] = ` class="component" >
@@ -183,105 +143,65 @@ exports[`PassCode Snapshot tests should match snapshot with unknown code length class="component" >
diff --git a/packages/pass-code/src/component.test.tsx b/packages/pass-code/src/component.test.tsx index 94ad123caf..359d07bb7e 100644 --- a/packages/pass-code/src/component.test.tsx +++ b/packages/pass-code/src/component.test.tsx @@ -45,7 +45,7 @@ describe('PassCode', () => { const { getByText } = render(); - const button = getByText(pressedDigit).parentNode as HTMLButtonElement; + const button = getByText(pressedDigit) as HTMLButtonElement; fireEvent.click(button); diff --git a/packages/pass-code/src/components/KeyPad/Component.tsx b/packages/pass-code/src/components/KeyPad/Component.tsx index 3f8cbc41fd..f35dda2d64 100644 --- a/packages/pass-code/src/components/KeyPad/Component.tsx +++ b/packages/pass-code/src/components/KeyPad/Component.tsx @@ -74,9 +74,8 @@ export const KeyPad: React.FC = ({ @@ -98,11 +97,14 @@ export const KeyPad: React.FC = ({ return
; } + const handleDigitClick = () => { + onClick(digit); + }; + return ( diff --git a/packages/pass-code/src/components/KeyPadButton/Component.tsx b/packages/pass-code/src/components/KeyPadButton/Component.tsx index 88d080f6b1..7b1a4f34b0 100644 --- a/packages/pass-code/src/components/KeyPadButton/Component.tsx +++ b/packages/pass-code/src/components/KeyPadButton/Component.tsx @@ -1,64 +1,48 @@ -import React, { type ReactNode } from 'react'; +import React, { type FC, type ReactNode } from 'react'; import cn from 'classnames'; -import { ButtonMobile, type ButtonMobileProps } from '@alfalab/core-components-button/mobile'; +import { BaseButtonCandidate } from '@alfalab/core-components-button/components/base-button-candidate'; import styles from './index.module.css'; -export type KeyPadButtonProps = { +export interface KeyPadButtonProps { /** - * Вид кнопки + * Значение. */ - view: ButtonMobileProps['view']; + children?: ReactNode; /** - * Значение - */ - children: T; - - /** - * Дополнительный класс + * Дополнительный класс. */ className?: string; /** - * Дополнительный класс кнопки + * Дополнительный класс кнопки. */ buttonClassName?: string; /** - * Коллбэк нажатия на кнопку + * Коллбэк нажатия на кнопку. */ - onClick?: (payload: T) => void; + onClick?: () => void; /** - * Идентификатор для систем автоматизированного тестирования + * Идентификатор для систем автоматизированного тестирования. */ dataTestId?: string; +} - /** - * Заголовок кнопки - */ - title?: string; -}; - -export function KeyPadButton({ - children, - onClick, - view = 'secondary', +export const KeyPadButton: FC = ({ buttonClassName, + children, dataTestId, - title, -}: KeyPadButtonProps) { - return ( - onClick?.(children)} - dataTestId={dataTestId} - {...(title && { title })} - > - {children} - - ); -} + onClick, +}) => ( + + {children} + +); diff --git a/packages/pass-code/src/components/KeyPadButton/index.module.css b/packages/pass-code/src/components/KeyPadButton/index.module.css index 5db8662c3e..d2adc43d10 100644 --- a/packages/pass-code/src/components/KeyPadButton/index.module.css +++ b/packages/pass-code/src/components/KeyPadButton/index.module.css @@ -1,35 +1,20 @@ @import '@alfalab/core-components-vars/src/no-typography-index.css'; @import '../../vars.css'; -.button.button { +.component { @mixin action_component_secondary; border-radius: var(--border-radius-circle); - padding: var(--gap-0); - min-width: var(--pass-code-button-min-width); width: var(--pass-code-button-width); height: var(--pass-code-button-height); - text-align: center; - - & > span { - vertical-align: middle; - - & > * { - vertical-align: middle; - } - } -} - -.secondary.secondary, -.button.button { + justify-content: center; + align-items: center; color: var(--color-light-text-primary); - background-color: var(--color-light-transparent-default); + background: var(--color-light-transparent-default); - @media (hover: hover) { - &:hover { - background-color: var(--color-light-transparent-default-hover); - } + @mixin hover { + background-color: var(--color-light-transparent-default-hover); } &:active { diff --git a/packages/pass-code/src/docs/Component.stories.tsx b/packages/pass-code/src/docs/Component.stories.tsx index 385b8bee03..bbd72d53ab 100644 --- a/packages/pass-code/src/docs/Component.stories.tsx +++ b/packages/pass-code/src/docs/Component.stories.tsx @@ -38,14 +38,12 @@ export const pass_code: Story = { disabled={boolean('disabled', false)} leftAddons={ boolean('leftAddons', false) && ( - - Забыли код? - + Забыли код? ) } rightAddons={ boolean('rightAddons', false) && ( - + ) diff --git a/packages/pass-code/src/docs/description.mdx b/packages/pass-code/src/docs/description.mdx index fffa676749..f47a30ac4f 100644 --- a/packages/pass-code/src/docs/description.mdx +++ b/packages/pass-code/src/docs/description.mdx @@ -215,13 +215,9 @@ render(() => { onChange={handleChange} error={error} success={isSuccess} - leftAddons={ - - Забыли код? - - } + leftAddons={Забыли код?} rightAddons={ - + } @@ -272,13 +268,9 @@ render(() => { onChange={handleChange} error={error} success={isSuccess} - leftAddons={ - - Забыли код? - - } + leftAddons={Забыли код?} rightAddons={ - + } From ba9204ccc97475ca88bfdf703da3be25b0553ba1 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Wed, 8 Oct 2025 12:07:05 +0300 Subject: [PATCH 5/9] refactor(pattern-lock-v1): button styles --- .../src/__snapshots__/component.test.tsx.snap | 4 +-- .../base-pattern-lock/Component.tsx | 35 ++++++++++--------- .../base-pattern-lock/index.module.css | 9 +++-- .../src/desktop/desktop.module.css | 2 +- .../src/mobile/mobile.module.css | 10 ++++-- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap b/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap index 630991db6c..d92d76a7ad 100644 --- a/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap +++ b/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap @@ -9,7 +9,7 @@ exports[`PatternLockV1 test Snapshot tests should match snapshot 1`] = ` class="message" />
@@ -26,7 +26,7 @@ exports[`PatternLockV1 test Snapshot tests should match snapshot with error prop Error message
diff --git a/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx b/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx index ca07026e6e..b7830a5299 100644 --- a/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx +++ b/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx @@ -126,23 +126,24 @@ export const BasePatternLock = forwardRef< extraBounds={extraBounds} hover={hover} /> - - {showForgotCodeBtn ? ( - - {forgotCodeBtnText} - - ) : ( -
- )} +
+ {showForgotCodeBtn && ( + + {forgotCodeBtnText} + + )} +
); }, diff --git a/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css b/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css index a9b297ba41..e02b49b74d 100644 --- a/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css +++ b/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css @@ -28,7 +28,12 @@ color: var(--color-light-text-negative); } -.forgotBtn { - display: block; +.forgotBtnContainer { + display: flex; + justify-content: center; +} + +.forgotBtnContainer, +.forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-xs-height); } diff --git a/packages/pattern-lock-v1/src/desktop/desktop.module.css b/packages/pattern-lock-v1/src/desktop/desktop.module.css index f9a14de1e5..d580c66f7e 100644 --- a/packages/pattern-lock-v1/src/desktop/desktop.module.css +++ b/packages/pattern-lock-v1/src/desktop/desktop.module.css @@ -6,7 +6,7 @@ margin: var(--gap-8) var(--gap-0) var(--gap-24) var(--gap-0); } -.forgotBtn { +.forgotBtnContainer { margin: var(--gap-24) auto var(--gap-0); } diff --git a/packages/pattern-lock-v1/src/mobile/mobile.module.css b/packages/pattern-lock-v1/src/mobile/mobile.module.css index 771c91fc56..9caaaa80e1 100644 --- a/packages/pattern-lock-v1/src/mobile/mobile.module.css +++ b/packages/pattern-lock-v1/src/mobile/mobile.module.css @@ -6,13 +6,16 @@ margin: var(--gap-8) var(--gap-0) var(--gap-24) var(--gap-0); } -.forgotBtn { +.forgotBtnContainer { margin: var(--gap-24) auto var(--gap-0); } @media screen and (min-width: 360px) { - .forgotBtn { + .forgotBtnContainer { margin-top: var(--gap-32); + } + .forgotBtnContainer, + .forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-s-height); } @@ -22,7 +25,8 @@ } @media screen and (min-width: 390px) { - .forgotBtn { + .forgotBtnContainer, + .forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-m-height); } From aabaf60f7c8359730ea62e84b6a25adc78323106 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Wed, 8 Oct 2025 12:34:47 +0300 Subject: [PATCH 6/9] refactor(pattern-lock): button styles --- .../src/__snapshots__/component.test.tsx.snap | 2 +- .../base-pattern-lock/Component.tsx | 21 ++++++++++--------- .../base-pattern-lock/index.module.css | 7 ++++--- .../src/desktop/Component.desktop.tsx | 4 +--- .../src/desktop/desktop.module.css | 15 ------------- .../src/mobile/Component.mobile.tsx | 4 +--- .../pattern-lock/src/mobile/mobile.module.css | 11 ---------- packages/pattern-lock/src/typings.ts | 4 ---- 8 files changed, 18 insertions(+), 50 deletions(-) delete mode 100644 packages/pattern-lock/src/desktop/desktop.module.css delete mode 100644 packages/pattern-lock/src/mobile/mobile.module.css diff --git a/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap b/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap index 575242d8d9..bf276cc7fa 100644 --- a/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap +++ b/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap @@ -3,7 +3,7 @@ exports[`PatternLock test Snapshot tests should match snapshot 1`] = `
{showForgotCodeBtn && ( - - {forgotCodeBtnText} - +
+ + {forgotCodeBtnText} + +
)}
); diff --git a/packages/pattern-lock/src/components/base-pattern-lock/index.module.css b/packages/pattern-lock/src/components/base-pattern-lock/index.module.css index 8afcb3af9c..38ff009988 100644 --- a/packages/pattern-lock/src/components/base-pattern-lock/index.module.css +++ b/packages/pattern-lock/src/components/base-pattern-lock/index.module.css @@ -35,7 +35,8 @@ min-height: var(--pattern-lock-with-forgot-btn-min-height); } -.forgotBtn { - display: block; - min-height: var(--size-xs-height); +.forgotBtnContainer { + display: flex; + justify-content: center; + margin: var(--gap-8) auto var(--gap-0); } diff --git a/packages/pattern-lock/src/desktop/Component.desktop.tsx b/packages/pattern-lock/src/desktop/Component.desktop.tsx index be765912c1..880305a092 100644 --- a/packages/pattern-lock/src/desktop/Component.desktop.tsx +++ b/packages/pattern-lock/src/desktop/Component.desktop.tsx @@ -5,10 +5,8 @@ import { type TPatternLockInstance } from '@alfalab/react-canvas-pattern-lock'; import { BasePatternLock } from '../components/base-pattern-lock'; import { type CommonPatternLockProps } from '../typings'; -import styles from './desktop.module.css'; - export const PatternLockDesktop = forwardRef( - (restProps, ref) => , + (restProps, ref) => , ); PatternLockDesktop.displayName = 'PatternLockDesktop'; diff --git a/packages/pattern-lock/src/desktop/desktop.module.css b/packages/pattern-lock/src/desktop/desktop.module.css deleted file mode 100644 index 6c6b96266e..0000000000 --- a/packages/pattern-lock/src/desktop/desktop.module.css +++ /dev/null @@ -1,15 +0,0 @@ -@import '@alfalab/core-components-vars/src/no-typography-index.css'; -@import '../vars.css'; - -.component { - margin: var(--gap-0) auto; - min-width: var(--pattern-lock-min-width); -} - -.forgotBtn { - margin: var(--gap-8) auto var(--gap-0); -} - -.hiddenBtn { - display: none; -} diff --git a/packages/pattern-lock/src/mobile/Component.mobile.tsx b/packages/pattern-lock/src/mobile/Component.mobile.tsx index 98efd99c02..36735aab1d 100644 --- a/packages/pattern-lock/src/mobile/Component.mobile.tsx +++ b/packages/pattern-lock/src/mobile/Component.mobile.tsx @@ -5,10 +5,8 @@ import { type TPatternLockInstance } from '@alfalab/react-canvas-pattern-lock'; import { BasePatternLock } from '../components/base-pattern-lock'; import { type CommonPatternLockProps } from '../typings'; -import styles from './mobile.module.css'; - export const PatternLockMobile = forwardRef( - (restProps, ref) => , + (restProps, ref) => , ); PatternLockMobile.displayName = 'PatternLockMobile'; diff --git a/packages/pattern-lock/src/mobile/mobile.module.css b/packages/pattern-lock/src/mobile/mobile.module.css deleted file mode 100644 index 57d3ff2840..0000000000 --- a/packages/pattern-lock/src/mobile/mobile.module.css +++ /dev/null @@ -1,11 +0,0 @@ -@import '@alfalab/core-components-vars/src/no-typography-index.css'; -@import '../vars.css'; - -.component { - margin: var(--gap-0) auto; - min-width: var(--pattern-lock-min-width); -} - -.forgotBtn { - margin: var(--gap-8) auto var(--gap-0); -} diff --git a/packages/pattern-lock/src/typings.ts b/packages/pattern-lock/src/typings.ts index e17ec2e02b..e8d6b1d102 100644 --- a/packages/pattern-lock/src/typings.ts +++ b/packages/pattern-lock/src/typings.ts @@ -75,10 +75,6 @@ export type PrivatePatternLockProps = { * Включает ховер-эффект */ hover?: boolean; - /** - * Стили компонента - */ - styles: { [key: string]: string }; }; export type PatternLockProps = CommonPatternLockProps & { From 976274daedb16acadf949ef275e87ead17c0d172 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Sat, 28 Feb 2026 15:39:41 +0300 Subject: [PATCH 7/9] test: updated screenshots --- ...-lock-screenshots-default-with-forgot-code-button-snap.png | 4 ++-- .../tabs-text-style-prop-text-style-13-snap.png | 4 ++-- .../tabs-text-style-prop-text-style-2-snap.png | 4 ++-- .../tabs-text-style-prop-text-style-5-snap.png | 4 ++-- .../tabs-text-style-prop-text-style-8-snap.png | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png b/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png index 678ec1c6d2..dc230a1366 100644 --- a/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png +++ b/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a8cc30205a0fdb528b64a54dbbd964a50b854d6a090b50cea8d2386e56df0d0 -size 9019 +oid sha256:bc7add260dd67f0f0bc65e793dec0b4f5bc8d617ee1624f013d3cab03f07de79 +size 8754 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png index 08611e4447..e3478b185e 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c572698e7a2e6b6aeb77c40a9ca443c03e0931b5790e58a383bd02cb3094af18 -size 7987 +oid sha256:699e84b4e35ad13f7201dbc5f96010d60011b7c08c69a45e5a85b747ea152ee8 +size 8080 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png index 294994425a..b1f440a8dd 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9750825ae110dd40bde417cf16122bc38db622435a9513925873b1123ad7c325 -size 7351 +oid sha256:af7c24f6602e818ae138537b17ef602e8dd26971de8ddec945caa782aa013c9b +size 7369 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png index d66f0440fa..c82d9fc6cc 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac058c0ff04f565cd6208bd5ede546cbaea78c1f85d3bb508c3efbf6ad827c56 -size 7610 +oid sha256:cd1cb94c931408904930ae306883ef68861a3553993c4ede7e576b57ec7928b8 +size 7738 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png index a98d0227ee..d2efdd3305 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a4f1bf6046223e353ac71e2ab94df0d05c05d51d770f03317d24a65fc5f2250 -size 7824 +oid sha256:008ac7a1272a95c5c3dc345d30e81705d9ba1fb98911da94418ce0f004870c8a +size 7837 From 39f705eb18df57563b95038e4c246a8eb79b5b5c Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Tue, 3 Mar 2026 16:51:20 +0300 Subject: [PATCH 8/9] refactor(action-button): used BaseButtonCandidate --- packages/action-button/package.json | 3 +- .../src/Component.screenshots.test.tsx | 14 +- packages/action-button/src/Component.test.tsx | 77 +++++--- packages/action-button/src/Component.tsx | 175 ++++++------------ ...on-button-disabled-loading-sprite-snap.png | 4 +- packages/action-button/src/default.module.css | 84 +++++---- .../action-button/src/docs/description.mdx | 2 +- packages/action-button/src/index.module.css | 75 +++----- .../action-button/src/inverted.module.css | 84 +++++---- packages/action-button/src/static.module.css | 50 ++--- packages/action-button/tsconfig.build.json | 10 +- packages/action-button/tsconfig.json | 6 +- yarn.lock | 3 +- 13 files changed, 263 insertions(+), 324 deletions(-) diff --git a/packages/action-button/package.json b/packages/action-button/package.json index ebf3acf9f7..b3644f8c0c 100644 --- a/packages/action-button/package.json +++ b/packages/action-button/package.json @@ -10,9 +10,8 @@ "main": "index.js", "module": "./esm/index.js", "dependencies": { + "@alfalab/core-components-button": "^13.1.0", "@alfalab/core-components-shared": "^2.1.0", - "@alfalab/core-components-spinner": "^6.0.2", - "@alfalab/hooks": "^1.13.1", "classnames": "^2.5.1", "react-merge-refs": "^1.1.0", "tslib": "^2.4.0" diff --git a/packages/action-button/src/Component.screenshots.test.tsx b/packages/action-button/src/Component.screenshots.test.tsx index 94d9f070fe..5d7080deee 100644 --- a/packages/action-button/src/Component.screenshots.test.tsx +++ b/packages/action-button/src/Component.screenshots.test.tsx @@ -87,8 +87,10 @@ describe( }, }), screenshotOpts: { clip }, - evaluate: (page: Page) => - page.hover('button[class^=component]').then(() => page.waitForTimeout(500)), + evaluate: async (page) => { + await page.hover('button[class*=component]'); + await page.waitForTimeout(500); + }, matchImageSnapshotOptions: { customSnapshotIdentifier: (...args) => `hover-${customSnapshotIdentifier(...args)}`, }, @@ -106,10 +108,10 @@ describe( }, }), screenshotOpts: { clip }, - evaluate: (page: Page) => { - return page.mouse - .move(30, 30) - .then(() => page.mouse.down().then(() => page.waitForTimeout(500))); + evaluate: async (page) => { + await page.mouse.move(30, 30); + await page.mouse.down(); + await page.waitForTimeout(500); }, matchImageSnapshotOptions: { customSnapshotIdentifier: (...args) => `pressed-${customSnapshotIdentifier(...args)}`, diff --git a/packages/action-button/src/Component.test.tsx b/packages/action-button/src/Component.test.tsx index 14d86bbb1f..9ebe913bc3 100644 --- a/packages/action-button/src/Component.test.tsx +++ b/packages/action-button/src/Component.test.tsx @@ -20,20 +20,16 @@ describe('ActionButton', () => { it('should use "size" prop', () => { const size = 48; - render(); + render(); - expect(screen.getByRole('button')).toHaveClass('size-48'); - }); - - it('should use "size" prop "s" by default', () => { - render(); - - expect(screen.getByRole('button')).toHaveClass('size-48'); + expect(screen.getByRole('button')).toHaveClass('size48'); }); it('should use "iconWrapperClassName" prop', () => { const iconClassName = 'test-class'; - const { container } = render(); + const { container } = render( + , + ); expect(container.querySelector(`.${iconClassName}`)).toBeInTheDocument(); }); @@ -41,57 +37,65 @@ describe('ActionButton', () => { it('should use "href" prop and become a link', () => { const href = 'http://127.0.0.1'; - render(); + render(); - expect(screen.getByRole('button')).toHaveAttribute('href', href); + expect(screen.getByTestId(dti)).toHaveAttribute('href', href); }); it('should use "disabled" prop (button)', () => { - const { rerender } = render(); + const { rerender } = render(); expect(screen.getByRole('button')).not.toBeDisabled(); - rerender(); + rerender(); expect(screen.getByRole('button')).toBeDisabled(); }); it('should use "disabled" prop (link)', () => { - const { rerender } = render(); + const { rerender } = render( + , + ); - expect(screen.getByRole('button')).not.toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).not.toHaveAttribute('aria-disabled', 'true'); - rerender(); + rerender( + , + ); - expect(screen.getByRole('button')).toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).toHaveAttribute('aria-disabled', 'true'); }); it('should use "loading" prop (button)', () => { - const { rerender } = render(); + const { rerender } = render(); expect(screen.getByRole('button')).not.toBeDisabled(); expect(screen.queryByTestId(loaderDti)).toBeNull(); - rerender(); + rerender(); expect(screen.getByRole('button')).toBeDisabled(); expect(screen.getByTestId(loaderDti)).toBeInTheDocument(); }); it('should use "loading" prop (link)', () => { - const { rerender } = render(); + const { rerender } = render( + , + ); - expect(screen.getByRole('button')).not.toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).not.toHaveAttribute('aria-disabled', 'true'); expect(screen.queryByTestId(loaderDti)).toBeNull(); - rerender(); + rerender( + , + ); - expect(screen.getByRole('button')).toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).toHaveAttribute('aria-disabled', 'true'); expect(screen.getByTestId(loaderDti)).toBeInTheDocument(); }); it('should use "dataTestId" prop', () => { - render(); + render(); expect(screen.getByRole('button')).toHaveAttribute('data-test-id', dti); }); @@ -99,7 +103,7 @@ describe('ActionButton', () => { it('should use "children" prop', () => { const label = 'Action Button'; - render({label}); + render({label}); expect(screen.getByRole('button')).toHaveTextContent(label); }); @@ -107,7 +111,7 @@ describe('ActionButton', () => { it('should use "className" prop', () => { const className = 'test-class'; - render(); + render(); expect(screen.getByRole('button')).toHaveClass(className); }); @@ -115,7 +119,7 @@ describe('ActionButton', () => { it('should call "onClick" prop', async () => { const cb = jest.fn(); - render(); + render(); await userEvent.click(screen.getByRole('button')); @@ -124,11 +128,28 @@ describe('ActionButton', () => { it('should have data-test-id', () => { const dti = 'action-button-dti'; - const { getByTestId } = render(); + const { getByTestId } = render(); const testIds = getActionButtonTestIds(dti); expect(getByTestId(testIds.actionButton)).toBeInTheDocument(); expect(getByTestId(testIds.spinner)).toBeInTheDocument(); }); + + it('should pass "loaderClassName"', () => { + const dti = 'action-button-dti'; + const loaderClassName = 'foo'; + const { getByTestId } = render( + , + ); + + const testIds = getActionButtonTestIds(dti); + + expect(getByTestId(testIds.spinner)).toHaveClass(loaderClassName); + }); }); diff --git a/packages/action-button/src/Component.tsx b/packages/action-button/src/Component.tsx index 4bce3faceb..623e0dd918 100644 --- a/packages/action-button/src/Component.tsx +++ b/packages/action-button/src/Component.tsx @@ -1,19 +1,14 @@ -import React, { - type AnchorHTMLAttributes, - type ButtonHTMLAttributes, - forwardRef, - Fragment, - useRef, -} from 'react'; +import React, { forwardRef, type ReactNode } from 'react'; import mergeRefs from 'react-merge-refs'; import cn from 'classnames'; -import { getDataTestId } from '@alfalab/core-components-shared'; -import { Spinner } from '@alfalab/core-components-spinner'; -import { useFocus } from '@alfalab/hooks'; - -import { LOADER_MIN_DISPLAY_INTERVAL } from './constants/loader-min-display-interval'; -import { useLoader } from './hooks'; +import { + BaseButtonCandidate, + type BaseButtonOwnProps, + type ButtonPropsFactory, +} from '@alfalab/core-components-button/components/base-button-candidate'; +import { ButtonContent } from '@alfalab/core-components-button/components/button-content'; +import { useLoading } from '@alfalab/core-components-button/shared'; import defaultColors from './default.module.css'; import styles from './index.module.css'; @@ -24,15 +19,14 @@ const colorStyles = { default: defaultColors, inverted: invertedColors, static: staticColors, -}; - -type Colors = 'default' | 'inverted' | 'static'; +} as const; -type ComponentProps = { +interface ComponentProps + extends Omit { /** * Иконка кнопки */ - icon: React.ReactNode; + icon: ReactNode; /** * Размер кнопки @@ -44,142 +38,79 @@ type ComponentProps = { */ view?: 'primary' | 'secondary'; - /** - * Дополнительный класс - */ - className?: string; - /** * Дополнительный класс для обертки иконки */ iconWrapperClassName?: string; - /** - * Значение href для ссылки - */ - href?: string; - - /** - * Заблокировать кнопку - */ - disabled?: boolean; - - /** - * Показать лоадер - */ - loading?: boolean; - - /** - * Идентификатор для систем автоматизированного тестирования. - * Для спиннера используется модификатор -loader - */ - dataTestId?: string; - /** * Палитра, в контексте которой используется кнопка */ - colors?: Colors; -}; + colors?: 'default' | 'inverted' | 'static'; +} -type AnchorProps = ComponentProps & AnchorHTMLAttributes; -type ButtonProps = ComponentProps & ButtonHTMLAttributes; -export type ActionButtonProps = Partial; +export type ActionButtonProps = ButtonPropsFactory; export const ActionButton = forwardRef( ( { - className, + className: classNameFromProps, icon, children, - href, size = 48, view = 'primary', - type = 'button', iconWrapperClassName, disabled, - loading, - dataTestId, + loading: loadingFromProps, colors = 'default', - ...rest + dataTestId, + loaderClassName, + ...restProps }, ref, ) => { - const componentRef = useRef(null); - - const [focused] = useFocus(componentRef, 'keyboard'); - - const { showLoader } = useLoader(!!loading, LOADER_MIN_DISPLAY_INTERVAL); - - const styleSize = `size-${size}`; - - const componentProps = { - className: cn( - styles.component, - colorStyles[colors][view], - styles[styleSize], - { - [styles.focused]: focused, - [styles.disabled]: disabled, - [colorStyles[colors].disabled]: disabled, - [styles.loading]: showLoader, - }, - className, - ), - 'data-test-id': dataTestId, - }; + const loading = useLoading(loadingFromProps); + const className = cn( + styles.component, + colorStyles[colors].component, + colorStyles[colors][view], + styles[`size${size}`], + loading && [colorStyles[colors].loading, styles.loading], + classNameFromProps, + ); - const buttonChildren = ( - - +
- {showLoader ? ( - - ) : ( - icon - )} - + + {icon} + +
{children} -
- ); - - if (href) { - return ( - )} - > - {buttonChildren} - - ); - } - - return ( - + ); }, ); diff --git a/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png b/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png index 8b7f8858d5..7d012b7441 100644 --- a/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png +++ b/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48ee688b03ea661724b4b1a80dd1a2a0b2fda4bf6b42e31857dc79c167537bd -size 23117 +oid sha256:9c2b984531f5d9128efe25f6231c9e3c28cdec3691c19ad4778237fb0db00015 +size 22921 diff --git a/packages/action-button/src/default.module.css b/packages/action-button/src/default.module.css index 1180709089..01623ce266 100644 --- a/packages/action-button/src/default.module.css +++ b/packages/action-button/src/default.module.css @@ -25,57 +25,65 @@ --action-button-disabled-bg-color: var(--color-light-neutral-100); } -.primary { - color: var(--action-button-primary-base-color); +.component { + &.primary { + color: var(--action-button-primary-base-color); - & .iconWrapper { - color: var(--action-button-primary-base-icon-color); - background-color: var(--action-button-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-primary-base-icon-color); + background-color: var(--action-button-primary-base-bg-color); + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-primary-hover-color); + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-primary-hover-color); + } + } + + &:active .iconWrapper { + background-color: var(--action-button-primary-active-color); + } } - } - &:active .iconWrapper { - background-color: var(--action-button-primary-active-color); + .loader { + color: var(--action-button-spinner-primary-color); + } } - & .loader { - color: var(--action-button-spinner-primary-color); - } -} + &.secondary { + color: var(--action-button-secondary-base-color); -.secondary { - color: var(--action-button-secondary-base-color); + .iconWrapper { + color: var(--action-button-secondary-base-icon-color); + background-color: var(--action-button-secondary-base-bg-color); + } - & .iconWrapper { - color: var(--action-button-secondary-base-icon-color); - background-color: var(--action-button-secondary-base-bg-color); - } + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-secondary-hover-color); + } + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-secondary-hover-color); + &:active .iconWrapper { + background-color: var(--action-button-secondary-active-color); + } } - } - - &:active .iconWrapper { - background-color: var(--action-button-secondary-active-color); - } - & .loader { - color: var(--action-button-spinner-default-color); + .loader { + color: var(--action-button-spinner-default-color); + } } -} -.disabled { - color: var(--action-button-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-disabled-color); - & .iconWrapper { - color: var(--action-button-disabled-icon-color); - background-color: var(--action-button-disabled-bg-color); + .iconWrapper { + color: var(--action-button-disabled-icon-color); + background-color: var(--action-button-disabled-bg-color); + } + } } } diff --git a/packages/action-button/src/docs/description.mdx b/packages/action-button/src/docs/description.mdx index 2314427a33..97afd239d0 100644 --- a/packages/action-button/src/docs/description.mdx +++ b/packages/action-button/src/docs/description.mdx @@ -29,7 +29,7 @@ render(() => { Лейбл кнопки ограничен двумя строками. ```jsx live - } view='primary'> + } view='primary'> Пример переноса текста ``` diff --git a/packages/action-button/src/index.module.css b/packages/action-button/src/index.module.css index 6415dfe952..6b1493cc3e 100644 --- a/packages/action-button/src/index.module.css +++ b/packages/action-button/src/index.module.css @@ -1,77 +1,44 @@ @import '@alfalab/core-components-vars/src/no-typography-index.css'; .component { - position: relative; - display: inline-flex; - flex-flow: column nowrap; - align-items: center; - vertical-align: top; + flex-direction: column; + flex-wrap: nowrap; width: 80px; min-height: 80px; max-height: 100px; - padding: var(--gap-0); - margin: var(--gap-0); - background: none; - border: none; - cursor: pointer; - outline: none; - text-align: center; - text-decoration: none; - text-transform: none; - transition: - color 0.2s ease, - opacity 0.2s ease; - user-select: none; - font-family: inherit; - appearance: none; - -webkit-tap-highlight-color: transparent; - - &.size-48 { - @mixin action_primary_small; + transition: color 0.2s ease; + + /* prettier-ignore */ + @each $size, $mixin in (48, action_primary_small) { + &.size$(size) { + @mixin $(mixin); + + .iconWrapper { + width: $(size)px; + height: $(size)px; + } + } } } -.disabled { - cursor: not-allowed; - pointer-events: none; -} - -.loading { - cursor: auto; - pointer-events: none; -} - .iconWrapper { + position: relative; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-bottom: var(--gap-12); border-radius: var(--border-radius-circle); - transition: background-color 0.2s ease; + transition: + opacity 0.2s ease, + background 0.2s ease; line-height: 0; - &.size-48 { - width: 48px; - height: 48px; + .loading & > *:not(.loader) { + opacity: 0; } } .label { - display: -webkit-box; - overflow: hidden; - text-overflow: ellipsis; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -} - -.loader { - position: absolute; - left: var(--gap-0); - right: var(--gap-0); - margin: var(--gap-0) auto; -} - -.focused { - @mixin focus-outline; + @mixin row_limit 2; } diff --git a/packages/action-button/src/inverted.module.css b/packages/action-button/src/inverted.module.css index 95c703a389..55e83737a5 100644 --- a/packages/action-button/src/inverted.module.css +++ b/packages/action-button/src/inverted.module.css @@ -33,57 +33,65 @@ --action-button-inverted-disabled-bg-color: var(--color-light-neutral-100-inverted); } -.primary { - color: var(--action-button-inverted-primary-base-color); +.component { + &.primary { + color: var(--action-button-inverted-primary-base-color); - & .iconWrapper { - color: var(--action-button-inverted-primary-base-icon-color); - background-color: var(--action-button-inverted-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-inverted-primary-base-icon-color); + background-color: var(--action-button-inverted-primary-base-bg-color); + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-inverted-primary-hover-color); + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-inverted-primary-hover-color); + } + } + + &:active .iconWrapper { + background-color: var(--action-button-inverted-primary-active-color); + } } - } - &:active .iconWrapper { - background-color: var(--action-button-inverted-primary-active-color); + .loader { + color: var(--action-button-spinner-inverted-primary-color); + } } - & .loader { - color: var(--action-button-spinner-inverted-primary-color); - } -} + &.secondary { + color: var(--action-button-inverted-secondary-base-color); -.secondary { - color: var(--action-button-inverted-secondary-base-color); + .iconWrapper { + color: var(--action-button-inverted-secondary-base-icon-color); + background-color: var(--action-button-inverted-secondary-base-bg-color); + } - & .iconWrapper { - color: var(--action-button-inverted-secondary-base-icon-color); - background-color: var(--action-button-inverted-secondary-base-bg-color); - } + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-inverted-secondary-hover-color); + } + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-inverted-secondary-hover-color); + &:active .iconWrapper { + background-color: var(--action-button-inverted-secondary-active-color); + } } - } - - &:active .iconWrapper { - background-color: var(--action-button-inverted-secondary-active-color); - } - & .loader { - color: var(--action-button-spinner-inverted-default-color); + .loader { + color: var(--action-button-spinner-inverted-default-color); + } } -} -.disabled { - color: var(--action-button-inverted-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-inverted-disabled-color); - & .iconWrapper { - color: var(--action-button-inverted-disabled-icon-color); - background-color: var(--action-button-inverted-disabled-bg-color); + .iconWrapper { + color: var(--action-button-inverted-disabled-icon-color); + background-color: var(--action-button-inverted-disabled-bg-color); + } + } } } diff --git a/packages/action-button/src/static.module.css b/packages/action-button/src/static.module.css index 9936c2819f..2432e4e721 100644 --- a/packages/action-button/src/static.module.css +++ b/packages/action-button/src/static.module.css @@ -25,37 +25,41 @@ --action-button-static-disabled-bg-color: var(--color-static-neutral-100); } -.primary { - color: var(--action-button-static-primary-base-color); +.component { + &.primary { + color: var(--action-button-static-primary-base-color); - & .iconWrapper { - color: var(--action-button-static-primary-base-icon-color); - background-color: var(--action-button-static-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-static-primary-base-icon-color); + background-color: var(--action-button-static-primary-base-bg-color); + } - & .loader { - color: var(--action-button-spinner-static-primary-color); + .loader { + color: var(--action-button-spinner-static-primary-color); + } } -} -.secondary { - color: var(--action-button-static-secondary-base-color); + &.secondary { + color: var(--action-button-static-secondary-base-color); - & .iconWrapper { - color: var(--action-button-static-secondary-base-icon-color); - background-color: var(--action-button-static-secondary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-static-secondary-base-icon-color); + background-color: var(--action-button-static-secondary-base-bg-color); + } - & .loader { - color: var(--action-button-spinner-static-secondary-color); + .loader { + color: var(--action-button-spinner-static-secondary-color); + } } -} -.disabled { - color: var(--action-button-static-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-static-disabled-color); - & .iconWrapper { - color: var(--action-button-static-disabled-icon-color); - background-color: var(--action-button-static-disabled-bg-color); + .iconWrapper { + color: var(--action-button-static-disabled-icon-color); + background-color: var(--action-button-static-disabled-bg-color); + } + } } } diff --git a/packages/action-button/tsconfig.build.json b/packages/action-button/tsconfig.build.json index d90f28397c..1c107e5ddd 100644 --- a/packages/action-button/tsconfig.build.json +++ b/packages/action-button/tsconfig.build.json @@ -9,14 +9,14 @@ "paths": { "@alfalab/core-components-action-button": ["./src"], "@alfalab/core-components-action-button/*": ["./src/*"], + "@alfalab/core-components-button": ["../button/src"], + "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-shared": ["../shared/src"], - "@alfalab/core-components-shared/*": ["../shared/src/*"], - "@alfalab/core-components-spinner": ["../spinner/src"], - "@alfalab/core-components-spinner/*": ["../spinner/src/*"] + "@alfalab/core-components-shared/*": ["../shared/src/*"] } }, "references": [ - { "path": "../shared/tsconfig.build.json" }, - { "path": "../spinner/tsconfig.build.json" } + { "path": "../button/tsconfig.build.json" }, + { "path": "../shared/tsconfig.build.json" } ] } diff --git a/packages/action-button/tsconfig.json b/packages/action-button/tsconfig.json index d35aee6188..e4ad5083c7 100644 --- a/packages/action-button/tsconfig.json +++ b/packages/action-button/tsconfig.json @@ -8,20 +8,20 @@ "paths": { "@alfalab/core-components-action-button": ["./src"], "@alfalab/core-components-action-button/*": ["./src/*"], + "@alfalab/core-components-button": ["../button/src"], + "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-screenshot-utils": ["../screenshot-utils/src"], "@alfalab/core-components-screenshot-utils/*": ["../screenshot-utils/src/*"], "@alfalab/core-components-shared": ["../shared/src"], "@alfalab/core-components-shared/*": ["../shared/src/*"], - "@alfalab/core-components-spinner": ["../spinner/src"], - "@alfalab/core-components-spinner/*": ["../spinner/src/*"], "@alfalab/core-components-test-utils": ["../test-utils/src"], "@alfalab/core-components-test-utils/*": ["../test-utils/src/*"] } }, "references": [ + { "path": "../button/tsconfig.build.json" }, { "path": "../screenshot-utils/tsconfig.build.json" }, { "path": "../shared/tsconfig.build.json" }, - { "path": "../spinner/tsconfig.build.json" }, { "path": "../test-utils/tsconfig.build.json" } ] } diff --git a/yarn.lock b/yarn.lock index 9366a23fc0..ee28fc585d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -110,9 +110,8 @@ __metadata: version: 0.0.0-use.local resolution: "@alfalab/core-components-action-button@workspace:packages/action-button" dependencies: + "@alfalab/core-components-button": "npm:^13.1.0" "@alfalab/core-components-shared": "npm:^2.1.0" - "@alfalab/core-components-spinner": "npm:^6.0.2" - "@alfalab/hooks": "npm:^1.13.1" classnames: "npm:^2.5.1" react-merge-refs: "npm:^1.1.0" tslib: "npm:^2.4.0" From 77f6501ffe33f7b3da02df52cc08256a51c90942 Mon Sep 17 00:00:00 2001 From: hextion <100ishundred@gmail.com> Date: Thu, 5 Mar 2026 11:55:26 +0300 Subject: [PATCH 9/9] refactor(custom-button): used ButtonLayout --- .../src/__snapshots__/Component.test.tsx.snap | 2 +- .../src/__snapshots__/Component.test.tsx.snap | 36 +- .../src/components/base-button/Component.tsx | 96 +--- .../components/base-button/index.module.css | 107 ---- .../components/button-layout/component.tsx | 90 ++++ .../components/button-layout/index.module.css | 109 ++++ .../src/components/button-layout/index.ts | 1 + packages/button/src/constants/const.ts | 3 + packages/button/src/typings.ts | 32 +- .../src/__snapshots__/Component.test.tsx.snap | 122 ++--- .../src/__snapshots__/Component.test.tsx.snap | 64 +-- .../src/__snapshots__/Component.test.tsx.snap | 474 +++++++++--------- .../src/__snapshots__/Component.test.tsx.snap | 2 +- .../src/__snapshots__/Component.test.tsx.snap | 6 +- packages/custom-button/package.json | 1 + packages/custom-button/src/Component.test.tsx | 6 +- packages/custom-button/src/Component.tsx | 32 +- ...or-1-content-color-0-state-type-0-snap.png | 4 +- ...or-0-content-color-0-state-type-0-snap.png | 4 +- ...or-0-content-color-1-state-type-1-snap.png | 4 +- ...or-1-content-color-0-state-type-0-snap.png | 4 +- ...or-1-content-color-1-state-type-1-snap.png | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 90 ++-- .../base-custom-button/base-custom-button.tsx | 72 +-- .../base-custom-button/index.module.css | 162 ++---- .../src/desktop/Component.desktop.tsx | 10 +- .../src/desktop/index.module.css | 16 + .../src/mobile/Component.mobile.tsx | 10 +- .../custom-button/src/mobile/index.module.css | 16 + packages/custom-button/src/types/props.ts | 33 +- packages/custom-button/tsconfig.build.json | 9 +- packages/custom-button/tsconfig.json | 3 + .../src/Component.test.tsx | 5 +- .../src/__snapshots__/Component.test.tsx.snap | 36 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- .../src/__snapshots__/Component.test.tsx.snap | 2 +- .../src/__snapshots__/Component.test.tsx.snap | 14 +- .../src/__snapshots__/Component.test.tsx.snap | 4 +- yarn.lock | 1 + 40 files changed, 883 insertions(+), 811 deletions(-) create mode 100644 packages/button/src/components/button-layout/component.tsx create mode 100644 packages/button/src/components/button-layout/index.module.css create mode 100644 packages/button/src/components/button-layout/index.ts create mode 100644 packages/button/src/constants/const.ts create mode 100644 packages/custom-button/src/desktop/index.module.css create mode 100644 packages/custom-button/src/mobile/index.module.css diff --git a/packages/attach/src/__snapshots__/Component.test.tsx.snap b/packages/attach/src/__snapshots__/Component.test.tsx.snap index beeae5e8c4..a5234bedee 100644 --- a/packages/attach/src/__snapshots__/Component.test.tsx.snap +++ b/packages/attach/src/__snapshots__/Component.test.tsx.snap @@ -6,7 +6,7 @@ exports[`Attach Snapshots tests should match snapshot 1`] = ` class="component size-48" >
, "container":
, @@ -78,7 +78,7 @@ exports[`Button Snapshots tests should render anchor if href pass 1`] = ` @@ -86,7 +86,7 @@ exports[`Button Snapshots tests should render anchor if href pass 1`] = ` "container": , @@ -150,14 +150,14 @@ exports[`Button Snapshots tests should render button by default 1`] = ` "baseElement":
, "container":
, @@ -221,7 +221,7 @@ exports[`Button Snapshots tests should render left addons 1`] = ` "baseElement":