Skip to content

Commit

Permalink
Merge branch 'chore-add-use-decorators' into chore-refactoring-Single…
Browse files Browse the repository at this point in the history
…ComboBox
  • Loading branch information
AtsushiM committed Jan 28, 2025
2 parents 549eec5 + 74f1c62 commit 7d25dcf
Show file tree
Hide file tree
Showing 19 changed files with 308 additions and 204 deletions.
3 changes: 3 additions & 0 deletions packages/smarthr-ui/.storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
code {
font-family: 'Courier New', Courier, monospace;
}
html, body {
height: 100%;
}
</style>
15 changes: 15 additions & 0 deletions packages/smarthr-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [65.0.0](https://github.com/kufu/smarthr-ui/compare/v64.0.1...v65.0.0) (2025-01-28)


### ⚠ BREAKING CHANGES

* FloatAreaのresponseMessage属性の型を実装に合わせて調整する (#5299)

### Bug Fixes

* **AppHeader:** AppNaviを使うように修正 ([#5296](https://github.com/kufu/smarthr-ui/issues/5296)) ([f71c333](https://github.com/kufu/smarthr-ui/commit/f71c333bbd7a133e652408cafc25bdcc2a2355da))
* **Button:** テキストのラベルが存在しない場合に自動的にsquareにする ([#5294](https://github.com/kufu/smarthr-ui/issues/5294)) ([b92fb8a](https://github.com/kufu/smarthr-ui/commit/b92fb8aaeb2ce7deee51415e05a1b77c068fe4ef))
* FloatAreaのresponseMessage属性の型を実装に合わせて調整する ([#5299](https://github.com/kufu/smarthr-ui/issues/5299)) ([0fd3afa](https://github.com/kufu/smarthr-ui/commit/0fd3afaf17f22e4b8bc7eb270a92d02780519896))
* FormControl、FieldsetでdangerouslyTitleHiddenを指定した場合、多くのtest用ライブラリで用意されているメソッドで対象にできなくなってしまう問題に対応したい ([#5339](https://github.com/kufu/smarthr-ui/issues/5339)) ([09fedd9](https://github.com/kufu/smarthr-ui/commit/09fedd96dac1dce378c44aa3e4a254ac3b7fddf0))
* **Textarea:** autoResize時にvalue, defaultValueの初期値でも高さを反映するように修正 ([#5330](https://github.com/kufu/smarthr-ui/issues/5330)) ([8d09ffa](https://github.com/kufu/smarthr-ui/commit/8d09ffaf3674d90bfaf1cd30cbedbaf0f6eeb573))

### [64.0.1](https://github.com/kufu/smarthr-ui/compare/v64.0.0...v64.0.1) (2025-01-21)


Expand Down
2 changes: 1 addition & 1 deletion packages/smarthr-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "smarthr-ui",
"description": "SmartHR ui components built with React.",
"version": "64.0.1",
"version": "65.0.0",
"author": "SmartHR-UI Team",
"dependencies": {
"@smarthr/wareki": "^1.3.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/smarthr-ui/public/exports/smarthr-ui-props.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/smarthr-ui/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const Button = forwardRef<HTMLButtonElement, BaseProps & ElementProps & P
{
type = 'button',
size = 'default',
square,
square = false,
prefix,
suffix,
wide = false,
Expand Down Expand Up @@ -94,7 +94,7 @@ export const Button = forwardRef<HTMLButtonElement, BaseProps & ElementProps & P
className={wrapperStyle}
buttonRef={ref}
disabled={disabledOnLoading}
loading={loading}
$loading={loading}
>
{
// `button` 要素内で live region を使うことはできないので、`role="status"` を持つ要素を外側に配置している。 https://github.com/kufu/smarthr-ui/pull/4558
Expand Down
20 changes: 8 additions & 12 deletions packages/smarthr-ui/src/components/Button/ButtonWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ import React, {
ReactNode,
useMemo,
} from 'react'
import innerText from 'react-innertext'
import { tv } from 'tailwind-variants'

import { Variant } from './types'

type BaseProps = {
size: 'default' | 's'
square?: boolean
square: boolean
wide: boolean
variant: Variant
loading?: boolean
$loading?: boolean
className: string
children: ReactNode
elementAs?: ElementType
Expand All @@ -39,27 +38,24 @@ export function ButtonWrapper({
size,
square,
wide = false,
loading,
$loading,
className,
...props
}: Props) {
const actualSquare = useMemo(() => square ?? !innerText(props.children), [props.children, square])
const { buttonStyle, anchorStyle } = useMemo(() => {
const { default: defaultButton, anchor } = button({
variant,
size,
square: actualSquare,
loading,
square,
loading: $loading,
wide,
})

const commonAttr = { className }

return {
buttonStyle: defaultButton(commonAttr),
anchorStyle: anchor(commonAttr),
buttonStyle: defaultButton({ className }),
anchorStyle: anchor({ className }),
}
}, [loading, className, size, actualSquare, variant, wide])
}, [$loading, className, size, square, variant, wide])

if (props.isAnchor) {
const { anchorRef, elementAs, isAnchor: _, ...others } = props
Expand Down
53 changes: 29 additions & 24 deletions packages/smarthr-ui/src/components/Dialog/FocusTrap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, PropsWithChildren, RefObject, useCallback, useEffect, useRef } from 'react'
import React, { FC, PropsWithChildren, RefObject, useEffect, useRef } from 'react'

import { tabbable } from '../../libs/tabbable'

Expand All @@ -10,38 +10,43 @@ export const FocusTrap: FC<Props> = ({ firstFocusTarget, children }) => {
const ref = useRef<HTMLDivElement | null>(null)
const dummyFocusRef = useRef<HTMLDivElement>(null)

const handleKeyDown = useCallback((e: KeyboardEvent) => {
if (e.key !== 'Tab' || ref.current === null) {
return
}
const tabbables = tabbable(ref.current).filter((elm) => elm.tabIndex >= 0)
if (tabbables.length === 0) {
return
}
const firstTabbable = tabbables[0]
const lastTabbable = tabbables[tabbables.length - 1]
const currentFocused = Array.from(tabbables).find((elm) => elm === e.target)
if (
e.shiftKey &&
(currentFocused === firstTabbable || document.activeElement === dummyFocusRef.current)
) {
lastTabbable.focus()
e.preventDefault()
} else if (!e.shiftKey && currentFocused === lastTabbable) {
firstTabbable.focus()
e.preventDefault()
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== 'Tab' || ref.current === null) {
return
}

const tabbables = tabbable(ref.current).filter((elm) => elm.tabIndex >= 0)

if (tabbables.length === 0) {
return
}

const firstTabbable = tabbables[0]
const lastTabbable = tabbables[tabbables.length - 1]
const currentFocused = tabbables.find((elm) => elm === e.target)

if (e.shiftKey) {
if (currentFocused === firstTabbable || document.activeElement === dummyFocusRef.current) {
e.preventDefault()
lastTabbable.focus()
}
} else if (currentFocused === lastTabbable) {
e.preventDefault()
firstTabbable.focus()
}
}
}, [])

useEffect(() => {
window.addEventListener('keydown', handleKeyDown)

return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [handleKeyDown])
}, [])

useEffect(() => {
const triggerElement = document.activeElement

if (firstFocusTarget?.current) {
firstFocusTarget.current.focus()
} else {
Expand Down
28 changes: 10 additions & 18 deletions packages/smarthr-ui/src/components/Dialog/useBodyScrollLock.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import { useEffect, useState } from 'react'
import { useEffect, useRef } from 'react'

export const useBodyScrollLock = (isOpen: boolean) => {
const [scrollBarWidth, setScrollBarWidth] = useState<number | null>(null)
const [paddingRight, setPaddingRight] = useState<number | null>(null)

useEffect(() => {
setScrollBarWidth(window.innerWidth - document.body.clientWidth)
}, [])

useEffect(() => {
if (scrollBarWidth === null) {
return
}
const originalPaddingRight = getComputedStyle(document.body).getPropertyValue('padding-right')
setPaddingRight(scrollBarWidth + parseInt(originalPaddingRight, 10))
}, [scrollBarWidth])
const paddingRightRef = useRef<string | null>(null)

useEffect(() => {
if (!isOpen) return

if (paddingRight !== null) {
document.body.style.paddingInlineEnd = `${paddingRight}px`
if (paddingRightRef.current === null) {
const scrollBarWidth = window.innerWidth - document.body.clientWidth
const originalPaddingRight = getComputedStyle(document.body).getPropertyValue('padding-right')

paddingRightRef.current = `${scrollBarWidth + parseInt(originalPaddingRight, 10)}px`
}

document.body.style.paddingInlineEnd = paddingRightRef.current
document.body.style.overflow = 'hidden'

return () => {
document.body.style.paddingInlineEnd = ''
document.body.style.overflow = ''
}
}, [isOpen, paddingRight])
}, [isOpen])
}
5 changes: 5 additions & 0 deletions packages/smarthr-ui/src/components/Dialog/useDialogPortal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ export function useDialogPortal(parent?: HTMLElement | RefObject<HTMLElement>, i
if (!portalContainer) {
return
}

if (id) {
portalContainer.id = id
}

const parentElement = parent && 'current' in parent ? parent.current : parent
// SSR を考慮し、useEffect 内で初期値 document.body を指定
const actualParent = parentElement || document.body

actualParent.appendChild(portalContainer)

return () => {
actualParent.removeChild(portalContainer)
}
Expand All @@ -27,6 +31,7 @@ export function useDialogPortal(parent?: HTMLElement | RefObject<HTMLElement>, i
if (portalContainer === null) {
return null
}

return createPortal(children, portalContainer)
},
[portalContainer],
Expand Down
14 changes: 6 additions & 8 deletions packages/smarthr-ui/src/components/Dialog/useRemoteTrigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,12 @@ export function useRemoteTrigger({
}, [id])

useEffect(() => {
if (onToggle) {
onToggle(isOpen)
}
if (onOpen && isOpen) {
onOpen()
}
if (onClose && !isOpen) {
onClose()
onToggle?.(isOpen)

if (isOpen) {
onOpen?.()
} else {
onClose?.()
}
// HINT: 再レンダリング際にhookを利用していないonToggleなどが渡されると意図せず発火してしまう場合がありえるため
// onToggle, onOpen, onClose を depsに含めていません
Expand Down
22 changes: 6 additions & 16 deletions packages/smarthr-ui/src/components/FloatArea/FloatArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { ComponentPropsWithoutRef, FC, ReactNode, useMemo } from 'react'
import { tv } from 'tailwind-variants'

import { AbstractSize, CharRelativeSize } from '../../themes/createSpacing'
import { Gap, ResponseMessageType } from '../../types'
import { Gap, ResponseMessageTypeWithoutProcessing } from '../../types'
import { Base } from '../Base'
import { Cluster } from '../Layout'
import { ResponseMessage } from '../ResponseMessage'
Expand Down Expand Up @@ -54,7 +54,7 @@ type Props = StyleProps & {
/** tertiary 領域に表示するボタン */
tertiaryButton?: ReactNode
/** 操作に対するフィードバックメッセージ */
responseMessage?: ResponseMessageType
responseMessage?: ResponseMessageTypeWithoutProcessing
}
type ElementProps = Omit<ComponentPropsWithoutRef<'div'>, keyof Props>

Expand All @@ -69,26 +69,16 @@ export const FloatArea: FC<Props & ElementProps> = ({
className,
...rest
}) => {
const styleProps = useMemo(
() => ({
style: { ...style, zIndex },
}),
[style, zIndex],
)
const styleAttr = useMemo(() => ({ ...style, zIndex }), [style, zIndex])
const actualClassName = useMemo(() => floatArea({ bottom, className }), [bottom, className])

return (
<Base
{...styleProps}
{...rest}
className={floatArea({ bottom, className })}
layer={3}
padding={1}
>
<Base {...rest} style={styleAttr} layer={3} padding={1} className={actualClassName}>
<Cluster gap={1}>
{tertiaryButton}
<div className="shr-ms-auto">
<Cluster gap={1} align="center">
{(responseMessage?.status === 'success' || responseMessage?.status === 'error') && (
{responseMessage && (
<ResponseMessage type={responseMessage.status}>
{responseMessage.text}
</ResponseMessage>
Expand Down
Loading

0 comments on commit 7d25dcf

Please sign in to comment.