From dfaf9db97a35b5043f14179db6aa130dc94e9374 Mon Sep 17 00:00:00 2001 From: Shaneeza Date: Wed, 10 Sep 2025 17:04:08 -0400 Subject: [PATCH 1/7] feat(time-input): add Time Input component with styles, WIP --- packages/time-input/README.md | 26 ++++ packages/time-input/package.json | 54 +++++++ packages/time-input/src/TimeInput.stories.tsx | 19 +++ .../src/TimeInput/TimeInput.spec.tsx | 11 ++ .../src/TimeInput/TimeInput.styles.ts | 48 ++++++ .../time-input/src/TimeInput/TimeInput.tsx | 24 +++ .../src/TimeInput/TimeInput.types.ts | 66 ++++++++ packages/time-input/src/TimeInput/index.ts | 3 + .../TimeInputContent.spec.tsx | 11 ++ .../TimeInputContent.styles.ts | 48 ++++++ .../src/TimeInputContent/TimeInputContent.tsx | 96 ++++++++++++ .../TimeInputContent.types.ts | 5 + .../time-input/src/TimeInputContent/index.ts | 3 + .../TimeInputInput/TimeInputInput.spec.tsx | 8 + .../TimeInputInput/TimeInputInput.styles.ts | 142 ++++++++++++++++++ .../src/TimeInputInput/TimeInputInput.tsx | 36 +++++ .../TimeInputInput/TimeInputInput.types.ts | 3 + .../time-input/src/TimeInputInput/index.ts | 2 + .../TimeInputSelect/TimeInputSelect.spec.tsx | 8 + .../TimeInputSelect/TimeInputSelect.styles.ts | 35 +++++ .../src/TimeInputSelect/TimeInputSelect.tsx | 79 ++++++++++ .../TimeInputSelect/TimeInputSelect.types.ts | 28 ++++ .../time-input/src/TimeInputSelect/index.ts | 2 + packages/time-input/src/index.ts | 1 + packages/time-input/src/shared/constants.ts | 4 + .../src/testing/getTestUtils.spec.tsx | 8 + .../time-input/src/testing/getTestUtils.tsx | 15 ++ .../src/testing/getTestUtils.types.ts | 1 + packages/time-input/src/testing/index.ts | 2 + packages/time-input/src/utils/getLgIds.ts | 12 ++ packages/time-input/tsconfig.json | 55 +++++++ 31 files changed, 855 insertions(+) create mode 100644 packages/time-input/README.md create mode 100644 packages/time-input/package.json create mode 100644 packages/time-input/src/TimeInput.stories.tsx create mode 100644 packages/time-input/src/TimeInput/TimeInput.spec.tsx create mode 100644 packages/time-input/src/TimeInput/TimeInput.styles.ts create mode 100644 packages/time-input/src/TimeInput/TimeInput.tsx create mode 100644 packages/time-input/src/TimeInput/TimeInput.types.ts create mode 100644 packages/time-input/src/TimeInput/index.ts create mode 100644 packages/time-input/src/TimeInputContent/TimeInputContent.spec.tsx create mode 100644 packages/time-input/src/TimeInputContent/TimeInputContent.styles.ts create mode 100644 packages/time-input/src/TimeInputContent/TimeInputContent.tsx create mode 100644 packages/time-input/src/TimeInputContent/TimeInputContent.types.ts create mode 100644 packages/time-input/src/TimeInputContent/index.ts create mode 100644 packages/time-input/src/TimeInputInput/TimeInputInput.spec.tsx create mode 100644 packages/time-input/src/TimeInputInput/TimeInputInput.styles.ts create mode 100644 packages/time-input/src/TimeInputInput/TimeInputInput.tsx create mode 100644 packages/time-input/src/TimeInputInput/TimeInputInput.types.ts create mode 100644 packages/time-input/src/TimeInputInput/index.ts create mode 100644 packages/time-input/src/TimeInputSelect/TimeInputSelect.spec.tsx create mode 100644 packages/time-input/src/TimeInputSelect/TimeInputSelect.styles.ts create mode 100644 packages/time-input/src/TimeInputSelect/TimeInputSelect.tsx create mode 100644 packages/time-input/src/TimeInputSelect/TimeInputSelect.types.ts create mode 100644 packages/time-input/src/TimeInputSelect/index.ts create mode 100644 packages/time-input/src/index.ts create mode 100644 packages/time-input/src/shared/constants.ts create mode 100644 packages/time-input/src/testing/getTestUtils.spec.tsx create mode 100644 packages/time-input/src/testing/getTestUtils.tsx create mode 100644 packages/time-input/src/testing/getTestUtils.types.ts create mode 100644 packages/time-input/src/testing/index.ts create mode 100644 packages/time-input/src/utils/getLgIds.ts create mode 100644 packages/time-input/tsconfig.json diff --git a/packages/time-input/README.md b/packages/time-input/README.md new file mode 100644 index 0000000000..f3946f2b0a --- /dev/null +++ b/packages/time-input/README.md @@ -0,0 +1,26 @@ + +# Time Input + +![npm (scoped)](https://img.shields.io/npm/v/@leafygreen-ui/time-input.svg) +#### [View on MongoDB.design](https://www.mongodb.design/component/time-input/live-example/) + +## Installation + +### PNPM + +```shell +pnpm add @leafygreen-ui/time-input +``` + +### Yarn + +```shell +yarn add @leafygreen-ui/time-input +``` + +### NPM + +```shell +npm install @leafygreen-ui/time-input +``` + diff --git a/packages/time-input/package.json b/packages/time-input/package.json new file mode 100644 index 0000000000..9a40d10bb9 --- /dev/null +++ b/packages/time-input/package.json @@ -0,0 +1,54 @@ + +{ + "name": "@leafygreen-ui/time-input", + "version": "0.1.0", + "description": "LeafyGreen UI Kit Time Input", + "main": "./dist/umd/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/types/index.d.ts", + "license": "Apache-2.0", + "exports": { + ".": { + "types": "./dist/types/index.d.ts", + "types@<=5.0": "./dist/types/ts4.9/index.d.ts", + "import": "./dist/esm/index.js", + "require": "./dist/umd/index.js" + }, + "./testing": { + "types": "./dist/types/testing/index.d.ts", + "import": "./dist/esm/testing/index.js", + "require": "./dist/umd/testing/index.js" + } + }, + "scripts": { + "build": "lg-build bundle", + "tsc": "lg-build tsc", + "docs": "lg-build docs" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@leafygreen-ui/date-utils": "workspace:^", + "@leafygreen-ui/emotion": "workspace:^", + "@leafygreen-ui/form-field": "workspace:^", + "@leafygreen-ui/hooks": "workspace:^", + "@leafygreen-ui/lib": "workspace:^", + "@leafygreen-ui/palette": "workspace:^", + "@leafygreen-ui/select": "workspace:^", + "@lg-tools/test-harnesses": "workspace:^", + "@leafygreen-ui/tokens": "workspace:^", + "@leafygreen-ui/typography": "workspace:^" + }, + "peerDependencies": { + "@leafygreen-ui/leafygreen-provider": "workspace:^" + }, + "homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/time-input", + "repository": { + "type": "git", + "url": "https://github.com/mongodb/leafygreen-ui" + }, + "bugs": { + "url": "https://jira.mongodb.org/projects/LG/summary" + } +} diff --git a/packages/time-input/src/TimeInput.stories.tsx b/packages/time-input/src/TimeInput.stories.tsx new file mode 100644 index 0000000000..319954d615 --- /dev/null +++ b/packages/time-input/src/TimeInput.stories.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { StoryFn } from '@storybook/react'; +import { type StoryMetaType } from '@lg-tools/storybook-utils'; + +import { TimeInput } from '.'; + +const meta: StoryMetaType = { + title: 'Components/Inputs/TimeInput', + component: TimeInput, + parameters: { + default: 'LiveExample', + }, +}; + +export default meta; + +const Template: StoryFn = props => ; + +export const LiveExample = Template.bind({}); diff --git a/packages/time-input/src/TimeInput/TimeInput.spec.tsx b/packages/time-input/src/TimeInput/TimeInput.spec.tsx new file mode 100644 index 0000000000..815cf3dce9 --- /dev/null +++ b/packages/time-input/src/TimeInput/TimeInput.spec.tsx @@ -0,0 +1,11 @@ + +import React from 'react'; +import { render } from '@testing-library/react'; + +import { TimeInput } from '.'; + +describe('packages/time-input', () => { + test('condition', () => { + + }) +}) diff --git a/packages/time-input/src/TimeInput/TimeInput.styles.ts b/packages/time-input/src/TimeInput/TimeInput.styles.ts new file mode 100644 index 0000000000..47245842e8 --- /dev/null +++ b/packages/time-input/src/TimeInput/TimeInput.styles.ts @@ -0,0 +1,48 @@ +import { css } from '@leafygreen-ui/emotion'; +import { Theme } from '@leafygreen-ui/lib'; +import { color, spacing } from '@leafygreen-ui/tokens'; + +import { Size } from './TimeInput.types'; + +export const labelDescriptionStyles = css` + margin-bottom: ${spacing[1]}px; + display: flex; + flex-direction: column; +`; + +export const wrapperBaseStyles = css` + display: flex; + position: relative; + z-index: 0; // Establish new stacking context +`; + +export const wrapperSizeStyles: Record = { + [Size.XSmall]: css` + height: 22px; + `, + [Size.Small]: css` + height: 28px; + `, + [Size.Default]: css` + height: 36px; + `, + [Size.Large]: css` + height: 48px; + `, +}; + +export const wrapperGapStyles = css` + gap: 12px; +`; + +export const unitBaseStyles = css` + align-self: center; +`; + +export const getUnitThemeStyles = (theme: Theme) => css` + color: ${color[theme].text.secondary.default}; +`; + +export const getUnitDisabledStyles = (theme: Theme) => css` + color: ${color[theme].text.disabled.default}; +`; diff --git a/packages/time-input/src/TimeInput/TimeInput.tsx b/packages/time-input/src/TimeInput/TimeInput.tsx new file mode 100644 index 0000000000..a240cb0e43 --- /dev/null +++ b/packages/time-input/src/TimeInput/TimeInput.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { TimeInputProps } from './TimeInput.types'; +import LeafyGreenProvider, { + useDarkMode, +} from '@leafygreen-ui/leafygreen-provider'; + +import { TimeInputContent } from '../TimeInputContent'; + +export function TimeInput({ + darkMode: darkModeProp, + + ...props +}: TimeInputProps) { + const { darkMode } = useDarkMode(darkModeProp); + + return ( + + {/* TODO: Add TimeInputProvider*/} + + + ); +} + +TimeInput.displayName = 'TimeInput'; diff --git a/packages/time-input/src/TimeInput/TimeInput.types.ts b/packages/time-input/src/TimeInput/TimeInput.types.ts new file mode 100644 index 0000000000..ec3e69ae24 --- /dev/null +++ b/packages/time-input/src/TimeInput/TimeInput.types.ts @@ -0,0 +1,66 @@ +import omit from 'lodash/omit'; + +import { FormFieldState } from '@leafygreen-ui/form-field'; +import { DarkModeProps } from '@leafygreen-ui/lib'; + +export const Size = { + XSmall: 'xsmall', + Small: 'small', + Default: 'default', + Large: 'large', +} as const; + +export type Size = (typeof Size)[keyof typeof Size]; + +export const TimeInputState = omit(FormFieldState, 'Valid'); +export type TimeInputState = + (typeof TimeInputState)[keyof typeof TimeInputState]; + +export interface BaseTimeInputProps extends DarkModeProps { + /** + * The current state of the input. + * + * @default 'none' + */ + state?: TimeInputState; + + /** + * The current value of the input. If a value is passed to this prop, component will be controlled by consumer. + */ + value?: string; + + /** + * Callback fired when the input value changes + */ + onTimeChange?: (value: string) => void; + + /** + * id associated with the PasswordInput component, referenced by `