From 2380e145ee937e678e8cb1dca02e9f95e3f3d8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Grandin?= Date: Thu, 15 Jan 2026 16:09:46 +0100 Subject: [PATCH 1/9] refactor(logo): rename logo component and update story title --- .../src/lib/components/logo-branded/logo-branded.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/shared/ui/src/lib/components/logo-branded/logo-branded.stories.tsx b/libs/shared/ui/src/lib/components/logo-branded/logo-branded.stories.tsx index a6065bafd24..2bbde2ea54a 100644 --- a/libs/shared/ui/src/lib/components/logo-branded/logo-branded.stories.tsx +++ b/libs/shared/ui/src/lib/components/logo-branded/logo-branded.stories.tsx @@ -1,9 +1,9 @@ import { type Meta, type StoryObj } from '@storybook/react-webpack5' -import { LogoBrandedIcon } from './logo' +import { LogoBrandedIcon } from './logo-branded' const meta: Meta = { component: LogoBrandedIcon, - title: 'Logo', + title: 'LogoBranded', } export default meta From ce86ca2dc11d9b950e345f815cbc108f3e8d4349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Grandin?= Date: Thu, 15 Jan 2026 18:01:20 +0100 Subject: [PATCH 2/9] feat(checkbox): enhance checkbox component with color variants and update storybook configuration --- .../components/checkbox/checkbox.stories.tsx | 37 +++++---- .../src/lib/components/checkbox/checkbox.tsx | 76 ++++++++++--------- .../shared/ui/src/lib/styles/base/themes.scss | 4 +- 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/libs/shared/ui/src/lib/components/checkbox/checkbox.stories.tsx b/libs/shared/ui/src/lib/components/checkbox/checkbox.stories.tsx index e02d8c43396..4969612afa0 100644 --- a/libs/shared/ui/src/lib/components/checkbox/checkbox.stories.tsx +++ b/libs/shared/ui/src/lib/components/checkbox/checkbox.stories.tsx @@ -1,9 +1,18 @@ import type { Meta } from '@storybook/react-webpack5' -import { Checkbox } from './checkbox' +import { Checkbox, type CheckboxProps } from './checkbox' const Story: Meta = { component: Checkbox, title: 'Checkbox', + argTypes: { + color: { + control: { type: 'radio' }, + options: ['brand', 'red'], + }, + }, + args: { + color: 'brand', + }, decorators: [ (Story) => (
@@ -15,27 +24,27 @@ const Story: Meta = { export default Story export const Primary = { - render: () => ( + render: (args: CheckboxProps) => ( <> -
) } From 7c557fb155a0ba64c0559e1ebbda630d8d450a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Grandin?= Date: Fri, 16 Jan 2026 15:35:45 +0100 Subject: [PATCH 4/9] refactor(inputs): update input components for improved styling and error handling --- .../inputs/input-select/input-select.tsx | 2 +- .../input-text-area/input-text-area.tsx | 8 +++--- .../input-text-small/input-text-small.tsx | 8 +++--- .../inputs/input-text/input-text.tsx | 20 ++++++++----- .../ui/src/lib/styles/components/input.scss | 28 +++++++++---------- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx b/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx index 63199d68a64..ee2f9cf690a 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx @@ -354,7 +354,7 @@ export function InputSelect({ )} - {hint &&

{hint}

} + {hint && !error &&

{hint}

} {error &&

{error}

} ) diff --git a/libs/shared/ui/src/lib/components/inputs/input-text-area/input-text-area.tsx b/libs/shared/ui/src/lib/components/inputs/input-text-area/input-text-area.tsx index 1ddbab0f678..2ace7cce0ac 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-text-area/input-text-area.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-text-area/input-text-area.tsx @@ -30,7 +30,7 @@ export const InputTextArea = forwardRef const hasError = error && error.length > 0 ? 'input--error' : '' const inputActions = hasFocus ? 'input--focused' : '' - const isDisabled = props.disabled ? 'input--disabled !border-neutral-250' : '' + const isDisabled = props.disabled ? 'input--disabled !border-neutral' : '' return (
ref={ref} name={name} id={label} - className="mt-5 min-h-[52px] w-full appearance-none bg-transparent pr-3 text-sm text-neutral-400 outline-0" + className="mt-5 min-h-[52px] w-full appearance-none bg-transparent pr-3 text-sm text-neutral outline-0" value={!currentValue ? undefined : currentValue} onChange={(e) => { if (onChange) onChange(e) @@ -61,8 +61,8 @@ export const InputTextArea = forwardRef disabled={props.disabled} />
- {hint &&

{hint}

} - {error &&

{error}

} + {hint && !error &&

{hint}

} + {error &&

{error}

} ) }) diff --git a/libs/shared/ui/src/lib/components/inputs/input-text-small/input-text-small.tsx b/libs/shared/ui/src/lib/components/inputs/input-text-small/input-text-small.tsx index 733d4f57a34..abf1e120ac7 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-text-small/input-text-small.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-text-small/input-text-small.tsx @@ -75,7 +75,7 @@ export const InputTextSmall = forwardRef( {(error || warning) && errorMessagePosition === 'left' && (
- +
)} @@ -93,7 +93,7 @@ export const InputTextSmall = forwardRef( (
setCurrentType(currentType === 'password' ? 'text' : 'password')} - className="absolute right-2 -translate-y-0.5 transform text-sm text-neutral-400 dark:text-neutral-50" + className="absolute right-2 -translate-y-[0.5px] transform text-sm text-neutral-subtle hover:text-neutral" >
)} {error && errorMessagePosition === 'bottom' && ( -

{error}

+

{error}

)} ) diff --git a/libs/shared/ui/src/lib/components/inputs/input-text/input-text.tsx b/libs/shared/ui/src/lib/components/inputs/input-text/input-text.tsx index d8979b110ba..e459385c1a7 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-text/input-text.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-text/input-text.tsx @@ -1,3 +1,4 @@ +import clsx from 'clsx' import { type ChangeEventHandler, type ReactNode, forwardRef, useEffect, useRef, useState } from 'react' import Icon from '../../icon/icon' @@ -51,7 +52,7 @@ export const InputText = forwardRef(function I const inputActions = hasFocus ? 'input--focused' : disabled ? 'input--disabled' : '' - const isDisabled = disabled ? 'input--disabled !border-neutral-250' : '' + const isDisabled = disabled ? 'input--disabled !border-neutral' : '' const displayPicker = () => { const input = inputRef.current?.querySelector('input') @@ -76,7 +77,7 @@ export const InputText = forwardRef(function I
@@ -102,12 +103,12 @@ export const InputText = forwardRef(function I /> {isInputDate && (
- +
)} {(currentValue as string)?.length > 0 && type === 'password' && (
(currentType === 'password' ? setCurrentType('text') : setCurrentType('password'))} > {currentType === 'password' && } @@ -117,13 +118,18 @@ export const InputText = forwardRef(function I
{!isInputDate && rightElement && ( -
+
{rightElement}
)}
- {hint &&

{hint}

} - {error &&

{error}

} + {hint && !error &&

{hint}

} + {error &&

{error}

}
) }) diff --git a/libs/shared/ui/src/lib/styles/components/input.scss b/libs/shared/ui/src/lib/styles/components/input.scss index 6d855b6772a..9f39480bca1 100644 --- a/libs/shared/ui/src/lib/styles/components/input.scss +++ b/libs/shared/ui/src/lib/styles/components/input.scss @@ -27,7 +27,7 @@ } .input--small { - @apply relative h-9 min-h-[36px]; + @apply relative h-9 min-h-[36px] rounded; } .input__value { @@ -41,7 +41,7 @@ .input--focused, .input__button--focused { - outline: 1px solid var(--brand-9); + outline: 2px solid var(--brand-4); label { @apply translate-y-0 text-xs; } @@ -60,7 +60,7 @@ min-height: theme('space.9'); height: theme('space.9'); padding: theme('space.2'); - background-color: theme('colors.neutral.150'); + @apply bg-surface-neutral-component; padding-top: 0; border-color: transparent; @@ -83,11 +83,11 @@ } .input--disabled { - @apply pointer-events-none border-neutral-250 bg-neutral-100; + @apply pointer-events-none border-neutral bg-surface-neutral-subtle; box-shadow: none !important; label { - @apply text-neutral-350; + @apply text-neutral-disabled; } .input__button--focused { @@ -97,20 +97,20 @@ .input--error, .input--error .input__button { - @apply border-red-500; + @apply border-negative-strong; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05); &:hover { - @apply border-red-500; + @apply border-negative-strong; } } .input--error.input--focused { - outline: 1px solid theme('colors.red.500'); + outline: 2px solid var(--negative-4); } .input--success { - @apply border-green-500; + @apply border-positive-strong; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05); } @@ -125,13 +125,13 @@ &:hover, &:focus, &[aria-expanded='true'] { - @apply border-brand-500; + @apply border-brand-strong; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05); } } .input__list { - @apply pointer-events-auto mt-2 max-h-96 w-full list-none overflow-scroll rounded border-neutral-250 bg-white p-2 text-neutral-400 focus-within:outline-none; + @apply pointer-events-auto mt-2 max-h-96 w-full list-none overflow-scroll rounded border-neutral bg-white p-2 text-neutral focus-within:outline-none; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); ul { @@ -140,17 +140,17 @@ } .input__item { - @apply mb-1 cursor-pointer select-none rounded px-3 py-2 text-sm font-medium text-neutral-400 last:mb-0 hover:bg-neutral-150 hover:text-neutral-400; + @apply mb-1 cursor-pointer select-none rounded px-3 py-2 text-sm font-medium text-neutral last:mb-0 hover:bg-surface-neutral-component hover:text-neutral; &.is-active, &[data-current-selected], &[data-current-nav] { - @apply bg-neutral-150 text-neutral-400; + @apply bg-surface-neutral-component text-neutral; } } .input__arrow { - @apply absolute right-4 top-1/2 -translate-y-1/2 text-sm text-neutral-400; + @apply absolute right-4 top-1/2 -translate-y-1/2 text-sm text-neutral; } // time From 58b9e42c637716572a99a41d8328d3c3354c62e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Grandin?= Date: Fri, 16 Jan 2026 15:41:03 +0100 Subject: [PATCH 5/9] feat(button, dropdown): add 'select-none' utility to button and dropdown menu item styles for improved user experience --- .../ui/src/lib/components/button-primitive/button-primitive.tsx | 1 + .../ui/src/lib/components/dropdown-menu/dropdown-menu.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/shared/ui/src/lib/components/button-primitive/button-primitive.tsx b/libs/shared/ui/src/lib/components/button-primitive/button-primitive.tsx index f0cd9a45c8f..11247b76d66 100644 --- a/libs/shared/ui/src/lib/components/button-primitive/button-primitive.tsx +++ b/libs/shared/ui/src/lib/components/button-primitive/button-primitive.tsx @@ -18,6 +18,7 @@ const _buttonVariants = cva( 'disabled:bg-surface-neutral-component', 'focus-visible:[&:not(:active)]:outline-2', 'outline-0', + 'select-none', ], { variants: { diff --git a/libs/shared/ui/src/lib/components/dropdown-menu/dropdown-menu.tsx b/libs/shared/ui/src/lib/components/dropdown-menu/dropdown-menu.tsx index ec165b7c06b..ac461e68e3e 100644 --- a/libs/shared/ui/src/lib/components/dropdown-menu/dropdown-menu.tsx +++ b/libs/shared/ui/src/lib/components/dropdown-menu/dropdown-menu.tsx @@ -5,7 +5,7 @@ import { type ComponentPropsWithoutRef, type ElementRef, type ReactElement, clon import { twMerge } from '@qovery/shared/util-js' const dropdownMenuItemVariants = cva( - ['px-3', 'flex', 'items-center', 'h-8', 'text-sm', 'font-medium', 'rounded-sm', 'outline-none'], + ['px-3', 'flex', 'items-center', 'h-8', 'text-sm', 'font-medium', 'rounded-sm', 'outline-none', 'select-none'], { variants: { color: { From 276fa062b889a7dc2cfbc6ed48c97ae8b3e305ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Grandin?= Date: Fri, 16 Jan 2026 17:58:21 +0100 Subject: [PATCH 6/9] feat(input-select): enhance styling and hover states for input select components --- .../input-select-small/input-select-small.tsx | 6 ++-- .../inputs/input-select/input-select.tsx | 18 ++++++------ .../ui/src/lib/styles/components/input.scss | 6 ++-- .../ui/src/lib/styles/components/select.scss | 28 ++++++++----------- tailwind-workspace-preset.js | 2 +- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx b/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx index ca50737541f..a2b65b378f8 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx @@ -48,14 +48,14 @@ export function InputSelectSmall(props: InputSelectSmallProps) { }, [defaultValue]) return ( -
+
{label && }
) diff --git a/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx b/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx index ee2f9cf690a..89ef7c1b83c 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-select/input-select.tsx @@ -134,7 +134,7 @@ export function InputSelect({
) } diff --git a/libs/shared/ui/src/lib/components/inputs/input-radio/input-radio.tsx b/libs/shared/ui/src/lib/components/inputs/input-radio/input-radio.tsx index 6643bbc2571..329c020db88 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-radio/input-radio.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-radio/input-radio.tsx @@ -57,14 +57,14 @@ export function InputRadio(props: InputRadioProps) { checked={check} disabled={disable} onChange={(e) => inputChange(e.currentTarget.checked, e.currentTarget.value, e)} - className="relative mr-5 appearance-none font-icons before:absolute before:left-[1px] before:top-[1px] before:flex before:h-[1.125rem] before:w-[1.125rem] before:items-center before:justify-center before:rounded-full before:border-2 before:border-neutral-350 before:bg-white before:text-xs before:font-black before:leading-none before:text-white before:transition-all before:content-[''] after:absolute after:left-[5px] after:top-[5px] after:h-2.5 after:w-2.5 after:rounded-full after:bg-brand-500 after:opacity-0 after:transition-all after:content-[''] checked:before:border-brand-500 checked:after:opacity-100 hover:before:border-brand-500" + className="relative mr-5 appearance-none font-icons before:absolute before:left-[1px] before:top-[1px] before:flex before:h-[1.125rem] before:w-[1.125rem] before:items-center before:justify-center before:rounded-full before:border before:border-neutral before:bg-surface-neutral before:text-xs before:font-black before:leading-none before:transition-all before:content-[''] after:absolute after:left-[5px] after:top-[5px] after:h-2.5 after:w-2.5 after:rounded-full after:bg-surface-brand-solid after:opacity-0 after:transition-all after:content-[''] checked:before:border-brand-strong checked:after:opacity-100 hover:before:border-brand-strong" />
) diff --git a/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx b/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx index a2b65b378f8..e56d0e0b336 100644 --- a/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx +++ b/libs/shared/ui/src/lib/components/inputs/input-select-small/input-select-small.tsx @@ -49,7 +49,7 @@ export function InputSelectSmall(props: InputSelectSmallProps) { return (
- {label && } + {label && }
@@ -119,9 +119,9 @@ exports[`ClusterLogRow should display cell message 1`] = ` /> - 12 Jan, 15:57:33.00 + 19 Jan, 13:44:04.00 diff --git a/libs/domains/clusters/feature/src/lib/cluster-migration-modal/__snapshots__/cluster-migration-modal.spec.tsx.snap b/libs/domains/clusters/feature/src/lib/cluster-migration-modal/__snapshots__/cluster-migration-modal.spec.tsx.snap index c04b4c2f8d6..6daa9abfa13 100644 --- a/libs/domains/clusters/feature/src/lib/cluster-migration-modal/__snapshots__/cluster-migration-modal.spec.tsx.snap +++ b/libs/domains/clusters/feature/src/lib/cluster-migration-modal/__snapshots__/cluster-migration-modal.spec.tsx.snap @@ -22,7 +22,7 @@ exports[`ClusterMigrationModal should match snapshot 1`] = ` >