From 5cfdfd5bbb83f83d457dc458bee9fd5490ec40c1 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sat, 18 Jan 2025 16:37:06 +0300 Subject: [PATCH 1/7] feat(DateInput): add placeholder prop --- .../DateInput/DateInput.e2e-playground.tsx | 4 + .../components/DateInput/DateInput.module.css | 35 ++++- .../components/DateInput/DateInput.test.tsx | 42 +++++ .../src/components/DateInput/DateInput.tsx | 147 ++++++++++-------- .../vkui/src/components/DateInput/Readme.md | 9 ++ ...dateinput-android-chromium-dark-1-snap.png | 4 +- ...ateinput-android-chromium-light-1-snap.png | 4 +- .../dateinput-ios-webkit-dark-1-snap.png | 4 +- .../dateinput-ios-webkit-light-1-snap.png | 4 +- .../dateinput-vkcom-chromium-dark-1-snap.png | 4 +- .../dateinput-vkcom-chromium-light-1-snap.png | 4 +- .../dateinput-vkcom-firefox-dark-1-snap.png | 4 +- .../dateinput-vkcom-firefox-light-1-snap.png | 4 +- .../dateinput-vkcom-webkit-dark-1-snap.png | 4 +- .../dateinput-vkcom-webkit-light-1-snap.png | 4 +- 15 files changed, 189 insertions(+), 88 deletions(-) diff --git a/packages/vkui/src/components/DateInput/DateInput.e2e-playground.tsx b/packages/vkui/src/components/DateInput/DateInput.e2e-playground.tsx index 9d4cfb18ec..123ae6b79d 100644 --- a/packages/vkui/src/components/DateInput/DateInput.e2e-playground.tsx +++ b/packages/vkui/src/components/DateInput/DateInput.e2e-playground.tsx @@ -13,6 +13,10 @@ export const DateInputPlayground = (props: ComponentPlaygroundProps) => { { status: ['error', 'valid'], }, + { + value: [new Date('1970-05-05'), undefined], + placeholder: ['Placeholder'], + }, ]} > {(props: DateInputProps) => } diff --git a/packages/vkui/src/components/DateInput/DateInput.module.css b/packages/vkui/src/components/DateInput/DateInput.module.css index bca9b30130..88a5fc376f 100644 --- a/packages/vkui/src/components/DateInput/DateInput.module.css +++ b/packages/vkui/src/components/DateInput/DateInput.module.css @@ -1,8 +1,20 @@ +.wrapper { + display: flex; + min-height: inherit; + min-width: inherit; + position: relative; + flex-grow: 1; + + --vkui_internal--DateInput_input_margin_inline_start: 10px; + --vkui_internal--DateInput_input_margin_inline_end: 14px; +} + .input { display: block; flex-grow: 1; align-self: center; - margin-inline: 10px 14px; + margin-inline: var(--vkui_internal--DateInput_input_margin_inline_start) + var(--vkui_internal--DateInput_input_margin_inline_end); z-index: var(--vkui_internal--z_index_form_field_element); cursor: text; white-space: nowrap; @@ -10,6 +22,25 @@ font-variant-numeric: tabular-nums; } +.hidden { + opacity: 0; +} + +.placeholder { + position: absolute; + margin-inline: var(--vkui_internal--DateInput_input_margin_inline_start) var(--vkui_internal--DateInput_input_margin_inline_end); + width: calc(100% - var(--vkui_internal--DateInput_input_margin_inline_start) - var(--vkui_internal--DateInput_input_margin_inline_end)); + align-self: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + box-sizing: border-box; + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + .inputTimeDivider { /* stylelint-disable-next-line declaration-no-important */ letter-spacing: 6px !important; @@ -21,6 +52,6 @@ @media (--sizeY-compact) { .sizeYNone .input { - margin-inline-end: 22px; + --vkui_internal--DateInput_input_margin_inline_end: 22px } } diff --git a/packages/vkui/src/components/DateInput/DateInput.test.tsx b/packages/vkui/src/components/DateInput/DateInput.test.tsx index c920c5c560..d0be9e5935 100644 --- a/packages/vkui/src/components/DateInput/DateInput.test.tsx +++ b/packages/vkui/src/components/DateInput/DateInput.test.tsx @@ -1,6 +1,9 @@ +import { useState } from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; +import { noop } from '@vkontakte/vkjs'; import { format, subDays } from 'date-fns'; import { baselineComponent, userEvent } from '../../testing/utils'; +import { Button } from '../Button/Button'; import { DateInput, type DateInputPropsTestsProps } from './DateInput'; const date = new Date(2024, 6, 31, 11, 20, 0, 0); @@ -261,4 +264,43 @@ describe('DateInput', () => { expect(onChange).not.toHaveBeenCalled(); }); + + it('check placeholder visibility', async () => { + const PLACEHOLDER_TEXT = 'Плейсхолдер'; + const Fixture = () => { + const [showValue, setShowValue] = useState(false); + return ( + <> + + + + ); + }; + + render(); + expect(screen.queryByPlaceholderText(PLACEHOLDER_TEXT)).toBeTruthy(); + expect(screen.queryByText(PLACEHOLDER_TEXT)).toBeTruthy(); + + // Добавляем значение в input - placeholder появляется + fireEvent.click(screen.getByTestId('add-date')); + expect(screen.queryByText(PLACEHOLDER_TEXT)).toBeFalsy(); + + // Убираем значение из input - placeholder исчезает + fireEvent.click(screen.getByTestId('add-date')); + expect(screen.queryByText(PLACEHOLDER_TEXT)).toBeTruthy(); + + // Ставим фокус в input - placeholder повляется + const inputLikes = getInputsLike(); + const [dates] = inputLikes; + await userEvent.click(dates); + + expect(screen.queryByText(PLACEHOLDER_TEXT)).toBeFalsy(); + }); }); diff --git a/packages/vkui/src/components/DateInput/DateInput.tsx b/packages/vkui/src/components/DateInput/DateInput.tsx index 8ebbb5c289..26a5d5c03f 100644 --- a/packages/vkui/src/components/DateInput/DateInput.tsx +++ b/packages/vkui/src/components/DateInput/DateInput.tsx @@ -101,6 +101,10 @@ export interface DateInputProps * Колбэк срабатывающий при нажатии на кнопку "Done". Используется совместно с флагом `enableTime`. */ onApply?: (value?: Date) => void; + /** + * Текст, который будет отображаться в пустом поле ввода + */ + placeholder?: string; } const elementsConfig = (index: number) => { @@ -196,6 +200,7 @@ export const DateInput = ({ minuteFieldTestId, id, onApply, + placeholder, ...props }: DateInputProps): React.ReactNode => { const daysRef = React.useRef(null); @@ -301,6 +306,8 @@ export const DateInput = ({ removeFocusFromField(); }, [onApply, onChange, removeFocusFromField, value]); + const showPlaceholder = !open && !value && !!placeholder; + return ( - - нормализация не нужна - > - - . - - . - + - {enableTime && ( - - - - : - - + нормализация не нужна + > + + . + + . + + {enableTime && ( + + + + : + + + )} + + {showPlaceholder && ( + + {placeholder} + )} - + {open && !disableCalendar && ( { const [closeOnChange, setCloseOnChange] = useState(true); const [showNeighboringMonth, setShowNeighboringMonth] = useState(false); const [disableCalendar, setDisableCalendar] = useState(false); + const [placeholder, setPlaceholder] = useState(''); const [locale, setLocale] = useState('ru'); return ( @@ -57,6 +58,13 @@ const Example = () => { Включено + + setPlaceholder(e.target.value)} + style={{ maxWidth: 300 }} + /> + setPlaceholder(e.target.value)} - style={{ maxWidth: 300 }} - /> -