@hzblj/kara-components 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js +6 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +2 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -1
- package/lib/module/atoms/avatar/avatar.js +5 -0
- package/lib/module/atoms/avatar/avatar.js.map +1 -1
- package/lib/module/atoms/box/box.js +3 -0
- package/lib/module/atoms/box/box.js.map +1 -1
- package/lib/module/atoms/box/index.js +0 -1
- package/lib/module/atoms/box/index.js.map +1 -1
- package/lib/module/atoms/button/button-tokens.js +2 -2
- package/lib/module/atoms/button/button-tokens.js.map +1 -1
- package/lib/module/atoms/button/button.android.js +6 -2
- package/lib/module/atoms/button/button.android.js.map +1 -1
- package/lib/module/atoms/button/button.ios.js +7 -2
- package/lib/module/atoms/button/button.ios.js.map +1 -1
- package/lib/module/atoms/card/card.android.js +5 -3
- package/lib/module/atoms/card/card.android.js.map +1 -1
- package/lib/module/atoms/card/card.ios.js +7 -3
- package/lib/module/atoms/card/card.ios.js.map +1 -1
- package/lib/module/atoms/checkbox/checkbox.android.js +1 -1
- package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
- package/lib/module/atoms/fab/fab.android.js +9 -1
- package/lib/module/atoms/fab/fab.android.js.map +1 -1
- package/lib/module/atoms/fab/fab.ios.js +9 -3
- package/lib/module/atoms/fab/fab.ios.js.map +1 -1
- package/lib/module/atoms/glass-view/glass-view.android.js +1 -1
- package/lib/module/atoms/glass-view/glass-view.android.js.map +1 -1
- package/lib/module/atoms/h-stack/h-stack.ios.js +5 -3
- package/lib/module/atoms/h-stack/h-stack.ios.js.map +1 -1
- package/lib/module/atoms/icon-button/icon-button.android.js +9 -0
- package/lib/module/atoms/icon-button/icon-button.android.js.map +1 -1
- package/lib/module/atoms/icon-button/icon-button.ios.js +9 -2
- package/lib/module/atoms/icon-button/icon-button.ios.js.map +1 -1
- package/lib/module/atoms/image/image.js +4 -4
- package/lib/module/atoms/image/image.js.map +1 -1
- package/lib/module/atoms/index.js +1 -0
- package/lib/module/atoms/index.js.map +1 -1
- package/lib/module/atoms/pressable/pressable.js +75 -27
- package/lib/module/atoms/pressable/pressable.js.map +1 -1
- package/lib/module/atoms/progress/progress.android.js +7 -0
- package/lib/module/atoms/progress/progress.android.js.map +1 -1
- package/lib/module/atoms/progress/progress.ios.js +6 -1
- package/lib/module/atoms/progress/progress.ios.js.map +1 -1
- package/lib/module/atoms/rn-text/rn-text.js +66 -26
- package/lib/module/atoms/rn-text/rn-text.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.ios.js +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -1
- package/lib/module/atoms/skeleton/skeleton.js +22 -8
- package/lib/module/atoms/skeleton/skeleton.js.map +1 -1
- package/lib/module/atoms/stagger/index.js +5 -0
- package/lib/module/atoms/stagger/index.js.map +1 -0
- package/lib/module/atoms/stagger/stagger.js +102 -0
- package/lib/module/atoms/stagger/stagger.js.map +1 -0
- package/lib/module/atoms/stagger/stagger.types.js +4 -0
- package/lib/module/atoms/stagger/stagger.types.js.map +1 -0
- package/lib/module/atoms/surface/surface.android.js +5 -3
- package/lib/module/atoms/surface/surface.android.js.map +1 -1
- package/lib/module/atoms/surface/surface.ios.js +7 -3
- package/lib/module/atoms/surface/surface.ios.js.map +1 -1
- package/lib/module/atoms/switch/switch.android.js +1 -1
- package/lib/module/atoms/switch/switch.android.js.map +1 -1
- package/lib/module/atoms/text/text.android.js +5 -3
- package/lib/module/atoms/text/text.android.js.map +1 -1
- package/lib/module/atoms/text/text.ios.js +6 -4
- package/lib/module/atoms/text/text.ios.js.map +1 -1
- package/lib/module/atoms/v-stack/v-stack.ios.js +5 -3
- package/lib/module/atoms/v-stack/v-stack.ios.js.map +1 -1
- package/lib/module/atoms/z-stack/z-stack.ios.js +5 -3
- package/lib/module/atoms/z-stack/z-stack.ios.js.map +1 -1
- package/lib/module/glyph/glyph.android.js +2 -0
- package/lib/module/glyph/glyph.android.js.map +1 -1
- package/lib/module/glyph/glyph.ios.js +5 -2
- package/lib/module/glyph/glyph.ios.js.map +1 -1
- package/lib/module/molecules/collapsible/collapsible.android.js +18 -8
- package/lib/module/molecules/collapsible/collapsible.android.js.map +1 -1
- package/lib/module/molecules/labeled-content/labeled-content.js +4 -1
- package/lib/module/molecules/labeled-content/labeled-content.js.map +1 -1
- package/lib/module/molecules/link/link.js +4 -1
- package/lib/module/molecules/link/link.js.map +1 -1
- package/lib/module/molecules/list-item/list-item.js +4 -1
- package/lib/module/molecules/list-item/list-item.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js.map +1 -1
- package/lib/module/molecules/rn-list-item/rn-list-item.js +10 -2
- package/lib/module/molecules/rn-list-item/rn-list-item.js.map +1 -1
- package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js +5 -6
- package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js.map +1 -1
- package/lib/module/molecules/stepper/stepper.ios.js +6 -2
- package/lib/module/molecules/stepper/stepper.ios.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.android.js +8 -5
- package/lib/module/organisms/fab-menu/fab-menu.android.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.ios.js +5 -2
- package/lib/module/organisms/fab-menu/fab-menu.ios.js.map +1 -1
- package/lib/module/organisms/snackbar/snackbar.js +155 -18
- package/lib/module/organisms/snackbar/snackbar.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js.map +1 -1
- package/lib/module/use-stack-modifiers.js +10 -8
- package/lib/module/use-stack-modifiers.js.map +1 -1
- package/lib/typescript/atoms/activity-indicator/activity-indicator.types.d.ts +2 -0
- package/lib/typescript/atoms/avatar/avatar.types.d.ts +5 -0
- package/lib/typescript/atoms/box/box.d.ts +3 -0
- package/lib/typescript/atoms/box/index.d.ts +0 -1
- package/lib/typescript/atoms/button/button-tokens.d.ts +1 -1
- package/lib/typescript/atoms/button/button.types.d.ts +2 -0
- package/lib/typescript/atoms/card/card.types.d.ts +2 -2
- package/lib/typescript/atoms/fab/fab.types.d.ts +8 -1
- package/lib/typescript/atoms/h-stack/h-stack.types.d.ts +6 -3
- package/lib/typescript/atoms/icon-button/icon-button.types.d.ts +7 -0
- package/lib/typescript/atoms/image/image.d.ts +2 -2
- package/lib/typescript/atoms/index.d.ts +1 -0
- package/lib/typescript/atoms/pressable/pressable.types.d.ts +10 -9
- package/lib/typescript/atoms/progress/progress.types.d.ts +2 -0
- package/lib/typescript/atoms/rn-text/rn-text.types.d.ts +7 -4
- package/lib/typescript/atoms/skeleton/skeleton.types.d.ts +3 -2
- package/lib/typescript/atoms/stagger/index.d.ts +2 -0
- package/lib/typescript/atoms/stagger/stagger.d.ts +2 -0
- package/lib/typescript/atoms/stagger/stagger.types.d.ts +32 -0
- package/lib/typescript/atoms/surface/surface.types.d.ts +2 -2
- package/lib/typescript/atoms/text/text.types.d.ts +2 -2
- package/lib/typescript/atoms/v-stack/v-stack.types.d.ts +3 -3
- package/lib/typescript/atoms/z-stack/z-stack.types.d.ts +3 -3
- package/lib/typescript/glyph/glyph.types.d.ts +2 -0
- package/lib/typescript/molecules/labeled-content/labeled-content.types.d.ts +4 -2
- package/lib/typescript/molecules/link/link.types.d.ts +2 -1
- package/lib/typescript/molecules/list-item/list-item.types.d.ts +5 -3
- package/lib/typescript/molecules/stepper/stepper.ios.d.ts +1 -1
- package/lib/typescript/organisms/fab-menu/fab-menu.types.d.ts +5 -0
- package/lib/typescript/organisms/snackbar/snackbar.types.d.ts +35 -4
- package/lib/typescript/use-stack-modifiers.d.ts +6 -5
- package/package.json +4 -4
- package/src/atoms/activity-indicator/activity-indicator.android.tsx +7 -1
- package/src/atoms/activity-indicator/activity-indicator.ios.tsx +9 -1
- package/src/atoms/activity-indicator/activity-indicator.types.ts +2 -0
- package/src/atoms/avatar/avatar.tsx +5 -1
- package/src/atoms/avatar/avatar.types.ts +5 -0
- package/src/atoms/box/box.tsx +3 -0
- package/src/atoms/box/index.ts +0 -1
- package/src/atoms/button/button-tokens.ts +2 -2
- package/src/atoms/button/button.android.tsx +5 -3
- package/src/atoms/button/button.ios.tsx +10 -2
- package/src/atoms/button/button.types.ts +2 -0
- package/src/atoms/card/card.android.tsx +6 -4
- package/src/atoms/card/card.ios.tsx +7 -3
- package/src/atoms/card/card.types.ts +8 -7
- package/src/atoms/checkbox/checkbox.android.tsx +1 -1
- package/src/atoms/fab/fab.android.tsx +5 -3
- package/src/atoms/fab/fab.ios.tsx +8 -4
- package/src/atoms/fab/fab.types.ts +8 -1
- package/src/atoms/glass-view/glass-view.android.tsx +1 -1
- package/src/atoms/h-stack/h-stack.ios.tsx +6 -4
- package/src/atoms/h-stack/h-stack.types.ts +17 -13
- package/src/atoms/icon-button/icon-button.android.tsx +16 -3
- package/src/atoms/icon-button/icon-button.ios.tsx +13 -4
- package/src/atoms/icon-button/icon-button.types.ts +7 -0
- package/src/atoms/image/image.tsx +3 -3
- package/src/atoms/index.ts +1 -0
- package/src/atoms/pressable/pressable.tsx +164 -100
- package/src/atoms/pressable/pressable.types.ts +32 -29
- package/src/atoms/progress/progress.android.tsx +5 -3
- package/src/atoms/progress/progress.ios.tsx +5 -2
- package/src/atoms/progress/progress.types.ts +2 -0
- package/src/atoms/rn-text/rn-text.tsx +101 -32
- package/src/atoms/rn-text/rn-text.types.ts +7 -3
- package/src/atoms/segmented-control/segmented-control.android.tsx +1 -1
- package/src/atoms/segmented-control/segmented-control.ios.tsx +1 -1
- package/src/atoms/skeleton/skeleton.tsx +20 -6
- package/src/atoms/skeleton/skeleton.types.ts +3 -2
- package/src/atoms/stagger/index.ts +2 -0
- package/src/atoms/stagger/stagger.tsx +98 -0
- package/src/atoms/stagger/stagger.types.ts +35 -0
- package/src/atoms/surface/surface.android.tsx +6 -4
- package/src/atoms/surface/surface.ios.tsx +7 -3
- package/src/atoms/surface/surface.types.ts +10 -9
- package/src/atoms/switch/switch.android.tsx +1 -1
- package/src/atoms/text/text.android.tsx +6 -4
- package/src/atoms/text/text.ios.tsx +6 -4
- package/src/atoms/text/text.types.ts +23 -22
- package/src/atoms/v-stack/v-stack.ios.tsx +6 -4
- package/src/atoms/v-stack/v-stack.types.ts +17 -16
- package/src/atoms/z-stack/z-stack.ios.tsx +6 -4
- package/src/atoms/z-stack/z-stack.types.ts +15 -14
- package/src/glyph/glyph.android.tsx +14 -2
- package/src/glyph/glyph.ios.tsx +13 -3
- package/src/glyph/glyph.types.ts +2 -0
- package/src/molecules/collapsible/collapsible.android.tsx +27 -7
- package/src/molecules/labeled-content/labeled-content.tsx +12 -1
- package/src/molecules/labeled-content/labeled-content.types.ts +4 -2
- package/src/molecules/link/link.tsx +2 -1
- package/src/molecules/link/link.types.ts +2 -1
- package/src/molecules/list-item/list-item.tsx +20 -2
- package/src/molecules/list-item/list-item.types.ts +5 -3
- package/src/molecules/navigation-bar/navigation-bar.android.tsx +1 -1
- package/src/molecules/navigation-bar/navigation-bar.ios.tsx +1 -1
- package/src/molecules/rn-list-item/rn-list-item.tsx +18 -3
- package/src/molecules/scroll-edge-container/scroll-edge-container.android.tsx +5 -4
- package/src/molecules/stepper/stepper.ios.tsx +8 -2
- package/src/organisms/fab-menu/fab-menu.android.tsx +9 -5
- package/src/organisms/fab-menu/fab-menu.ios.tsx +6 -2
- package/src/organisms/fab-menu/fab-menu.types.ts +5 -0
- package/src/organisms/snackbar/snackbar.tsx +125 -21
- package/src/organisms/snackbar/snackbar.types.ts +38 -4
- package/src/organisms/swipe-actions/swipe-actions.android.tsx +1 -1
- package/src/use-stack-modifiers.ts +20 -7
- package/lib/module/atoms/box/a-box.js +0 -6
- package/lib/module/atoms/box/a-box.js.map +0 -1
- package/lib/typescript/atoms/box/a-box.d.ts +0 -49
- package/src/atoms/box/a-box.ts +0 -5
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type ModifierConfig } from '@expo/ui/jetpack-compose/modifiers';
|
|
2
|
-
import { type ResponsiveSx } from '@hzblj/kara-sx';
|
|
2
|
+
import { type AccessibilityProps, type ResponsiveSx } from '@hzblj/kara-sx';
|
|
3
3
|
/**
|
|
4
|
-
* A Compose stack's modifiers in the order a pressable one needs: its frame, shape and background, then the press,
|
|
5
|
-
* then its padding. Compose clips a `clickable` to what comes after it, so with the padding first the ripple
|
|
6
|
-
* at the padding and a row pressed by its edge would light up only in the middle.
|
|
4
|
+
* A Compose stack's modifiers in the order a pressable one needs: its frame, shape and background, then the press, its
|
|
5
|
+
* semantics, then its padding. Compose clips a `clickable` to what comes after it, so with the padding first the ripple
|
|
6
|
+
* would stop at the padding and a row pressed by its edge would light up only in the middle. The semantics come after
|
|
7
|
+
* the click, because a label that replaces the children's clears whatever semantics are inside it.
|
|
7
8
|
*/
|
|
8
|
-
export declare const useStackModifiers: (
|
|
9
|
+
export declare const useStackModifiers: (props: ResponsiveSx & AccessibilityProps, onPress?: () => void, testID?: string) => ModifierConfig[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hzblj/kara-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "The atoms, molecules, organisms and templates of @hzblj/kara-ui — real SwiftUI and Jetpack Compose views through @expo/ui.",
|
|
5
5
|
"author": "Jan Blazej",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
]
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@hzblj/kara-native": "^0.
|
|
63
|
-
"@hzblj/kara-sx": "^0.
|
|
64
|
-
"@hzblj/kara-theme": "^0.
|
|
62
|
+
"@hzblj/kara-native": "^0.12.0",
|
|
63
|
+
"@hzblj/kara-sx": "^0.12.0",
|
|
64
|
+
"@hzblj/kara-theme": "^0.12.0",
|
|
65
65
|
"sf-symbols-typescript": "^2.2.0"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Host, LoadingIndicator} from '@expo/ui/jetpack-compose'
|
|
2
2
|
import {fillMaxSize, testID as testIdModifier} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
|
+
import {useAccessibilityModifiers} from '@hzblj/kara-sx'
|
|
3
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
5
|
import {useMemo} from 'react'
|
|
5
6
|
import {StyleSheet} from 'react-native'
|
|
@@ -17,12 +18,17 @@ const styles = StyleSheet.create({
|
|
|
17
18
|
* anywhere and takes its place in the first frame.
|
|
18
19
|
*/
|
|
19
20
|
export const ActivityIndicator: ActivityIndicatorComponent = ({
|
|
21
|
+
accessibilityLabel,
|
|
20
22
|
color = 'fill.accent.primary',
|
|
21
23
|
size = 'small',
|
|
22
24
|
testID,
|
|
23
25
|
}: ActivityIndicatorProps) => {
|
|
24
26
|
const theme = useAppTheme()
|
|
25
|
-
const
|
|
27
|
+
const accessibilityModifiers = useAccessibilityModifiers({accessibilityLabel})
|
|
28
|
+
const modifiers = useMemo(
|
|
29
|
+
() => [fillMaxSize(), ...(testID ? [testIdModifier(testID)] : []), ...accessibilityModifiers],
|
|
30
|
+
[accessibilityModifiers, testID]
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
return (
|
|
28
34
|
<Host colorScheme={theme.dark ? 'dark' : 'light'} seedColor={theme.materialSeed} style={styles[size]}>
|
|
@@ -5,11 +5,19 @@ import type {ActivityIndicatorComponent, ActivityIndicatorProps} from './activit
|
|
|
5
5
|
|
|
6
6
|
/** React Native's spinner, which on iOS is UIKit's own `UIActivityIndicatorView`. */
|
|
7
7
|
export const ActivityIndicator: ActivityIndicatorComponent = ({
|
|
8
|
+
accessibilityLabel,
|
|
8
9
|
color = 'fill.accent.primary',
|
|
9
10
|
size = 'small',
|
|
10
11
|
testID,
|
|
11
12
|
}: ActivityIndicatorProps) => {
|
|
12
13
|
const theme = useAppTheme()
|
|
13
14
|
|
|
14
|
-
return
|
|
15
|
+
return (
|
|
16
|
+
<RNActivityIndicator
|
|
17
|
+
accessibilityLabel={accessibilityLabel}
|
|
18
|
+
color={theme.color(color)}
|
|
19
|
+
size={size}
|
|
20
|
+
testID={testID}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
15
23
|
}
|
|
@@ -9,6 +9,8 @@ export type ActivityIndicatorSize = 'large' | 'small'
|
|
|
9
9
|
* Android, so it renders anywhere. For how far along something is, use `Progress`.
|
|
10
10
|
*/
|
|
11
11
|
export type ActivityIndicatorProps = {
|
|
12
|
+
/** What is loading, for VoiceOver and TalkBack: "Loading photos". Unset, the platform's own word ("In progress"). */
|
|
13
|
+
accessibilityLabel?: string
|
|
12
14
|
/** Its colour. `fill.accent.primary` by default. */
|
|
13
15
|
color?: ColorToken
|
|
14
16
|
/** `small` sits in a row or a button, `large` holds a screen that is loading. `small` by default. */
|
|
@@ -17,11 +17,15 @@ const VARIANT = {
|
|
|
17
17
|
sm: 'caption',
|
|
18
18
|
} as const
|
|
19
19
|
|
|
20
|
-
export const Avatar: AvatarComponent = ({initials, size = 'md', source, testID}: AvatarProps) => {
|
|
20
|
+
export const Avatar: AvatarComponent = ({accessibilityLabel, initials, size = 'md', source, testID}: AvatarProps) => {
|
|
21
21
|
const diameter = DIAMETER[size]
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<Box
|
|
25
|
+
aria-hidden={accessibilityLabel === undefined}
|
|
26
|
+
accessibilityLabel={accessibilityLabel}
|
|
27
|
+
accessibilityRole={accessibilityLabel === undefined ? undefined : 'image'}
|
|
28
|
+
accessible={accessibilityLabel !== undefined}
|
|
25
29
|
align="center"
|
|
26
30
|
bg="fill.tertiary"
|
|
27
31
|
borderRadius="full"
|
|
@@ -5,6 +5,11 @@ export type AvatarSize = 'lg' | 'md' | 'sm'
|
|
|
5
5
|
|
|
6
6
|
/** A round avatar: the image in `source`, or `initials` without one. The React Native tier: it needs no host. */
|
|
7
7
|
export type AvatarProps = {
|
|
8
|
+
/**
|
|
9
|
+
* Who it is, for VoiceOver and TalkBack: "Jan Blazej". Unset, the avatar is decorative and hidden from them, as one
|
|
10
|
+
* beside the person's name should be.
|
|
11
|
+
*/
|
|
12
|
+
accessibilityLabel?: string
|
|
8
13
|
/** Shown in place of the image when there is no `source`. */
|
|
9
14
|
initials?: string
|
|
10
15
|
/** The diameter: `sm` is `s24`, `md` `s40`, `lg` `s64`. `md` by default. */
|
package/src/atoms/box/box.tsx
CHANGED
|
@@ -4,5 +4,8 @@ import {View} from 'react-native'
|
|
|
4
4
|
/**
|
|
5
5
|
* A React Native `View` that takes the design system's `sx` props. The `sx()` HOC is the whole
|
|
6
6
|
* implementation — Box is just its first caller, and any other style-taking component gets the same.
|
|
7
|
+
*
|
|
8
|
+
* That includes motion: `entering`, `exiting`, `layout`, `animate` or an animated `style` make it an `Animated.View`
|
|
9
|
+
* from its first frame, and without them it stays a plain `View`.
|
|
7
10
|
*/
|
|
8
11
|
export const Box = sx(View)
|
package/src/atoms/box/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ type ButtonTokens = {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const TOKENS = {
|
|
12
|
-
accent: {content: 'content.on.
|
|
12
|
+
accent: {content: 'content.on.accent', fill: 'fill.accent.primary', shadow: 'btn.accent'},
|
|
13
13
|
destructive: {content: 'content.on.destructive', fill: 'fill.destructive.primary', shadow: 'btn.destructive'},
|
|
14
14
|
glass: {content: 'content.primary', fill: 'btn.bg.glass.base', shadow: 'btn.glass'},
|
|
15
15
|
secondary: {content: 'content.primary', fill: 'btn.bg.secondary.base', shadow: 'btn.secondary'},
|
|
@@ -81,4 +81,4 @@ const currentHex = (token: ColorToken, theme: Theme): unknown => {
|
|
|
81
81
|
* content colour over a pale one (`fill.accent.base`) — the light container tokens pair with it in both appearances.
|
|
82
82
|
*/
|
|
83
83
|
export const contentOnTint = (tint: ColorToken, theme: Theme): ColorToken =>
|
|
84
|
-
(luminance(currentHex(tint, theme)) ?? 0) > 0.4 ? 'content.primary' : 'content.on.
|
|
84
|
+
(luminance(currentHex(tint, theme)) ?? 0) > 0.4 ? 'content.primary' : 'content.on.accent'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Button as ComposeButton, Text as ComposeText, OutlinedButton} from '@expo/ui/jetpack-compose'
|
|
2
2
|
import {testID as testIdModifier} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
|
-
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
3
|
+
import {useAccessibilityModifiers, useSxModifiers} from '@hzblj/kara-sx'
|
|
4
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
5
5
|
import {useMemo} from 'react'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
@@ -16,6 +16,7 @@ import {buttonTokens, contentOnTint} from './button-tokens'
|
|
|
16
16
|
* colour, as a prominent style does on iOS. `buttonStyle` and `controlSize` are SwiftUI's alone.
|
|
17
17
|
*/
|
|
18
18
|
export const Button: ButtonComponent = ({
|
|
19
|
+
accessibilityHint,
|
|
19
20
|
disabled = false,
|
|
20
21
|
label,
|
|
21
22
|
onPress,
|
|
@@ -28,9 +29,10 @@ export const Button: ButtonComponent = ({
|
|
|
28
29
|
const theme = useAppTheme()
|
|
29
30
|
const tokens = buttonTokens(variant, disabled, theme)
|
|
30
31
|
const sxModifiers = useSxModifiers({wide})
|
|
32
|
+
const accessibilityModifiers = useAccessibilityModifiers({accessibilityHint}, accessibilityHint !== undefined)
|
|
31
33
|
const modifiers = useMemo(
|
|
32
|
-
() => (testID ? [
|
|
33
|
-
[sxModifiers, testID]
|
|
34
|
+
() => [...sxModifiers, ...(testID ? [testIdModifier(testID)] : []), ...accessibilityModifiers],
|
|
35
|
+
[accessibilityModifiers, sxModifiers, testID]
|
|
34
36
|
)
|
|
35
37
|
const style = theme.typography.body
|
|
36
38
|
const outlined = variant === 'glass' && !tint
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
glassEffect as glassEffectModifier,
|
|
7
7
|
tint as tintModifier,
|
|
8
8
|
} from '@expo/ui/swift-ui/modifiers'
|
|
9
|
+
import {useAccessibilityModifiers} from '@hzblj/kara-sx'
|
|
9
10
|
import {type ColorToken, useAppTheme} from '@hzblj/kara-theme'
|
|
10
11
|
import {useMemo} from 'react'
|
|
11
12
|
import {useHostGuard} from '../../host-context'
|
|
@@ -29,6 +30,7 @@ const TINT_BY_VARIANT = {
|
|
|
29
30
|
} as const satisfies Record<ButtonVariant, ColorToken | undefined>
|
|
30
31
|
|
|
31
32
|
export const Button: ButtonComponent = ({
|
|
33
|
+
accessibilityHint,
|
|
32
34
|
buttonStyle,
|
|
33
35
|
controlSize = 'large',
|
|
34
36
|
disabled = false,
|
|
@@ -59,8 +61,14 @@ export const Button: ButtonComponent = ({
|
|
|
59
61
|
// A prominent style — and tinted glass — is coloured by the tint, so a caller's own tint picks the label on it.
|
|
60
62
|
const content = tint && filled && !disabled ? contentOnTint(tint, theme) : tokens.content
|
|
61
63
|
|
|
64
|
+
const accessibilityModifiers = useAccessibilityModifiers({accessibilityHint})
|
|
65
|
+
|
|
62
66
|
const modifiers = useMemo(() => {
|
|
63
|
-
const list = [
|
|
67
|
+
const list = [
|
|
68
|
+
buttonStyleModifier(glassTint ? 'plain' : style),
|
|
69
|
+
controlSizeModifier(controlSize),
|
|
70
|
+
...accessibilityModifiers,
|
|
71
|
+
]
|
|
64
72
|
|
|
65
73
|
if (glassTint) {
|
|
66
74
|
list.push(
|
|
@@ -75,7 +83,7 @@ export const Button: ButtonComponent = ({
|
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
return list
|
|
78
|
-
}, [controlSize, disabled, glassTint, resolvedTint, style, theme])
|
|
86
|
+
}, [accessibilityModifiers, controlSize, disabled, glassTint, resolvedTint, style, theme])
|
|
79
87
|
|
|
80
88
|
return (
|
|
81
89
|
<SwiftUIButton modifiers={modifiers} onPress={onPress} testID={testID}>
|
|
@@ -24,6 +24,8 @@ export type ButtonControlSize = 'extraLarge' | 'large' | 'mini' | 'regular' | 's
|
|
|
24
24
|
|
|
25
25
|
/** A text button: SwiftUI `Button` on iOS, Material's filled button (outlined for `glass`) on Android. */
|
|
26
26
|
export type ButtonProps = {
|
|
27
|
+
/** What pressing it does, when the label alone does not say. See `AccessibilityProps`. */
|
|
28
|
+
accessibilityHint?: string
|
|
27
29
|
/**
|
|
28
30
|
* Replaces the style the variant picks: `borderedProminent` for `accent` and `destructive`, `bordered` for
|
|
29
31
|
* `secondary`, `glass` for `glass`. iOS only. Android ignores it.
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {Column} from '@expo/ui/jetpack-compose'
|
|
2
2
|
import {testID as testIdModifier} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
|
-
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
3
|
+
import {splitAccessibility, useAccessibilityModifiers, useSxModifiers} from '@hzblj/kara-sx'
|
|
4
4
|
import {useMemo} from 'react'
|
|
5
5
|
import {useHostGuard} from '../../host-context'
|
|
6
6
|
import type {CardComponent, CardProps} from './card.types'
|
|
7
7
|
|
|
8
|
-
export const Card: CardComponent = ({children, testID, ...
|
|
8
|
+
export const Card: CardComponent = ({children, testID, ...props}: CardProps) => {
|
|
9
9
|
useHostGuard('Card')
|
|
10
|
+
const [accessibility, sx] = splitAccessibility(props)
|
|
10
11
|
const sxModifiers = useSxModifiers({bg: 'surface.primary', borderRadius: 'large', p: 's16', shadow: 'card', ...sx})
|
|
12
|
+
const accessibilityModifiers = useAccessibilityModifiers(accessibility)
|
|
11
13
|
const modifiers = useMemo(
|
|
12
|
-
() => (testID ? [
|
|
13
|
-
[sxModifiers, testID]
|
|
14
|
+
() => [...sxModifiers, ...(testID ? [testIdModifier(testID)] : []), ...accessibilityModifiers],
|
|
15
|
+
[accessibilityModifiers, sxModifiers, testID]
|
|
14
16
|
)
|
|
15
17
|
|
|
16
18
|
return <Column modifiers={modifiers}>{children}</Column>
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {VStack} from '@expo/ui/swift-ui'
|
|
2
|
-
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
2
|
+
import {splitAccessibility, useAccessibilityModifiers, useSxModifiers} from '@hzblj/kara-sx'
|
|
3
|
+
import {useMemo} from 'react'
|
|
3
4
|
import {useHostGuard} from '../../host-context'
|
|
4
5
|
import type {CardComponent, CardProps} from './card.types'
|
|
5
6
|
|
|
6
|
-
export const Card: CardComponent = ({children, testID, ...
|
|
7
|
+
export const Card: CardComponent = ({children, testID, ...props}: CardProps) => {
|
|
7
8
|
useHostGuard('Card')
|
|
8
|
-
const
|
|
9
|
+
const [accessibility, sx] = splitAccessibility(props)
|
|
10
|
+
const sxModifiers = useSxModifiers({bg: 'surface.primary', borderRadius: 'large', p: 's16', shadow: 'card', ...sx})
|
|
11
|
+
const accessibilityModifiers = useAccessibilityModifiers(accessibility)
|
|
12
|
+
const modifiers = useMemo(() => [...sxModifiers, ...accessibilityModifiers], [accessibilityModifiers, sxModifiers])
|
|
9
13
|
|
|
10
14
|
return (
|
|
11
15
|
<VStack alignment="leading" modifiers={modifiers} testID={testID}>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type {ResponsiveSx} from '@hzblj/kara-sx'
|
|
1
|
+
import type {AccessibilityProps, ResponsiveSx} from '@hzblj/kara-sx'
|
|
2
2
|
import type {ReactNode} from 'react'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A raised container: SwiftUI `VStack` / Compose `Column` on `surface.primary`, with a large radius, `s16` padding and
|
|
6
6
|
* the `card` shadow. Any `sx` prop overrides its default.
|
|
7
7
|
*/
|
|
8
|
-
export type CardProps = ResponsiveSx &
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export type CardProps = ResponsiveSx &
|
|
9
|
+
AccessibilityProps & {
|
|
10
|
+
/** Native views, stacked vertically from the leading edge. */
|
|
11
|
+
children?: ReactNode
|
|
12
|
+
/** Test identifier, forwarded to the native view. */
|
|
13
|
+
testID?: string
|
|
14
|
+
}
|
|
14
15
|
|
|
15
16
|
export type CardComponent = (props: CardProps) => ReactNode
|
|
@@ -23,7 +23,7 @@ export const Checkbox: CheckboxComponent = ({disabled = false, label, onValueCha
|
|
|
23
23
|
)
|
|
24
24
|
const control = (
|
|
25
25
|
<ComposeCheckbox
|
|
26
|
-
colors={{checkedColor: theme.color('fill.accent.primary'), checkmarkColor: theme.color('content.on.
|
|
26
|
+
colors={{checkedColor: theme.color('fill.accent.primary'), checkmarkColor: theme.color('content.on.accent')}}
|
|
27
27
|
enabled={!disabled}
|
|
28
28
|
onCheckedChange={onValueChange ?? NOOP}
|
|
29
29
|
value={value}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import {FloatingActionButton} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {useAccessibilityModifiers} from '@hzblj/kara-sx'
|
|
2
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
3
4
|
|
|
4
5
|
import {useHostGuard} from '../../host-context'
|
|
5
6
|
import {Icon} from '../icon'
|
|
6
7
|
import type {FabComponent, FabProps} from './fab.types'
|
|
7
8
|
|
|
8
|
-
export const Fab: FabComponent = ({name, onPress}: FabProps) => {
|
|
9
|
+
export const Fab: FabComponent = ({accessibilityHint, accessibilityLabel, name, onPress}: FabProps) => {
|
|
9
10
|
useHostGuard('Fab')
|
|
10
11
|
|
|
11
12
|
const theme = useAppTheme()
|
|
13
|
+
const modifiers = useAccessibilityModifiers({accessibilityHint}, accessibilityHint !== undefined)
|
|
12
14
|
|
|
13
15
|
return (
|
|
14
|
-
<FloatingActionButton containerColor={theme.color('fill.accent.primary')} onClick={onPress}>
|
|
16
|
+
<FloatingActionButton containerColor={theme.color('fill.accent.primary')} modifiers={modifiers} onClick={onPress}>
|
|
15
17
|
{/* `@expo/ui`'s FAB is slot-based: content outside `.Icon` is not composed at all. */}
|
|
16
18
|
<FloatingActionButton.Icon>
|
|
17
|
-
<Icon color="content.on.
|
|
19
|
+
<Icon accessibilityLabel={accessibilityLabel} color="content.on.accent" name={name} />
|
|
18
20
|
</FloatingActionButton.Icon>
|
|
19
21
|
</FloatingActionButton>
|
|
20
22
|
)
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {Button} from '@expo/ui/swift-ui'
|
|
2
2
|
import {buttonStyle} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
-
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
3
|
+
import {useAccessibilityModifiers, useSxModifiers} from '@hzblj/kara-sx'
|
|
4
4
|
import {useMemo} from 'react'
|
|
5
5
|
import {useHostGuard} from '../../host-context'
|
|
6
6
|
import {Icon} from '../icon'
|
|
7
7
|
import type {FabComponent, FabProps} from './fab.types'
|
|
8
8
|
|
|
9
|
-
export const Fab: FabComponent = ({name, onPress, testID}: FabProps) => {
|
|
9
|
+
export const Fab: FabComponent = ({accessibilityHint, accessibilityLabel, name, onPress, testID}: FabProps) => {
|
|
10
10
|
useHostGuard('Fab')
|
|
11
|
+
const accessibilityModifiers = useAccessibilityModifiers({accessibilityHint})
|
|
11
12
|
|
|
12
13
|
const sxModifiers = useSxModifiers({
|
|
13
14
|
bg: 'fill.accent.primary',
|
|
@@ -17,11 +18,14 @@ export const Fab: FabComponent = ({name, onPress, testID}: FabProps) => {
|
|
|
17
18
|
shadow: 'btn.accent',
|
|
18
19
|
w: 56,
|
|
19
20
|
})
|
|
20
|
-
const modifiers = useMemo(
|
|
21
|
+
const modifiers = useMemo(
|
|
22
|
+
() => [buttonStyle('plain'), ...sxModifiers, ...accessibilityModifiers],
|
|
23
|
+
[accessibilityModifiers, sxModifiers]
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
return (
|
|
23
27
|
<Button modifiers={modifiers} onPress={onPress} testID={testID}>
|
|
24
|
-
<Icon color="content.on.
|
|
28
|
+
<Icon accessibilityLabel={accessibilityLabel} color="content.on.accent" name={name} />
|
|
25
29
|
</Button>
|
|
26
30
|
)
|
|
27
31
|
}
|
|
@@ -7,7 +7,14 @@ import type {IconName} from '../icon'
|
|
|
7
7
|
* `Button`) on iOS. It renders inline; pinning it to a corner is up to the screen.
|
|
8
8
|
*/
|
|
9
9
|
export type FabProps = {
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* What VoiceOver and TalkBack say for the button, since an icon has no words of its own: "Share", "Add to
|
|
12
|
+
* favourites". Required for that reason.
|
|
13
|
+
*/
|
|
14
|
+
accessibilityLabel: string
|
|
15
|
+
/** What pressing it does, when the label alone does not say. See `AccessibilityProps`. */
|
|
16
|
+
accessibilityHint?: string
|
|
17
|
+
/** The icon, one of the app's, drawn in `content.on.accent`. */
|
|
11
18
|
name: IconName
|
|
12
19
|
/** Called when the button is pressed. */
|
|
13
20
|
onPress?: () => void
|
|
@@ -31,7 +31,7 @@ export const GlassView: GlassViewComponent = ({
|
|
|
31
31
|
cornerRadius={radii.full}
|
|
32
32
|
fallbackTint={withOpacity(base, 'o95')}
|
|
33
33
|
glassTint={withOpacity(base, tint ? 'o85' : 'o50')}
|
|
34
|
-
hairlineColor={withOpacity(String(theme.color('content.on.
|
|
34
|
+
hairlineColor={withOpacity(String(theme.color('content.on.accent')), theme.dark ? 'o20' : 'o60')}
|
|
35
35
|
hairlineWidth={1}
|
|
36
36
|
saturation={1.6}
|
|
37
37
|
style={style}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {HStack as SwiftUIHStack} from '@expo/ui/swift-ui'
|
|
2
2
|
import {onTapGesture} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
-
import {type FrameAlignment, useSxModifiers} from '@hzblj/kara-sx'
|
|
3
|
+
import {type FrameAlignment, splitAccessibility, useAccessibilityModifiers, useSxModifiers} from '@hzblj/kara-sx'
|
|
4
4
|
import {spacing} from '@hzblj/kara-theme'
|
|
5
5
|
import {useMemo} from 'react'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
@@ -24,13 +24,15 @@ export const HStack: HStackComponent = ({
|
|
|
24
24
|
onPress,
|
|
25
25
|
spacing: gap,
|
|
26
26
|
testID,
|
|
27
|
-
...
|
|
27
|
+
...props
|
|
28
28
|
}: HStackProps) => {
|
|
29
29
|
useHostGuard('HStack')
|
|
30
|
+
const [accessibility, sx] = splitAccessibility(props)
|
|
30
31
|
const sxModifiers = useSxModifiers(sx, FRAME_ALIGNMENT[align])
|
|
32
|
+
const accessibilityModifiers = useAccessibilityModifiers(accessibility, onPress !== undefined)
|
|
31
33
|
const modifiers = useMemo(
|
|
32
|
-
() => (onPress ? [
|
|
33
|
-
[onPress, sxModifiers]
|
|
34
|
+
() => [...sxModifiers, ...(onPress ? [onTapGesture(onPress)] : []), ...accessibilityModifiers],
|
|
35
|
+
[accessibilityModifiers, onPress, sxModifiers]
|
|
34
36
|
)
|
|
35
37
|
|
|
36
38
|
return (
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import type {ResponsiveSx} from '@hzblj/kara-sx'
|
|
1
|
+
import type {AccessibilityProps, ResponsiveSx} from '@hzblj/kara-sx'
|
|
2
2
|
import type {SpaceSize} from '@hzblj/kara-theme'
|
|
3
3
|
import type {ReactNode} from 'react'
|
|
4
4
|
|
|
5
5
|
export type HStackAlign = 'center' | 'end' | 'start'
|
|
6
6
|
|
|
7
7
|
/** A horizontal stack: SwiftUI `HStack` / Compose `Row`. */
|
|
8
|
-
export type HStackProps = ResponsiveSx &
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
export type HStackProps = ResponsiveSx &
|
|
9
|
+
AccessibilityProps & {
|
|
10
|
+
/** How the children line up vertically: `start` is the top, `end` the bottom. `start` by default. */
|
|
11
|
+
align?: HStackAlign
|
|
12
|
+
/** Native views, laid out from the leading edge. */
|
|
13
|
+
children?: ReactNode
|
|
14
|
+
/**
|
|
15
|
+
* Makes the stack pressable: a tap gesture on iOS, a `clickable` with Material's ripple on Android. Screen readers
|
|
16
|
+
* then read the stack as one button.
|
|
17
|
+
*/
|
|
18
|
+
onPress?: () => void
|
|
19
|
+
/** The gap between children. Unset, SwiftUI puts its default spacing between them and Compose none. */
|
|
20
|
+
spacing?: SpaceSize
|
|
21
|
+
/** Test identifier, forwarded to the native view. */
|
|
22
|
+
testID?: string
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
export type HStackComponent = (props: HStackProps) => ReactNode
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import {IconButton as ComposeIconButton} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {useAccessibilityModifiers} from '@hzblj/kara-sx'
|
|
2
3
|
|
|
3
4
|
import {useHostGuard} from '../../host-context'
|
|
4
5
|
import {Icon} from '../icon'
|
|
5
6
|
import type {IconButtonComponent, IconButtonProps} from './icon-button.types'
|
|
6
7
|
|
|
7
|
-
export const IconButton: IconButtonComponent = ({
|
|
8
|
+
export const IconButton: IconButtonComponent = ({
|
|
9
|
+
accessibilityHint,
|
|
10
|
+
accessibilityLabel,
|
|
11
|
+
disabled = false,
|
|
12
|
+
name,
|
|
13
|
+
onPress,
|
|
14
|
+
}: IconButtonProps) => {
|
|
8
15
|
useHostGuard('IconButton')
|
|
16
|
+
// The label rides on the icon, as Material's own icon buttons carry it; the hint labels the click.
|
|
17
|
+
const modifiers = useAccessibilityModifiers({accessibilityHint}, accessibilityHint !== undefined)
|
|
9
18
|
|
|
10
19
|
return (
|
|
11
|
-
<ComposeIconButton enabled={!disabled} onClick={onPress}>
|
|
12
|
-
<Icon
|
|
20
|
+
<ComposeIconButton enabled={!disabled} modifiers={modifiers} onClick={onPress}>
|
|
21
|
+
<Icon
|
|
22
|
+
accessibilityLabel={accessibilityLabel}
|
|
23
|
+
color={disabled ? 'btn.content.disabled' : 'content.primary'}
|
|
24
|
+
name={name}
|
|
25
|
+
/>
|
|
13
26
|
</ComposeIconButton>
|
|
14
27
|
)
|
|
15
28
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Button} from '@expo/ui/swift-ui'
|
|
2
2
|
import {buttonStyle, contentShape, disabled as disabledModifier, shapes} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
+
import {useAccessibilityModifiers} from '@hzblj/kara-sx'
|
|
3
4
|
import {useMemo} from 'react'
|
|
4
5
|
|
|
5
6
|
import {useHostGuard} from '../../host-context'
|
|
@@ -13,24 +14,32 @@ const TARGET = 44
|
|
|
13
14
|
/** The whole square takes the tap, not only the glyph's own pixels. */
|
|
14
15
|
const WHOLE_TARGET = {modifiers: [contentShape(shapes.circle())]}
|
|
15
16
|
|
|
16
|
-
export const IconButton: IconButtonComponent = ({
|
|
17
|
+
export const IconButton: IconButtonComponent = ({
|
|
18
|
+
accessibilityHint,
|
|
19
|
+
accessibilityLabel,
|
|
20
|
+
disabled = false,
|
|
21
|
+
name,
|
|
22
|
+
onPress,
|
|
23
|
+
testID,
|
|
24
|
+
}: IconButtonProps) => {
|
|
17
25
|
useHostGuard('IconButton')
|
|
26
|
+
const accessibilityModifiers = useAccessibilityModifiers({accessibilityHint})
|
|
18
27
|
|
|
19
28
|
const modifiers = useMemo(() => {
|
|
20
|
-
const list = [buttonStyle('plain')]
|
|
29
|
+
const list = [buttonStyle('plain'), ...accessibilityModifiers]
|
|
21
30
|
|
|
22
31
|
if (disabled) {
|
|
23
32
|
list.push(disabledModifier(true))
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
return list
|
|
27
|
-
}, [disabled])
|
|
36
|
+
}, [accessibilityModifiers, disabled])
|
|
28
37
|
|
|
29
38
|
return (
|
|
30
39
|
<Button modifiers={modifiers} onPress={onPress} testID={testID}>
|
|
31
40
|
<ZStack h={TARGET} ios={WHOLE_TARGET} w={TARGET}>
|
|
32
41
|
{/* SwiftUI dims a disabled button's label itself; a disabled colour on top of that dimmed it twice. */}
|
|
33
|
-
<Icon color="content.primary" name={name} />
|
|
42
|
+
<Icon accessibilityLabel={accessibilityLabel} color="content.primary" name={name} />
|
|
34
43
|
</ZStack>
|
|
35
44
|
</Button>
|
|
36
45
|
)
|
|
@@ -8,6 +8,13 @@ import type {IconName} from '../icon'
|
|
|
8
8
|
* itself the same way on both.
|
|
9
9
|
*/
|
|
10
10
|
export type IconButtonProps = {
|
|
11
|
+
/**
|
|
12
|
+
* What VoiceOver and TalkBack say for the button, since an icon has no words of its own: "Share", "Add to
|
|
13
|
+
* favourites". Required for that reason.
|
|
14
|
+
*/
|
|
15
|
+
accessibilityLabel: string
|
|
16
|
+
/** What pressing it does, when the label alone does not say. See `AccessibilityProps`. */
|
|
17
|
+
accessibilityHint?: string
|
|
11
18
|
/** Dims the icon (iOS's own disabled look, `btn.content.disabled` on Android) and stops the button responding. */
|
|
12
19
|
disabled?: boolean
|
|
13
20
|
/** The icon, one of the app's. */
|
|
@@ -3,12 +3,12 @@ import {duration} from '@hzblj/kara-theme'
|
|
|
3
3
|
import {Image as ExpoImage, type ImageProps as ExpoImageProps} from 'expo-image'
|
|
4
4
|
import type {Ref} from 'react'
|
|
5
5
|
|
|
6
|
-
const FADE = {duration: duration.
|
|
6
|
+
const FADE = {duration: duration.quick, timing: 'ease-out'} as const
|
|
7
7
|
|
|
8
8
|
const FadingImage = (props: ExpoImageProps & {ref?: Ref<ExpoImage>}) => <ExpoImage transition={FADE} {...props} />
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* `expo-image` with the `sx` props, the way `Box` is a `View` with them, and the design system's
|
|
12
|
-
* already applied, so a loaded image never pops in. An explicit `transition` wins, and so does an explicit `style`.
|
|
11
|
+
* `expo-image` with the `sx` props, the way `Box` is a `View` with them, and the design system's fade (`quick`,
|
|
12
|
+
* eased out) already applied, so a loaded image never pops in. An explicit `transition` wins, and so does an explicit `style`.
|
|
13
13
|
*/
|
|
14
14
|
export const Image = sx(FadingImage)
|
package/src/atoms/index.ts
CHANGED