diff --git a/packages/components/src/input/src/Input.css b/packages/components/src/input/src/Input.css index 14eea8e04..3d46cdeec 100644 --- a/packages/components/src/input/src/Input.css +++ b/packages/components/src/input/src/Input.css @@ -1,19 +1,21 @@ .o-ui { - --o-ui-input-padding: var(--o-ui-sp-3); + --o-ui-input-padding: var(--hop-space-inset-squish-md); --o-ui-input-padding-with-icon: var(--o-ui-sp-7); --o-ui-input-padding-with-button: var(--o-ui-sp-8); --o-ui-input-padding-loading: var(--o-ui-sp-8); - --o-ui-input-border-color: var(--o-ui-b-alias-mid-break); - --o-ui-input-border-radius: var(--o-ui-br-2); - --o-ui-input-background-color: var(--o-ui-bg-alias-mid-break); + --o-ui-input-border-color: var(--hop-neutral-border); + --o-ui-input-border-radius: var(--hop-shape-rounded-md); + --o-ui-input-background-color: var(--hop-neutral-surface); } .o-ui-input { display: inline-flex; position: relative; transition: var(--o-ui-focus-ring-transition); - color: var(--o-ui-text-alias-primary); - width: var(--o-ui-sz-16); + color: var(--hop-neutral-text); + font-family: var(--hop-body-md-font-family); + font-size: var(--hop-body-md-font-size); + width: 20rem; align-items: center; } @@ -25,8 +27,8 @@ border: none; width: 100%; background-color: inherit; - color: inherit; - min-height: calc(var(--o-ui-sz-6) - 2px); + color: var(--hop-neutral-text); + min-height: calc(2.5rem - 2px); margin: 0; padding: 0; } @@ -47,7 +49,7 @@ .o-ui-text-input, .o-ui-text-area textarea, .o-ui-number-input { - font-size: var(--o-ui-fs-3); + font-size: var(--hop-body-sm-font-size); padding: 0; border-radius: var(--o-ui-input-border-radius); border: 1px solid var(--o-ui-input-border-color); @@ -60,7 +62,7 @@ .o-ui-text-input input, .o-ui-text-area textarea, .o-ui-number-input input { - padding: 0 var(--o-ui-input-padding); + padding: var(--o-ui-input-padding); } .o-ui-text-input input, @@ -96,26 +98,27 @@ .o-ui-input input:-webkit-autofill, .o-ui-input textarea:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--o-ui-bg-alias-accent-faint) inset !important; - -webkit-text-fill-color: var(--o-ui-text-alias-primary) !important; + -webkit-text-fill-color: var(--hop-neutral-text) !important; } /* STATE | HOVER */ .o-ui-input:not(.o-ui-input-focus):not(.o-ui-input-disabled):hover, .o-ui-input:not(.o-ui-input-focus):hover textarea:not(:disabled) { - border-color: var(--o-ui-b-alias-high-break); + border-color: var(--hop-neutral-border-hover); + background-color: var(--hop-neutral-surface-hover); } /* PLACEHOLDER */ .o-ui-input input::placeholder, .o-ui-input textarea::placeholder { - color: var(--o-ui-text-alias-input-placeholder); + color: var(--hop-neutral-text-weakest); opacity: 1; - font-size: var(--o-ui-fs-3); + font-size: var(--hop-body-md-font-size); } .o-ui-input-disabled input::placeholder, .o-ui-input textarea:disabled::placeholder { - color: var(--o-ui-text-alias-secondary); + color: var(--hop-neutral-text-disabled); } /* FLUID */ @@ -126,19 +129,19 @@ /* INVALID */ .o-ui-input-invalid:not(.o-ui-input-disabled), .o-ui-input-invalid:not(.o-ui-input-disabled) textarea { - --o-ui-input-border-color: var(--o-ui-b-alias-alert); + --o-ui-input-border-color: var(--hop-danger-border-strong); } /* INVALID | DISABLED */ .o-ui-input-invalid.o-ui-input-disabled, .o-ui-input-invalid.o-ui-text-area textarea:disabled { - background-color: var(--o-ui-bg-alias-alert-light); - --o-ui-input-border-color: var(--o-ui-bg-alias-alert-light); + background-color: var(--hop-neutral-border-disabled); + --o-ui-input-border-color: var(--hop-neutral-surface-disabled); } .o-ui-input.o-ui-input-invalid:not(.o-ui-text-area):focus-within, .o-ui-input-focus.o-ui-input-invalid { - box-shadow: var(--o-ui-focus-ring-inset-md); + box-shadow: 0 0 0 0.12rem var(--hop-neutral-surface), 0 0 0 0.219rem var(--hop-primary-border-focus); } /* STATE | HOVER | INVALID */ @@ -154,6 +157,7 @@ flex-shrink: 0; margin-right: 0.5rem; margin-left: 0.5rem; + color: var(--hop-neutral-icon); } /* ICON | MEDIUM */ @@ -164,7 +168,6 @@ /* BUTTON | INPUT */ .o-ui-text-input .o-ui-input-button, .o-ui-number-input .o-ui-input-button { - position: inline-flex !important; display: flex; text-align: center; margin-right: .625rem; @@ -182,7 +185,7 @@ .o-ui-number-input:not(.o-ui-input-disabled):focus-within, .o-ui-text-area:not(.o-ui-input-disabled).o-ui-input-has-focus textarea, .o-ui-input-focus:not(.o-ui-input-disabled):not(.o-ui-has-button-disabled) { - box-shadow: var(--o-ui-focus-ring-inset-md) !important; + box-shadow: 0 0 0 0.12rem var(--hop-neutral-surface), 0 0 0 0.219rem var(--hop-primary-border-focus); outline: transparent; } @@ -190,9 +193,14 @@ .o-ui-text-input.o-ui-input-disabled, .o-ui-number-input.o-ui-input-disabled, .o-ui-input textarea:disabled { - opacity: var(--o-ui-disabled-opacity); - background-color: var(--o-ui-input-background-color); + background-color: var(--hop-neutral-surface-disabled); cursor: not-allowed; + --o-ui-input-border-color: var(--hop-neutral-border-disabled); +} + +/* STATES | ACTIVE */ +.o-ui-text-input.o-ui-input-has-active { + --o-ui-input-border-color: var(--hop-neutral-border-active); } .o-ui-input-disabled > * { @@ -223,4 +231,4 @@ .o-ui-number-input.o-ui-input-loading, .o-ui-text-area.o-ui-input-loading textarea { padding-right: var(--o-ui-input-padding-loading); -} \ No newline at end of file +} diff --git a/packages/components/src/input/src/index.ts b/packages/components/src/input/src/index.ts index 3fce2dd9c..1e42da45a 100644 --- a/packages/components/src/input/src/index.ts +++ b/packages/components/src/input/src/index.ts @@ -2,6 +2,7 @@ export * from "./useGroupInput"; export * from "./useInput"; export * from "./useInputContent"; export * from "./useInputHasFocus"; +export * from "./useInputHasActive"; export * from "./adaptInputStylingProps"; export * from "./types"; diff --git a/packages/components/src/input/src/useInputHasActive.ts b/packages/components/src/input/src/useInputHasActive.ts new file mode 100644 index 000000000..7bf098b4b --- /dev/null +++ b/packages/components/src/input/src/useInputHasActive.ts @@ -0,0 +1,18 @@ +import { useEventCallback } from "../../shared"; +import { useState } from "react"; + +export function useInputHasActive() { + const [hasActive, setHasActive] = useState(false); + + return { + hasActive, + inputProps: { + onBlur: useEventCallback(() => { + setHasActive(false); + }), + onFocus: useEventCallback(() => { + setHasActive(true); + }) + } + }; +} diff --git a/packages/components/src/text-input/docs/TextInput.stories.mdx b/packages/components/src/text-input/docs/TextInput.stories.mdx index 33c078726..5ab6f4491 100644 --- a/packages/components/src/text-input/docs/TextInput.stories.mdx +++ b/packages/components/src/text-input/docs/TextInput.stories.mdx @@ -130,7 +130,7 @@ A specialized text input which show / hide a password. - + diff --git a/packages/components/src/text-input/src/TextInput.tsx b/packages/components/src/text-input/src/TextInput.tsx index f0928fe79..eb31aee50 100644 --- a/packages/components/src/text-input/src/TextInput.tsx +++ b/packages/components/src/text-input/src/TextInput.tsx @@ -1,4 +1,4 @@ -import { AbstractInputProps, adaptInputStylingProps, useInput, useInputButton, useInputHasFocus, useInputIcon, useInputSpinner } from "../../input"; +import { AbstractInputProps, adaptInputStylingProps, useInput, useInputButton, useInputHasFocus, useInputHasActive, useInputIcon, useInputSpinner } from "../../input"; import { Box, BoxProps } from "../../box"; import { ChangeEvent, ComponentProps, ElementType, ReactElement, forwardRef } from "react"; import { ClearInputGroupContext, useInputGroupTextInputProps } from "../../input-group"; @@ -135,6 +135,7 @@ export function InnerTextInput(props: InnerTextInputProps) { }); const { hasFocus, inputProps: inputFocusProps } = useInputHasFocus(); + const { hasActive, inputProps: inputActiveProps } = useInputHasActive(); const iconMarkup = useInputIcon(icon, { disabled }); @@ -156,7 +157,8 @@ export function InnerTextInput(props: InnerTextInputProps) { style }, inputProps, - inputFocusProps + inputFocusProps, + inputActiveProps )} /> {/* Otherwise an input button will receive an addon className */} @@ -178,7 +180,8 @@ export function InnerTextInput(props: InnerTextInputProps) { iconMarkup && "has-icon", disabled && "disabled", buttonMarkup && "has-button", - hasFocus && "has-focus" + hasFocus && "has-focus", + hasActive && "has-active", ) }, wrapperProps diff --git a/packages/components/src/text-input/tests/chromatic/TextInput.stories.tsx b/packages/components/src/text-input/tests/chromatic/TextInput.stories.tsx index d82528322..74c7951fb 100644 --- a/packages/components/src/text-input/tests/chromatic/TextInput.stories.tsx +++ b/packages/components/src/text-input/tests/chromatic/TextInput.stories.tsx @@ -18,6 +18,7 @@ export const Default: TextInputStory = { render: () => ( + @@ -35,6 +36,7 @@ export const Placeholder: TextInputStory = { render: () => ( + @@ -52,6 +54,7 @@ export const Value: TextInputStory = { render: () => ( + @@ -74,6 +77,7 @@ export const Icon: TextInputStory = { } placeholder="Where to?" aria-label="Label" /> } defaultValue="SpaceX will win the race!" placeholder="Where to?" /> + } placeholder="Where to?" /> } placeholder="Where to?" /> } placeholder="Where to?" /> } placeholder="Where to?" /> @@ -96,6 +100,7 @@ export const Button: TextInputStory = { } placeholder="Where to?" /> } placeholder="Where to?" /> + } placeholder="Where to?" /> ) };