Skip to content

Commit d518205

Browse files
authored
Merge pull request #92 from helpwave/version-0.1.29
chore: update input styles and change focus behavior
2 parents 6edd877 + 15d92c7 commit d518205

25 files changed

Lines changed: 336 additions & 214 deletions

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
66
and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.1.29] - 2025-10-02
9+
10+
### Added
11+
- HTML elements now use `color-scheme: dark` when in dark mode
12+
- Add invalid state styling to Selects
13+
- Add a placeholder color called `placeholder`
14+
- Add a hook for localized validation translation `useTranslatedValidators`
15+
16+
### Changed
17+
- `disabled` and `required` are now optional in `FormElementWrapper`
18+
- changed focus to draw an outline instead of a ring
19+
20+
### Removed
21+
- removed several typography entries that only change the `font-weight` (e.g. `typography-label-md-bold` -> `typography-label-md font-bold`)
22+
23+
### Fix
24+
- Fix disabled color for `Select`
25+
826
## [0.1.28] - 2025-10-02
927

1028
### Added

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "git+https://github.com/helpwave/hightide.git"
88
},
99
"license": "MPL-2.0",
10-
"version": "0.1.28",
10+
"version": "0.1.29",
1111
"files": [
1212
"dist"
1313
],

src/components/date/DatePicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const DatePicker = ({
5757
<div className="flex-row-2 items-center justify-between h-7">
5858
<TextButton
5959
className={clsx('flex-row-1 items-center cursor-pointer select-none', {
60-
'text-disabled-text': displayMode !== 'day',
60+
'text-disabled': displayMode !== 'day',
6161
})}
6262
onClick={() => setDisplayMode(displayMode === 'day' ? 'yearMonth' : 'day')}
6363
>

src/components/date/DayPicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const DayPicker = ({
6060
'text-button-solid-neutral-text bg-button-solid-neutral-background': !isSelected && isSameMonth && isDayValid,
6161
'text-button-solid-primary-text bg-button-solid-primary-background': isSelected && isDayValid,
6262
'hover:brightness-90 hover:bg-button-solid-primary-background hover:text-button-solid-primary-text': isDayValid,
63-
'text-disabled-text bg-disabled-background cursor-not-allowed': !isDayValid,
63+
'text-disabled bg-disabled-background cursor-not-allowed': !isDayValid,
6464
'border-secondary': isToday && markToday,
6565
'border-transparent': !isToday || !markToday,
6666
}

src/components/dialog/Dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export const Dialog = ({
9696
className
9797
)}
9898
>
99-
<div className="typography-title-lg-semibold mr-8">
99+
<div className="typography-title-lg mr-8">
100100
{titleElement}
101101
</div>
102102
<div className="text-description">

src/components/form/FormElementWrapper.tsx

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import type { HTMLAttributes, ReactNode } from 'react'
2+
import { useEffect } from 'react'
3+
import { useState } from 'react'
24
import { useId } from 'react'
35
import { clsx } from 'clsx'
46
import type { BagFunction } from '@/src/utils/bagFunctions'
57
import type { LabelProps } from '@/src/components/user-action/Label'
68
import { Label } from '@/src/components/user-action/Label'
79

10+
type ErrorShowBehaviour = 'always' | 'whenTouched'
11+
812
type FormElementWrapperBag = {
13+
'touched': boolean,
14+
'onTouched': (isTouched?: boolean) => void,
915
'invalid': boolean,
1016
'required': boolean,
1117
'disabled': boolean,
@@ -17,10 +23,12 @@ type FormElementWrapperBag = {
1723
export type FormElementWrapperProps = {
1824
children: BagFunction<FormElementWrapperBag>,
1925
id?: string,
20-
required: boolean,
21-
disabled: boolean,
26+
required?: boolean,
27+
disabled?: boolean,
28+
isTouched?: boolean,
2229
label?: ReactNode,
2330
labelProps?: Omit<LabelProps, 'children'>,
31+
errorShowBehaviour?: ErrorShowBehaviour,
2432
error?: ReactNode,
2533
errorProps?: Omit<HTMLAttributes<HTMLParagraphElement>, 'children'>,
2634
description?: ReactNode,
@@ -33,49 +41,60 @@ export const FormElementWrapper = ({
3341
id,
3442
required = false,
3543
disabled = false,
44+
isTouched: initialIsTouched = false,
3645
label,
3746
labelProps,
47+
errorShowBehaviour = 'whenTouched',
3848
error,
3949
errorProps,
4050
description,
4151
descriptionProps,
4252
containerClassName,
4353
}: FormElementWrapperProps) => {
54+
const [touched, setTouched] = useState(initialIsTouched)
4455
const generatedId = useId()
4556
const usedId = id ?? generatedId
4657

58+
useEffect(() => {
59+
setTouched(initialIsTouched)
60+
}, [initialIsTouched])
61+
4762
const describedBy: string = [
4863
description ? `${usedId}-description` : undefined,
4964
error ? `${usedId}-error` : undefined,
5065
].filter(Boolean).join(' ')
5166

5267
const labeledBy = label ? `${usedId}-label` : undefined
5368

69+
const isShowingError = errorShowBehaviour === 'always' || (touched)
70+
5471
const bag: FormElementWrapperBag = {
72+
'touched': touched,
73+
'onTouched': (isTouched) => setTouched(isTouched ?? true),
5574
'disabled': disabled,
56-
'invalid': !!error,
75+
'invalid': !!error && isShowingError,
5776
'required': required,
5877
'id': usedId,
5978
'aria-describedby': describedBy,
6079
'aria-labelby': labeledBy
6180
}
6281

6382
return (
64-
<div className={clsx('flex flex-col gap-y-1', containerClassName)}>
83+
<div className={clsx('relative flex flex-col gap-y-1', containerClassName)}>
6584
{label && (
66-
<Label htmlFor={usedId} className={clsx('typography-label-md', labelProps?.className)}>
85+
<Label htmlFor={usedId} size="lg" className={clsx('flex-row-1 items-start', labelProps?.className)}>
6786
{label}
68-
{required && <span role="none" className="text-primary font-bold">*</span>}
87+
{required && <div role="none" className="bg-primary w-2 h-2 rounded-full"/>}
6988
</Label>
7089
)}
7190
{description && (
72-
<p {...descriptionProps} className={clsx('text-description text-xs', descriptionProps?.className)}>
91+
<p {...descriptionProps} className={clsx('text-description text-sm', descriptionProps?.className)}>
7392
{description}
7493
</p>
7594
)}
7695
{children(bag)}
77-
{error && (
78-
<p {...errorProps} role="alert" className={clsx('text-negative text-sm font-medium', errorProps)}>
96+
{error && isShowingError && (
97+
<p {...errorProps} role="alert" className={clsx('absolute top-[calc(100%_+_0.25rem)] left-0 text-negative text-sm font-medium', errorProps)}>
7998
{error}
8099
</p>
81100
)}

src/components/layout/FAQSection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const FAQSection = ({
3838
<ExpandableUncontrolled
3939
key={id}
4040
{...restProps}
41-
label={(<h3 id={id} className="typography-title-md-semibold">{title}</h3>)}
41+
label={(<span id={id} className="typography-title-md">{title}</span>)}
4242
clickOnlyOnHeader={false}
4343
icon={(expanded) => (<ExpansionIcon isExpanded={expanded} className="text-primary"/>)}
4444
className={clsx('rounded-xl', expandableClassName)}

src/components/layout/TextImage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const TextImage = ({
6363
</div>
6464
)}
6565
<div className="flex-col-1 overflow-hidden">
66-
<span className="typography-title-lg-semibold">{title}</span>
66+
<span className="typography-title-lg">{title}</span>
6767
<span className="text-ellipsis overflow-hidden">{description}</span>
6868
</div>
6969
{onShowMoreClicked && (

src/components/table/FillerRowElement.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const FillerRowElement = ({
77
className
88
}: FillerRowElementProps) => {
99
return (
10-
<div className={clsx('flex flex-row items-center w-1/2 h-4 text-disabled-text font-bold', className)}>
10+
<div className={clsx('flex flex-row items-center w-1/2 h-4 text-disabled font-bold', className)}>
1111
-
1212
</div>
1313
)

src/components/user-action/Button.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ export type IconButtonColor = typeof IconButtonUtil.icon[number]
3535
/**
3636
* The different sizes for a button
3737
*/
38-
type ButtonSizes = 'small' | 'medium' | 'large'
38+
type ButtonSizes = 'small' | 'medium' | 'large' | 'none'
3939

40-
type IconButtonSize = 'tiny' | 'small' | 'medium' | 'large'
40+
type IconButtonSize = 'tiny' | 'small' | 'medium' | 'large' | 'none'
4141

4242
/**
4343
* The shard properties between all button types
@@ -50,12 +50,14 @@ export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
5050
}
5151

5252
const paddingMapping: Record<ButtonSizes, string> = {
53+
none: '',
5354
small: 'btn-sm',
5455
medium: 'btn-md',
5556
large: 'btn-lg'
5657
}
5758

5859
const iconPaddingMapping: Record<IconButtonSize, string> = {
60+
none: '',
5961
tiny: 'icon-btn-xs',
6062
small: 'icon-btn-sm',
6163
medium: 'icon-btn-md',
@@ -137,7 +139,7 @@ export const SolidButton = forwardRef<HTMLButtonElement, SolidButtonProps>(funct
137139
'group font-semibold',
138140
colorClasses,
139141
'not-disabled:hover:brightness-90',
140-
'disabled:text-disabled-text disabled:bg-disabled-background',
142+
'disabled:text-disabled disabled:bg-disabled-background',
141143
ButtonUtil.paddingMapping[size],
142144
className
143145
)}
@@ -195,7 +197,7 @@ export const OutlineButton = ({
195197
'group font-semibold bg-transparent border-2 ',
196198
'not-disabled:hover:brightness-80',
197199
colorClasses,
198-
'disabled:text-disabled-text disabled:border-disabled-outline',
200+
'disabled:text-disabled disabled:border-disabled-outline',
199201
ButtonUtil.paddingMapping[size],
200202
className
201203
)}
@@ -241,9 +243,9 @@ export const TextButton = ({
241243
...restProps
242244
}: TextButtonProps) => {
243245
const colorClasses = {
244-
primary: 'not-disabled:bg-transparent not-disabled:text-button-text-primary-text focus-style-none focus-visible:ring-2 not-disabled:focus-visible:ring-button-text-primary-text',
245-
negative: 'not-disabled:bg-transparent not-disabled:text-button-text-negative-text focus-style-none focus-visible:ring-2 not-disabled:focus-visible:ring-button-text-negative-text',
246-
neutral: 'not-disabled:bg-transparent not-disabled:text-button-text-neutral-text focus-style-none focus-visible:ring-2 not-disabled:focus-visible:ring-button-text-neutral-text',
246+
primary: 'not-disabled:bg-transparent not-disabled:text-button-text-primary-text not-disabled:focus-visible:outline-button-text-primary-text',
247+
negative: 'not-disabled:bg-transparent not-disabled:text-button-text-negative-text not-disabled:focus-visible:outline-button-text-negative-text',
248+
neutral: 'not-disabled:bg-transparent not-disabled:text-button-text-neutral-text not-disabled:focus-visible:outline-button-text-neutral-text',
247249
}[color]
248250

249251
const backgroundColor = {
@@ -263,7 +265,7 @@ export const TextButton = ({
263265
onClick={onClick}
264266
className={clsx(
265267
'group font-semibold',
266-
'disabled:text-disabled-text',
268+
'disabled:text-disabled',
267269
colorClasses,
268270
{
269271
[backgroundColor]: coloredHoverBackground,
@@ -328,7 +330,7 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(functio
328330
className={clsx(
329331
colorClasses,
330332
'not-disabled:hover:brightness-90',
331-
'disabled:text-disabled-text',
333+
'disabled:text-disabled',
332334
{
333335
'disabled:bg-disabled-background': color !== 'transparent',
334336
'disabled:opacity-70': color === 'transparent',

0 commit comments

Comments
 (0)