@juspay/blend-design-system 0.0.37-beta.8 → 0.0.37
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/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/AccordionV2/accordionV2.animations.d.ts +1 -1
- package/dist/components/Alert/index.d.ts +1 -0
- package/dist/components/Avatar/index.d.ts +1 -0
- package/dist/components/Breadcrumb/index.d.ts +1 -0
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/ButtonGroup/index.d.ts +1 -0
- package/dist/components/Card/index.d.ts +1 -0
- package/dist/components/CardV2/CardV2.d.ts +45 -0
- package/dist/components/CardV2/CardV2.utils.d.ts +14 -0
- package/dist/components/CardV2/CardV2Components.d.ts +8 -0
- package/dist/components/CardV2/CardV2Context.d.ts +14 -0
- package/dist/components/CardV2/CardV2Skeleton.d.ts +6 -0
- package/dist/components/CardV2/accessibility/CardV2AccessibilityReport.d.ts +2 -0
- package/dist/components/CardV2/accessibility/index.d.ts +1 -0
- package/dist/components/CardV2/cardV2.dark.tokens.d.ts +3 -0
- package/dist/components/CardV2/cardV2.light.tokens.d.ts +3 -0
- package/dist/components/CardV2/cardV2.tokens.d.ts +5 -0
- package/dist/components/CardV2/cardV2.tokens.types.d.ts +92 -0
- package/dist/components/CardV2/cardV2.types.d.ts +106 -0
- package/dist/components/CardV2/index.d.ts +5 -0
- package/dist/components/Charts/index.d.ts +10 -0
- package/dist/components/Charts/types.d.ts +2 -0
- package/dist/components/ChatInput/index.d.ts +1 -0
- package/dist/components/Checkbox/index.d.ts +1 -0
- package/dist/components/CodeEditor/index.d.ts +1 -0
- package/dist/components/DataTable/PivotTableModal/pivotModal.styled.d.ts +184 -0
- package/dist/components/DataTable/TableBody/types.d.ts +3 -1
- package/dist/components/DataTable/hooks/index.d.ts +2 -0
- package/dist/components/DataTable/hooks/useReducedMotion.d.ts +1 -0
- package/dist/components/DataTable/hooks/useRowFlip.d.ts +6 -0
- package/dist/components/DataTable/types.d.ts +26 -0
- package/dist/components/DateRangePicker/CalendarGrid.d.ts +5 -2
- package/dist/components/DateRangePicker/types.d.ts +3 -1
- package/dist/components/DateRangePicker/utils.d.ts +5 -5
- package/dist/components/Directory/Directory.d.ts +1 -1
- package/dist/components/Directory/NavItem.d.ts +1 -1
- package/dist/components/Directory/Section.d.ts +1 -1
- package/dist/components/Directory/VirtualizedDirectory.d.ts +3 -0
- package/dist/components/Directory/directory.tokens.d.ts +7 -0
- package/dist/components/Directory/types.d.ts +38 -1
- package/dist/components/Directory/utils.d.ts +3 -1
- package/dist/components/Drawer/index.d.ts +1 -0
- package/dist/components/Inputs/MultiValueInput/index.d.ts +1 -0
- package/dist/components/Inputs/NumberInput/index.d.ts +1 -0
- package/dist/components/Inputs/OTPInput/index.d.ts +1 -0
- package/dist/components/Inputs/SearchInput/index.d.ts +1 -0
- package/dist/components/Inputs/TextArea/index.d.ts +1 -0
- package/dist/components/Inputs/TextInput/index.d.ts +1 -0
- package/dist/components/InputsV2/TextAreaV2/utils.d.ts +2 -1
- package/dist/components/InputsV2/TextInputV2/utils.d.ts +2 -1
- package/dist/components/InputsV2/UploadV2/UploadContainerV2.d.ts +24 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.d.ts +31 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.dark.tokens.d.ts +3 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.light.tokens.d.ts +3 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.tokens.d.ts +5 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.tokens.types.d.ts +115 -0
- package/dist/components/InputsV2/UploadV2/UploadV2.types.d.ts +56 -0
- package/dist/components/InputsV2/UploadV2/index.d.ts +3 -0
- package/dist/components/InputsV2/UploadV2/utils.d.ts +32 -0
- package/dist/components/KeyValuePair/index.d.ts +1 -0
- package/dist/components/Menu/Menu.d.ts +1 -1
- package/dist/components/Menu/index.d.ts +1 -0
- package/dist/components/Menu/types.d.ts +7 -0
- package/dist/components/Menu/utils.d.ts +10 -2
- package/dist/components/Modal/index.d.ts +1 -0
- package/dist/components/ModalV2/ModalV2.d.ts +22 -0
- package/dist/components/ModalV2/ModalV2Footer.d.ts +10 -0
- package/dist/components/ModalV2/ModalV2Header.d.ts +15 -0
- package/dist/components/ModalV2/ModalV2Skeleton.d.ts +4 -0
- package/dist/components/ModalV2/index.d.ts +4 -0
- package/dist/components/ModalV2/mobileModalV2.d.ts +23 -0
- package/dist/components/ModalV2/modalAnimationV2.d.ts +3 -0
- package/dist/components/ModalV2/modalV2.dark.tokens.d.ts +3 -0
- package/dist/components/ModalV2/modalV2.light.tokens.d.ts +3 -0
- package/dist/components/ModalV2/modalV2.tokens.d.ts +5 -0
- package/dist/components/ModalV2/modalV2.tokens.types.d.ts +91 -0
- package/dist/components/ModalV2/modalV2.types.d.ts +66 -0
- package/dist/components/MultiSelect/index.d.ts +2 -0
- package/dist/components/Popover/index.d.ts +1 -0
- package/dist/components/Primitives/Block/Block.d.ts +1 -1
- package/dist/components/ProgressBar/index.d.ts +1 -0
- package/dist/components/Radio/index.d.ts +2 -0
- package/dist/components/Sidebar/SidebarContent.d.ts +9 -1
- package/dist/components/Sidebar/index.d.ts +1 -0
- package/dist/components/Sidebar/types.d.ts +9 -1
- package/dist/components/SidebarV2/SidebarV2Panel.d.ts +10 -2
- package/dist/components/SidebarV2/types.d.ts +9 -1
- package/dist/components/SingleSelect/index.d.ts +1 -0
- package/dist/components/Skeleton/SkeletonCompound.d.ts +24 -33
- package/dist/components/Snackbar/index.d.ts +2 -0
- package/dist/components/StatCard/index.d.ts +1 -0
- package/dist/components/Stepper/index.d.ts +1 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Tabs/index.d.ts +1 -0
- package/dist/components/Tags/index.d.ts +1 -0
- package/dist/components/Timeline/Timeline.d.ts +13 -37
- package/dist/components/Tooltip/index.d.ts +1 -0
- package/dist/components/Topbar/index.d.ts +1 -0
- package/dist/components/Upload/index.d.ts +1 -0
- package/dist/context/ThemeContext.d.ts +6 -0
- package/dist/context/useComponentToken.d.ts +4 -1
- package/dist/main.d.ts +6 -0
- package/dist/main.js +45081 -41934
- package/dist/node-B3rrXW84.js +1023 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.js +21 -18
- package/dist/token-engine.js +1 -1
- package/lib/components/Accordion/AccordionItem.tsx +2 -6
- package/lib/components/Accordion/index.ts +2 -0
- package/lib/components/AccordionV2/AccordionV2Item.tsx +1 -1
- package/lib/components/AccordionV2/accordionV2.animations.ts +1 -5
- package/lib/components/Alert/index.ts +1 -0
- package/lib/components/Avatar/index.ts +1 -0
- package/lib/components/Breadcrumb/index.ts +1 -0
- package/lib/components/Button/index.ts +1 -0
- package/lib/components/ButtonGroup/index.ts +1 -0
- package/lib/components/Card/index.ts +1 -0
- package/lib/components/CardV2/CardV2.tsx +327 -0
- package/lib/components/CardV2/CardV2.utils.tsx +77 -0
- package/lib/components/CardV2/CardV2Components.tsx +297 -0
- package/lib/components/CardV2/CardV2Context.tsx +18 -0
- package/lib/components/CardV2/CardV2Skeleton.tsx +40 -0
- package/lib/components/CardV2/accessibility/CardV2AccessibilityReport.ts +284 -0
- package/lib/components/CardV2/accessibility/index.ts +1 -0
- package/lib/components/CardV2/cardV2.dark.tokens.ts +177 -0
- package/lib/components/CardV2/cardV2.light.tokens.ts +177 -0
- package/lib/components/CardV2/cardV2.tokens.ts +21 -0
- package/lib/components/CardV2/cardV2.tokens.types.ts +94 -0
- package/lib/components/CardV2/cardV2.types.ts +131 -0
- package/lib/components/CardV2/index.ts +13 -0
- package/lib/components/Charts/ChartLegend.tsx +25 -5
- package/lib/components/Charts/Charts.tsx +10 -0
- package/lib/components/Charts/index.ts +10 -0
- package/lib/components/Charts/types.tsx +2 -0
- package/lib/components/ChatInput/index.tsx +1 -0
- package/lib/components/Checkbox/index.ts +1 -0
- package/lib/components/CodeEditor/index.ts +1 -0
- package/lib/components/DataTable/DataTable.tsx +8 -0
- package/lib/components/DataTable/TableBody/index.tsx +47 -11
- package/lib/components/DataTable/TableBody/types.ts +7 -1
- package/lib/components/DataTable/TableCell/index.tsx +1 -1
- package/lib/components/DataTable/hooks/index.ts +2 -0
- package/lib/components/DataTable/hooks/useReducedMotion.ts +19 -0
- package/lib/components/DataTable/hooks/useRowFlip.ts +170 -0
- package/lib/components/DataTable/types.ts +32 -0
- package/lib/components/DateRangePicker/CalendarGrid.tsx +36 -6
- package/lib/components/DateRangePicker/DateRangePicker.tsx +22 -3
- package/lib/components/DateRangePicker/types.ts +6 -1
- package/lib/components/DateRangePicker/utils.ts +123 -12
- package/lib/components/Directory/Directory.tsx +31 -0
- package/lib/components/Directory/NavItem.tsx +177 -86
- package/lib/components/Directory/Section.tsx +9 -0
- package/lib/components/Directory/VirtualizedDirectory.tsx +670 -0
- package/lib/components/Directory/directory.tokens.ts +21 -0
- package/lib/components/Directory/types.ts +43 -1
- package/lib/components/Directory/utils.ts +81 -1
- package/lib/components/Drawer/index.ts +1 -0
- package/lib/components/Inputs/DropdownInput/DropdownInput.tsx +6 -2
- package/lib/components/Inputs/MultiValueInput/index.ts +1 -0
- package/lib/components/Inputs/NumberInput/NumberInput.tsx +6 -2
- package/lib/components/Inputs/NumberInput/index.ts +1 -0
- package/lib/components/Inputs/OTPInput/index.ts +1 -0
- package/lib/components/Inputs/SearchInput/index.ts +1 -0
- package/lib/components/Inputs/TextArea/TextArea.tsx +4 -2
- package/lib/components/Inputs/TextArea/index.ts +1 -0
- package/lib/components/Inputs/TextInput/TextInput.tsx +6 -2
- package/lib/components/Inputs/TextInput/index.ts +1 -0
- package/lib/components/Inputs/UnitInput/UnitInput.tsx +6 -2
- package/lib/components/InputsV2/NumberInputV2/NumberInputV2.tsx +6 -2
- package/lib/components/InputsV2/TextAreaV2/TextAreaV2.tsx +2 -1
- package/lib/components/InputsV2/TextAreaV2/utils.ts +3 -1
- package/lib/components/InputsV2/TextInputV2/TextInputV2.tsx +1 -0
- package/lib/components/InputsV2/TextInputV2/utils.ts +6 -8
- package/lib/components/InputsV2/UploadV2/UploadContainerV2.tsx +470 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.dark.tokens.ts +348 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.light.tokens.ts +348 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.tokens.ts +20 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.tokens.types.ts +117 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.tsx +336 -0
- package/lib/components/InputsV2/UploadV2/UploadV2.types.ts +67 -0
- package/lib/components/InputsV2/UploadV2/index.ts +3 -0
- package/lib/components/InputsV2/UploadV2/utils.ts +170 -0
- package/lib/components/KeyValuePair/index.ts +1 -0
- package/lib/components/Menu/Menu.tsx +18 -2
- package/lib/components/Menu/SubMenu.tsx +25 -3
- package/lib/components/Menu/index.ts +1 -0
- package/lib/components/Menu/types.tsx +14 -0
- package/lib/components/Menu/utils.ts +46 -3
- package/lib/components/Modal/index.ts +1 -0
- package/lib/components/ModalV2/ModalV2.tsx +269 -0
- package/lib/components/ModalV2/ModalV2Footer.tsx +76 -0
- package/lib/components/ModalV2/ModalV2Header.tsx +144 -0
- package/lib/components/ModalV2/ModalV2Skeleton.tsx +80 -0
- package/lib/components/ModalV2/index.ts +4 -0
- package/lib/components/ModalV2/mobileModalV2.tsx +411 -0
- package/lib/components/ModalV2/modalAnimationV2.tsx +19 -0
- package/lib/components/ModalV2/modalV2.dark.tokens.ts +183 -0
- package/lib/components/ModalV2/modalV2.light.tokens.ts +183 -0
- package/lib/components/ModalV2/modalV2.tokens.ts +21 -0
- package/lib/components/ModalV2/modalV2.tokens.types.ts +94 -0
- package/lib/components/ModalV2/modalV2.types.ts +80 -0
- package/lib/components/MultiSelect/MultiSelect.tsx +2 -1
- package/lib/components/MultiSelect/MultiSelectTrigger.tsx +2 -1
- package/lib/components/MultiSelect/index.ts +2 -0
- package/lib/components/MultiSelectV2/MultiSelectV2Trigger.tsx +4 -1
- package/lib/components/Popover/index.ts +1 -0
- package/lib/components/Primitives/Block/Block.tsx +1 -1
- package/lib/components/ProgressBar/index.ts +1 -0
- package/lib/components/Radio/index.ts +2 -0
- package/lib/components/Sidebar/Sidebar.tsx +38 -0
- package/lib/components/Sidebar/SidebarContent.tsx +25 -1
- package/lib/components/Sidebar/index.ts +1 -0
- package/lib/components/Sidebar/types.ts +13 -1
- package/lib/components/SidebarV2/SidebarV2.tsx +30 -0
- package/lib/components/SidebarV2/SidebarV2Panel.tsx +25 -1
- package/lib/components/SidebarV2/types.ts +9 -1
- package/lib/components/SingleSelect/SingleSelect.tsx +2 -1
- package/lib/components/SingleSelect/SingleSelectTrigger.tsx +3 -1
- package/lib/components/SingleSelect/index.ts +1 -0
- package/lib/components/SingleSelectV2/SingleSelectV2Trigger.tsx +3 -1
- package/lib/components/Skeleton/SkeletonCompound.tsx +45 -31
- package/lib/components/Snackbar/index.ts +2 -0
- package/lib/components/StatCard/index.ts +1 -0
- package/lib/components/Stepper/index.ts +1 -0
- package/lib/components/Switch/index.ts +2 -0
- package/lib/components/Tabs/index.ts +1 -0
- package/lib/components/Tags/index.ts +1 -0
- package/lib/components/Timeline/Timeline.tsx +9 -1
- package/lib/components/Tooltip/index.ts +1 -0
- package/lib/components/Topbar/index.ts +1 -0
- package/lib/components/Upload/index.ts +1 -0
- package/lib/context/ThemeContext.tsx +16 -0
- package/lib/context/initComponentTokens.ts +11 -0
- package/lib/context/useComponentToken.ts +15 -1
- package/lib/hooks/useResponsiveTokens.ts +63 -0
- package/lib/main.ts +16 -0
- package/lib/node.ts +2 -0
- package/package.json +1 -1
- /package/dist/{node-CovJEwot.js → breadcrumbV2.tokens-CovJEwot.js} +0 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { useId } from 'react'
|
|
2
|
+
import { useResponsiveTokens } from '../../hooks/useResponsiveTokens'
|
|
3
|
+
import Block from '../Primitives/Block/Block'
|
|
4
|
+
import ButtonV2 from '../ButtonV2/ButtonV2'
|
|
5
|
+
import type { CardV2TokensType } from './cardV2.tokens'
|
|
6
|
+
import { useCardV2Context } from './CardV2Context'
|
|
7
|
+
import {
|
|
8
|
+
CardV2Orientation,
|
|
9
|
+
type CardV2ActionsProps,
|
|
10
|
+
type CardV2BodyProps,
|
|
11
|
+
type CardV2FooterProps,
|
|
12
|
+
type CardV2HeaderProps,
|
|
13
|
+
type CardV2MediaProps,
|
|
14
|
+
type CardV2MetaProps,
|
|
15
|
+
type CardV2SectionProps,
|
|
16
|
+
} from './cardV2.types'
|
|
17
|
+
import { renderCardV2Text, toCardV2ActionArray } from './CardV2.utils'
|
|
18
|
+
|
|
19
|
+
const useCardV2SectionContext = () => {
|
|
20
|
+
const context = useCardV2Context()
|
|
21
|
+
const responsiveTokens = useResponsiveTokens<CardV2TokensType>('CARDV2')
|
|
22
|
+
const fallbackId = useId()
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
tokens: context?.tokens ?? responsiveTokens,
|
|
26
|
+
centered: context?.centered ?? false,
|
|
27
|
+
scrollable: context?.scrollable ?? false,
|
|
28
|
+
ids: context?.ids ?? {
|
|
29
|
+
eyebrow: `${fallbackId}-card-eyebrow`,
|
|
30
|
+
title: `${fallbackId}-card-title`,
|
|
31
|
+
subtitle: `${fallbackId}-card-subtitle`,
|
|
32
|
+
description: `${fallbackId}-card-description`,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const CardV2Meta = ({
|
|
38
|
+
title,
|
|
39
|
+
truncateTitle,
|
|
40
|
+
subtitle,
|
|
41
|
+
eyebrow,
|
|
42
|
+
centered,
|
|
43
|
+
}: CardV2MetaProps) => {
|
|
44
|
+
const { tokens, centered: contextCentered, ids } = useCardV2SectionContext()
|
|
45
|
+
const isCentered = centered ?? contextCentered
|
|
46
|
+
|
|
47
|
+
if (!eyebrow && !title && !subtitle) return null
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Block
|
|
51
|
+
display="flex"
|
|
52
|
+
flexDirection="column"
|
|
53
|
+
gap={tokens.header.gap}
|
|
54
|
+
minWidth={0}
|
|
55
|
+
alignItems={isCentered ? 'center' : undefined}
|
|
56
|
+
data-element="card-meta"
|
|
57
|
+
>
|
|
58
|
+
{renderCardV2Text({
|
|
59
|
+
value: eyebrow,
|
|
60
|
+
id: ids.eyebrow,
|
|
61
|
+
as: 'p',
|
|
62
|
+
styles: tokens.header.eyebrow as React.CSSProperties,
|
|
63
|
+
dataElement: 'card-eyebrow',
|
|
64
|
+
})}
|
|
65
|
+
{renderCardV2Text({
|
|
66
|
+
value: title,
|
|
67
|
+
id: ids.title,
|
|
68
|
+
as: 'h2',
|
|
69
|
+
styles: tokens.header.title as React.CSSProperties,
|
|
70
|
+
dataElement: 'card-title',
|
|
71
|
+
truncate: truncateTitle,
|
|
72
|
+
})}
|
|
73
|
+
{renderCardV2Text({
|
|
74
|
+
value: subtitle,
|
|
75
|
+
id: ids.subtitle,
|
|
76
|
+
as: 'p',
|
|
77
|
+
styles: tokens.header.subtitle as React.CSSProperties,
|
|
78
|
+
dataElement: 'card-subtitle',
|
|
79
|
+
})}
|
|
80
|
+
</Block>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const CardV2Header = ({
|
|
85
|
+
title,
|
|
86
|
+
truncateTitle,
|
|
87
|
+
subtitle,
|
|
88
|
+
eyebrow,
|
|
89
|
+
leadingSlot,
|
|
90
|
+
trailingSlot,
|
|
91
|
+
centered,
|
|
92
|
+
}: CardV2HeaderProps) => {
|
|
93
|
+
const { tokens, centered: contextCentered, ids } = useCardV2SectionContext()
|
|
94
|
+
const isCentered = centered ?? contextCentered
|
|
95
|
+
const hasHeader = Boolean(
|
|
96
|
+
leadingSlot || eyebrow || title || subtitle || trailingSlot
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if (!hasHeader) return null
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Block
|
|
103
|
+
data-element="card-header"
|
|
104
|
+
display="flex"
|
|
105
|
+
flexDirection={isCentered ? 'column' : 'row'}
|
|
106
|
+
alignItems={isCentered ? 'center' : 'flex-start'}
|
|
107
|
+
justifyContent={isCentered ? 'center' : 'space-between'}
|
|
108
|
+
gap={tokens.header.gap}
|
|
109
|
+
width="100%"
|
|
110
|
+
role="group"
|
|
111
|
+
aria-labelledby={title ? ids.title : undefined}
|
|
112
|
+
>
|
|
113
|
+
<Block
|
|
114
|
+
display="flex"
|
|
115
|
+
flexDirection={isCentered ? 'column' : 'row'}
|
|
116
|
+
alignItems={isCentered ? 'center' : 'flex-start'}
|
|
117
|
+
gap={tokens.header.gap}
|
|
118
|
+
minWidth={0}
|
|
119
|
+
flexGrow={1}
|
|
120
|
+
justifyContent={isCentered ? 'center' : undefined}
|
|
121
|
+
alignSelf={isCentered ? 'center' : undefined}
|
|
122
|
+
width={isCentered ? '100%' : undefined}
|
|
123
|
+
>
|
|
124
|
+
{leadingSlot && <Block flexShrink={0}>{leadingSlot}</Block>}
|
|
125
|
+
<CardV2Meta
|
|
126
|
+
eyebrow={eyebrow}
|
|
127
|
+
title={title}
|
|
128
|
+
truncateTitle={truncateTitle}
|
|
129
|
+
subtitle={subtitle}
|
|
130
|
+
centered={isCentered}
|
|
131
|
+
/>
|
|
132
|
+
</Block>
|
|
133
|
+
{trailingSlot && (
|
|
134
|
+
<Block
|
|
135
|
+
flexShrink={0}
|
|
136
|
+
alignSelf={isCentered ? 'center' : undefined}
|
|
137
|
+
>
|
|
138
|
+
{trailingSlot}
|
|
139
|
+
</Block>
|
|
140
|
+
)}
|
|
141
|
+
</Block>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const CardV2Media = ({
|
|
146
|
+
children,
|
|
147
|
+
orientation,
|
|
148
|
+
width,
|
|
149
|
+
height,
|
|
150
|
+
minHeight,
|
|
151
|
+
}: CardV2MediaProps) => {
|
|
152
|
+
const { tokens, centered } = useCardV2SectionContext()
|
|
153
|
+
const isHorizontal = orientation === CardV2Orientation.HORIZONTAL
|
|
154
|
+
|
|
155
|
+
if (!children) return null
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<Block
|
|
159
|
+
data-element="card-media"
|
|
160
|
+
display="flex"
|
|
161
|
+
alignItems="center"
|
|
162
|
+
alignSelf={centered ? 'center' : 'flex-start'}
|
|
163
|
+
justifyContent="center"
|
|
164
|
+
flexShrink={0}
|
|
165
|
+
width={width ?? (isHorizontal ? tokens.media.width : '100%')}
|
|
166
|
+
height={height ?? tokens.media.height}
|
|
167
|
+
minHeight={
|
|
168
|
+
minHeight ?? (isHorizontal ? undefined : tokens.media.minHeight)
|
|
169
|
+
}
|
|
170
|
+
borderRadius={tokens.media.borderRadius}
|
|
171
|
+
backgroundColor={tokens.media.backgroundColor}
|
|
172
|
+
overflow="hidden"
|
|
173
|
+
>
|
|
174
|
+
{children}
|
|
175
|
+
</Block>
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export const CardV2Actions = ({ actions, centered }: CardV2ActionsProps) => {
|
|
180
|
+
const { tokens, centered: contextCentered } = useCardV2SectionContext()
|
|
181
|
+
const isCentered = centered ?? contextCentered
|
|
182
|
+
const actionItems = toCardV2ActionArray(actions)
|
|
183
|
+
|
|
184
|
+
if (actionItems.length === 0) return null
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<Block
|
|
188
|
+
display="flex"
|
|
189
|
+
flexWrap="wrap"
|
|
190
|
+
justifyContent={isCentered ? 'center' : 'flex-start'}
|
|
191
|
+
gap={tokens.actions.gap}
|
|
192
|
+
data-element="card-actions"
|
|
193
|
+
>
|
|
194
|
+
{actionItems.map((action, index) => (
|
|
195
|
+
<ButtonV2
|
|
196
|
+
key={`${action.text ?? action['aria-label'] ?? 'action'}-${index}`}
|
|
197
|
+
{...action}
|
|
198
|
+
/>
|
|
199
|
+
))}
|
|
200
|
+
</Block>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const CardV2Content = ({ children }: CardV2SectionProps) => {
|
|
205
|
+
const { centered } = useCardV2SectionContext()
|
|
206
|
+
|
|
207
|
+
if (!children) return null
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<Block
|
|
211
|
+
data-element="card-content"
|
|
212
|
+
width="100%"
|
|
213
|
+
display={centered ? 'flex' : undefined}
|
|
214
|
+
justifyContent={centered ? 'center' : undefined}
|
|
215
|
+
>
|
|
216
|
+
{children}
|
|
217
|
+
</Block>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const CardV2Body = ({
|
|
222
|
+
description,
|
|
223
|
+
actions,
|
|
224
|
+
centered,
|
|
225
|
+
scrollable,
|
|
226
|
+
children,
|
|
227
|
+
}: CardV2BodyProps) => {
|
|
228
|
+
const {
|
|
229
|
+
tokens,
|
|
230
|
+
centered: contextCentered,
|
|
231
|
+
scrollable: contextScrollable,
|
|
232
|
+
ids,
|
|
233
|
+
} = useCardV2SectionContext()
|
|
234
|
+
const isCentered = centered ?? contextCentered
|
|
235
|
+
const isScrollable = scrollable ?? contextScrollable
|
|
236
|
+
const hasBody = Boolean(description || children || actions)
|
|
237
|
+
|
|
238
|
+
if (!hasBody) return null
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<Block
|
|
242
|
+
data-element="card-body"
|
|
243
|
+
display="flex"
|
|
244
|
+
flexDirection="column"
|
|
245
|
+
gap={tokens.body.gap}
|
|
246
|
+
width="100%"
|
|
247
|
+
minHeight={0}
|
|
248
|
+
overflowY={isScrollable ? 'auto' : undefined}
|
|
249
|
+
overflowX={isScrollable ? 'hidden' : undefined}
|
|
250
|
+
alignItems={isCentered ? 'center' : undefined}
|
|
251
|
+
textAlign={isCentered ? 'center' : undefined}
|
|
252
|
+
role="group"
|
|
253
|
+
aria-describedby={description ? ids.description : undefined}
|
|
254
|
+
>
|
|
255
|
+
{renderCardV2Text({
|
|
256
|
+
value: description,
|
|
257
|
+
id: ids.description,
|
|
258
|
+
as: 'p',
|
|
259
|
+
styles: tokens.body.description as React.CSSProperties,
|
|
260
|
+
dataElement: 'card-description',
|
|
261
|
+
})}
|
|
262
|
+
<CardV2Content>{children}</CardV2Content>
|
|
263
|
+
<CardV2Actions actions={actions} centered={isCentered} />
|
|
264
|
+
</Block>
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const CardV2Footer = ({
|
|
269
|
+
children,
|
|
270
|
+
actions,
|
|
271
|
+
centered,
|
|
272
|
+
divider = false,
|
|
273
|
+
}: CardV2FooterProps) => {
|
|
274
|
+
const { tokens, centered: contextCentered } = useCardV2SectionContext()
|
|
275
|
+
const isCentered = centered ?? contextCentered
|
|
276
|
+
const hasFooter = Boolean(children || actions)
|
|
277
|
+
|
|
278
|
+
if (!hasFooter) return null
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<Block
|
|
282
|
+
data-element="card-footer"
|
|
283
|
+
data-divider={divider || undefined}
|
|
284
|
+
display="flex"
|
|
285
|
+
flexWrap="wrap"
|
|
286
|
+
alignItems="center"
|
|
287
|
+
justifyContent={isCentered ? 'center' : 'space-between'}
|
|
288
|
+
gap={tokens.footer.gap}
|
|
289
|
+
width="100%"
|
|
290
|
+
paddingTop={divider ? tokens.footer.paddingTop : undefined}
|
|
291
|
+
borderTop={divider ? tokens.footer.borderTop : undefined}
|
|
292
|
+
>
|
|
293
|
+
{children && <Block>{children}</Block>}
|
|
294
|
+
<CardV2Actions actions={actions} centered={isCentered} />
|
|
295
|
+
</Block>
|
|
296
|
+
)
|
|
297
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react'
|
|
2
|
+
import type { CardV2TokensType } from './cardV2.tokens'
|
|
3
|
+
|
|
4
|
+
export type CardV2ContextValue = {
|
|
5
|
+
tokens: CardV2TokensType
|
|
6
|
+
centered: boolean
|
|
7
|
+
scrollable: boolean
|
|
8
|
+
ids: {
|
|
9
|
+
eyebrow: string
|
|
10
|
+
title: string
|
|
11
|
+
subtitle: string
|
|
12
|
+
description: string
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const CardV2Context = createContext<CardV2ContextValue | null>(null)
|
|
17
|
+
|
|
18
|
+
export const useCardV2Context = () => useContext(CardV2Context)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useResponsiveTokens } from '../../hooks/useResponsiveTokens'
|
|
2
|
+
import Block from '../Primitives/Block/Block'
|
|
3
|
+
import Skeleton from '../Skeleton/Skeleton'
|
|
4
|
+
import type { CardV2TokensType } from './cardV2.tokens'
|
|
5
|
+
import { useCardV2Context } from './CardV2Context'
|
|
6
|
+
import type { CardV2SkeletonProps } from './cardV2.types'
|
|
7
|
+
|
|
8
|
+
export type CardV2SkeletonComponentProps = {
|
|
9
|
+
skeleton?: CardV2SkeletonProps
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const CardV2Skeleton = ({ skeleton }: CardV2SkeletonComponentProps) => {
|
|
13
|
+
const context = useCardV2Context()
|
|
14
|
+
const responsiveTokens = useResponsiveTokens<CardV2TokensType>('CARDV2')
|
|
15
|
+
const tokens = context?.tokens ?? responsiveTokens
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Block display="flex" flexDirection="column" gap={tokens.layout.gap}>
|
|
19
|
+
<Skeleton
|
|
20
|
+
variant={skeleton?.variant}
|
|
21
|
+
width={skeleton?.width ?? '100%'}
|
|
22
|
+
height={skeleton?.height ?? '160px'}
|
|
23
|
+
shape="rounded"
|
|
24
|
+
/>
|
|
25
|
+
<Block
|
|
26
|
+
display="flex"
|
|
27
|
+
flexDirection="column"
|
|
28
|
+
gap={tokens.header.gap}
|
|
29
|
+
>
|
|
30
|
+
<Skeleton width="40%" height="18px" shape="rounded" />
|
|
31
|
+
<Skeleton width="70%" height="24px" shape="rounded" />
|
|
32
|
+
<Skeleton width="55%" height="18px" shape="rounded" />
|
|
33
|
+
</Block>
|
|
34
|
+
<Skeleton width="100%" height="18px" shape="rounded" />
|
|
35
|
+
<Skeleton width="84%" height="18px" shape="rounded" />
|
|
36
|
+
</Block>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default CardV2Skeleton
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import type { AccessibilityReport } from '../../StatCard/accessibility/StatCardAccessibilityReport'
|
|
2
|
+
|
|
3
|
+
export const cardV2AccessibilityReport: AccessibilityReport = {
|
|
4
|
+
componentName: 'CardV2',
|
|
5
|
+
wcagVersion: '2.1',
|
|
6
|
+
reportDate: new Date().toISOString().split('T')[0],
|
|
7
|
+
conformanceLevel: 'Level AA',
|
|
8
|
+
overallStatus: 'partial',
|
|
9
|
+
summary:
|
|
10
|
+
'CardV2 is a composable grouping surface with prop-based and compound APIs. The component supports semantic regions, generated accessible names and descriptions, keyboard-focusable interactive cards, selected/pressed state semantics, accessible action buttons through ButtonV2, and consumer-owned media alternatives. Automated axe tests cover default, media/action, compound, and interactive selected cards. Manual verification is still required for token contrast across light/dark themes and for consumer-provided media content.',
|
|
11
|
+
criteria: [
|
|
12
|
+
{
|
|
13
|
+
id: '1.1.1',
|
|
14
|
+
level: 'A',
|
|
15
|
+
title: 'Non-text Content',
|
|
16
|
+
status: 'compliant',
|
|
17
|
+
description:
|
|
18
|
+
'All non-text content that is part of the component must have a text alternative or be hidden when decorative.',
|
|
19
|
+
implementation:
|
|
20
|
+
'CardV2 media, leadingSlot, and trailingSlot are consumer-owned React nodes. The component preserves supplied image alt text and supports decorative icons via aria-hidden on consumer content. Action icons are rendered through ButtonV2 and can receive aria-label.',
|
|
21
|
+
testResults:
|
|
22
|
+
'Automated tests verify CardV2 with accessible image media and icon-only actions has no axe violations.',
|
|
23
|
+
notes: 'Consumers must provide alt text for informative media or empty alt text/aria-hidden for decorative media.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: '1.3.1',
|
|
27
|
+
level: 'A',
|
|
28
|
+
title: 'Info and Relationships',
|
|
29
|
+
status: 'compliant',
|
|
30
|
+
description:
|
|
31
|
+
'Information, structure, and relationships conveyed visually can be programmatically determined.',
|
|
32
|
+
implementation:
|
|
33
|
+
'The root uses role="region" by default. Title, subtitle, and description receive generated IDs. Root aria-labelledby points to the title when present, and aria-describedby points to description or subtitle. Header and body sections use role="group" where appropriate.',
|
|
34
|
+
testResults:
|
|
35
|
+
'Automated tests verify aria-labelledby and aria-describedby are wired to generated IDs.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: '1.3.2',
|
|
39
|
+
level: 'A',
|
|
40
|
+
title: 'Meaningful Sequence',
|
|
41
|
+
status: 'compliant',
|
|
42
|
+
description:
|
|
43
|
+
'Content is presented in a meaningful DOM and reading sequence.',
|
|
44
|
+
implementation:
|
|
45
|
+
'Prop composition renders media, header, body, and footer in visual reading order. Compound composition preserves consumer-provided DOM order while sharing context and tokens.',
|
|
46
|
+
testResults: 'Verified by render tests for prop and compound APIs.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: '1.3.4',
|
|
50
|
+
level: 'AA',
|
|
51
|
+
title: 'Orientation',
|
|
52
|
+
status: 'compliant',
|
|
53
|
+
description:
|
|
54
|
+
'Content does not restrict its view and operation to a single display orientation.',
|
|
55
|
+
implementation:
|
|
56
|
+
'CardV2 supports vertical and horizontal orientations and responsive sm/lg token sets.',
|
|
57
|
+
testResults:
|
|
58
|
+
'Automated tests cover horizontal cards with accessible media.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: '1.4.3',
|
|
62
|
+
level: 'AA',
|
|
63
|
+
title: 'Contrast (Minimum)',
|
|
64
|
+
status: 'unsure',
|
|
65
|
+
description:
|
|
66
|
+
'Text and images of text have sufficient contrast against their backgrounds.',
|
|
67
|
+
implementation:
|
|
68
|
+
'CardV2 typography and surfaces use theme tokens for light and dark modes.',
|
|
69
|
+
testResults:
|
|
70
|
+
'UNSURE: Requires manual contrast verification across all variants, states, and themes.',
|
|
71
|
+
notes: 'Verify title, subtitle, description, borders, focus rings, and selected states in light and dark themes.',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: '1.4.4',
|
|
75
|
+
level: 'AA',
|
|
76
|
+
title: 'Resize Text',
|
|
77
|
+
status: 'compliant',
|
|
78
|
+
description:
|
|
79
|
+
'Text can be resized up to 200 percent without loss of content or functionality.',
|
|
80
|
+
implementation:
|
|
81
|
+
'The layout uses flex containers, minWidth=0 where text can shrink, and optional truncateTitle for constrained titles.',
|
|
82
|
+
testResults:
|
|
83
|
+
'Automated render tests cover long wrapping titles and truncateTitle behavior.',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: '1.4.10',
|
|
87
|
+
level: 'AA',
|
|
88
|
+
title: 'Reflow',
|
|
89
|
+
status: 'compliant',
|
|
90
|
+
description:
|
|
91
|
+
'Content can reflow without requiring two-dimensional scrolling at common viewport sizes.',
|
|
92
|
+
implementation:
|
|
93
|
+
'Cards support width constraints, horizontal/vertical orientation, wrapping action rows, and responsive token compaction.',
|
|
94
|
+
testResults:
|
|
95
|
+
'Demo and tests cover narrow cards, horizontal cards, and long content.',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: '1.4.11',
|
|
99
|
+
level: 'AA',
|
|
100
|
+
title: 'Non-text Contrast',
|
|
101
|
+
status: 'unsure',
|
|
102
|
+
description:
|
|
103
|
+
'UI component boundaries, focus indicators, and graphical states have sufficient contrast.',
|
|
104
|
+
implementation:
|
|
105
|
+
'Borders, selected state, hover state, and focus-visible outline use theme tokens.',
|
|
106
|
+
testResults:
|
|
107
|
+
'UNSURE: Requires manual token contrast verification across variants and themes.',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: '2.1.1',
|
|
111
|
+
level: 'A',
|
|
112
|
+
title: 'Keyboard',
|
|
113
|
+
status: 'compliant',
|
|
114
|
+
description:
|
|
115
|
+
'All functionality is operable through a keyboard interface.',
|
|
116
|
+
implementation:
|
|
117
|
+
'Interactive cards receive role="button" and tabIndex=0 by default. Actions are rendered through ButtonV2 and remain keyboard reachable.',
|
|
118
|
+
testResults:
|
|
119
|
+
'Automated tests verify interactive role, tabIndex, and reachable footer/body actions.',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: '2.4.3',
|
|
123
|
+
level: 'A',
|
|
124
|
+
title: 'Focus Order',
|
|
125
|
+
status: 'compliant',
|
|
126
|
+
description:
|
|
127
|
+
'Focusable components receive focus in an order that preserves meaning and operability.',
|
|
128
|
+
implementation:
|
|
129
|
+
'DOM order follows media, header, body, actions, and footer order for prop composition. Compound composition preserves consumer-defined order.',
|
|
130
|
+
testResults:
|
|
131
|
+
'Verified structurally through render tests and ButtonV2 keyboard behavior.',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: '2.4.6',
|
|
135
|
+
level: 'AA',
|
|
136
|
+
title: 'Headings and Labels',
|
|
137
|
+
status: 'compliant',
|
|
138
|
+
description: 'Headings and labels describe topic or purpose.',
|
|
139
|
+
implementation:
|
|
140
|
+
'Title renders as h2 by default through CardV2Meta. aria-labelledby points to title when available; aria-label is used only when no title is present.',
|
|
141
|
+
testResults:
|
|
142
|
+
'Automated tests verify aria-label and aria-labelledby are not set together for titled cards.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: '2.4.7',
|
|
146
|
+
level: 'AA',
|
|
147
|
+
title: 'Focus Visible',
|
|
148
|
+
status: 'compliant',
|
|
149
|
+
description: 'Keyboard-operable UI has a visible focus indicator.',
|
|
150
|
+
implementation:
|
|
151
|
+
'The root applies tokenized focus-visible outline. ButtonV2 actions provide their own focus treatment.',
|
|
152
|
+
testResults:
|
|
153
|
+
'Axe tests pass for interactive selected cards. Manual visual verification recommended for theme contrast.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: '2.5.8',
|
|
157
|
+
level: 'AA',
|
|
158
|
+
title: 'Target Size (Minimum)',
|
|
159
|
+
status: 'compliant',
|
|
160
|
+
description:
|
|
161
|
+
'Pointer targets are at least 24 by 24 CSS pixels or have equivalent spacing.',
|
|
162
|
+
implementation:
|
|
163
|
+
'Action controls are rendered through ButtonV2 sizing. Interactive root cards are large surfaces by design.',
|
|
164
|
+
testResults:
|
|
165
|
+
'Verified by component composition and ButtonV2 target sizing.',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: '3.2.1',
|
|
169
|
+
level: 'A',
|
|
170
|
+
title: 'On Focus',
|
|
171
|
+
status: 'compliant',
|
|
172
|
+
description:
|
|
173
|
+
'Receiving focus does not initiate a change of context.',
|
|
174
|
+
implementation:
|
|
175
|
+
'CardV2 focus styles are visual only; no behavior is triggered by focus.',
|
|
176
|
+
testResults: 'Verified by implementation review.',
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: '4.1.2',
|
|
180
|
+
level: 'A',
|
|
181
|
+
title: 'Name, Role, Value',
|
|
182
|
+
status: 'compliant',
|
|
183
|
+
description:
|
|
184
|
+
'UI components expose appropriate name, role, and state.',
|
|
185
|
+
implementation:
|
|
186
|
+
'Root cards expose region or button roles. Titled cards use aria-labelledby. Interactive selected cards use aria-pressed. aria-selected is only emitted for roles that support it.',
|
|
187
|
+
testResults:
|
|
188
|
+
'Automated tests and axe checks cover root roles, labels, descriptions, pressed state, and selected-state constraints.',
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
strengths: [
|
|
192
|
+
'Clear generated ID relationships for title, subtitle, and description.',
|
|
193
|
+
'No conflicting aria-label when aria-labelledby is available.',
|
|
194
|
+
'Interactive selected cards use aria-pressed for button semantics.',
|
|
195
|
+
'Selected aria state is limited to roles that support aria-selected.',
|
|
196
|
+
'Compound API preserves consumer DOM order and semantic control.',
|
|
197
|
+
'Axe coverage exists for default, media/action, compound, and interactive cards.',
|
|
198
|
+
],
|
|
199
|
+
recommendations: [
|
|
200
|
+
'Manually verify light and dark token contrast for every variant and state.',
|
|
201
|
+
'Require consumers to provide accessible names for informative custom media and icon-only slots.',
|
|
202
|
+
'Use CardV2 as a region only when the grouped content is meaningful enough to appear as a landmark-like region.',
|
|
203
|
+
'Prefer explicit role overrides when rendering CardV2 inside list, grid, tab, or option collections.',
|
|
204
|
+
'Keep nested interactive controls out of cards with root-level click handlers unless event behavior is intentionally managed.',
|
|
205
|
+
],
|
|
206
|
+
wcagVersions: {
|
|
207
|
+
'2.0': [
|
|
208
|
+
'1.1.1',
|
|
209
|
+
'1.3.1',
|
|
210
|
+
'1.3.2',
|
|
211
|
+
'1.4.3',
|
|
212
|
+
'2.1.1',
|
|
213
|
+
'2.4.3',
|
|
214
|
+
'2.4.6',
|
|
215
|
+
'2.4.7',
|
|
216
|
+
'3.2.1',
|
|
217
|
+
'4.1.2',
|
|
218
|
+
],
|
|
219
|
+
'2.1': ['1.3.4', '1.4.10', '1.4.11'],
|
|
220
|
+
'2.2': ['2.5.8'],
|
|
221
|
+
},
|
|
222
|
+
testMethodology: {
|
|
223
|
+
automated: [
|
|
224
|
+
'Vitest and React Testing Library render tests.',
|
|
225
|
+
'jest-axe checks for default, media/action, compound, and interactive selected examples.',
|
|
226
|
+
'ARIA relationship assertions for root, title, subtitle, and description.',
|
|
227
|
+
],
|
|
228
|
+
manual: [
|
|
229
|
+
'Keyboard navigation through interactive card roots and nested actions.',
|
|
230
|
+
'Screen reader review of titled, untitled, compound, and media-rich cards.',
|
|
231
|
+
'Light/dark contrast verification for text, borders, focus, selected, and hover states.',
|
|
232
|
+
'Responsive visual review across narrow and wide viewports.',
|
|
233
|
+
],
|
|
234
|
+
verificationTools: [
|
|
235
|
+
'jest-axe',
|
|
236
|
+
'React Testing Library',
|
|
237
|
+
'Storybook accessibility addon',
|
|
238
|
+
'WebAIM Contrast Checker',
|
|
239
|
+
'VoiceOver, NVDA, or equivalent screen reader',
|
|
240
|
+
],
|
|
241
|
+
wcagLevels: {
|
|
242
|
+
A: ['1.1.1', '1.3.1', '1.3.2', '2.1.1', '2.4.3', '3.2.1', '4.1.2'],
|
|
243
|
+
AA: [
|
|
244
|
+
'1.3.4',
|
|
245
|
+
'1.4.3',
|
|
246
|
+
'1.4.4',
|
|
247
|
+
'1.4.10',
|
|
248
|
+
'1.4.11',
|
|
249
|
+
'2.4.6',
|
|
250
|
+
'2.4.7',
|
|
251
|
+
'2.5.8',
|
|
252
|
+
],
|
|
253
|
+
AAA: [],
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
accessibilityBestPractices: {
|
|
257
|
+
semanticGrouping: {
|
|
258
|
+
status: 'compliant',
|
|
259
|
+
implementation:
|
|
260
|
+
'Root role defaults to region and can be overridden for list/grid/tab/option contexts.',
|
|
261
|
+
verification: 'Render tests verify default and custom root roles.',
|
|
262
|
+
},
|
|
263
|
+
accessibleNaming: {
|
|
264
|
+
status: 'compliant',
|
|
265
|
+
implementation:
|
|
266
|
+
'Title-driven cards use aria-labelledby; custom aria-label is reserved for cards without titles.',
|
|
267
|
+
verification:
|
|
268
|
+
'Accessibility tests verify aria-label and aria-labelledby behavior.',
|
|
269
|
+
},
|
|
270
|
+
stateSemantics: {
|
|
271
|
+
status: 'compliant',
|
|
272
|
+
implementation:
|
|
273
|
+
'Interactive selected cards use aria-pressed; aria-selected is limited to supported roles.',
|
|
274
|
+
verification: 'Axe checks pass for interactive selected cards.',
|
|
275
|
+
},
|
|
276
|
+
consumerMedia: {
|
|
277
|
+
status: 'unsure',
|
|
278
|
+
implementation:
|
|
279
|
+
'Media is consumer-owned and can be accessible or decorative depending on supplied markup.',
|
|
280
|
+
verification:
|
|
281
|
+
'Consumers must verify alt text or aria-hidden on media content.',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cardV2AccessibilityReport } from './CardV2AccessibilityReport'
|