@arbor-education/design-system.components 4.0.0 → 4.1.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 +10 -0
- package/dist/components/widget/types.d.ts +9 -0
- package/dist/components/widget/types.d.ts.map +1 -1
- package/dist/components/widgetCalendar/WidgetCalendar.d.ts +4 -2
- package/dist/components/widgetCalendar/WidgetCalendar.d.ts.map +1 -1
- package/dist/components/widgetCalendar/WidgetCalendar.js +30 -5
- package/dist/components/widgetCalendar/WidgetCalendar.js.map +1 -1
- package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts +18 -2
- package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts.map +1 -1
- package/dist/components/widgetCalendar/WidgetCalendar.stories.js +231 -2
- package/dist/components/widgetCalendar/WidgetCalendar.stories.js.map +1 -1
- package/dist/components/widgetCalendar/WidgetCalendar.test.js +131 -1
- package/dist/components/widgetCalendar/WidgetCalendar.test.js.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavourites.d.ts.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavourites.js +5 -4
- package/dist/components/widgetFavourites/WidgetFavourites.js.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts +3 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavourites.stories.js +157 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.js.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavourites.test.js +41 -1
- package/dist/components/widgetFavourites/WidgetFavourites.test.js.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavouritesItem.d.ts.map +1 -1
- package/dist/components/widgetFavourites/WidgetFavouritesItem.js +2 -2
- package/dist/components/widgetFavourites/WidgetFavouritesItem.js.map +1 -1
- package/dist/components/widgetFavourites/types.d.ts +4 -2
- package/dist/components/widgetFavourites/types.d.ts.map +1 -1
- package/dist/index.css +16 -0
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/widget/types.ts +13 -0
- package/src/components/widgetCalendar/WidgetCalendar.stories.tsx +268 -2
- package/src/components/widgetCalendar/WidgetCalendar.test.tsx +242 -0
- package/src/components/widgetCalendar/WidgetCalendar.tsx +76 -32
- package/src/components/widgetCalendar/widgetCalendar.scss +9 -0
- package/src/components/widgetFavourites/WidgetFavourites.stories.tsx +217 -0
- package/src/components/widgetFavourites/WidgetFavourites.test.tsx +99 -0
- package/src/components/widgetFavourites/WidgetFavourites.tsx +6 -2
- package/src/components/widgetFavourites/WidgetFavouritesItem.tsx +2 -1
- package/src/components/widgetFavourites/types.ts +5 -2
- package/src/components/widgetFavourites/widgetFavourites.scss +7 -0
- package/src/tokens.scss +1 -0
- package/tokens/json/Arbor.json +4 -0
|
@@ -63,6 +63,14 @@ describe('WidgetFavourites', () => {
|
|
|
63
63
|
expect(container.querySelector('.ds-widget--floating')).toBeInTheDocument();
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
test('applies the bounded root class alongside a consumer className', () => {
|
|
67
|
+
const { container } = render(
|
|
68
|
+
<WidgetFavourites heading="Favourites" items={mockItems} className="consumer-class" />,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(container.querySelector('.ds-widget')).toHaveClass('ds-widget-favourites', 'consumer-class');
|
|
72
|
+
});
|
|
73
|
+
|
|
66
74
|
test('renders linked widget header when headingHref is provided', () => {
|
|
67
75
|
render(
|
|
68
76
|
<WidgetFavourites
|
|
@@ -75,6 +83,97 @@ describe('WidgetFavourites', () => {
|
|
|
75
83
|
expect(screen.getByRole('link', { name: 'Favourites (2)' })).toHaveAttribute('href', '/favourites');
|
|
76
84
|
});
|
|
77
85
|
|
|
86
|
+
test('forwards linkProps to the linked header', () => {
|
|
87
|
+
const onClick = vi.fn();
|
|
88
|
+
|
|
89
|
+
render(
|
|
90
|
+
<WidgetFavourites
|
|
91
|
+
heading="Favourites (2)"
|
|
92
|
+
headingHref="/favourites"
|
|
93
|
+
linkProps={{ onClick, target: '_blank' }}
|
|
94
|
+
items={mockItems}
|
|
95
|
+
/>,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const link = screen.getByRole('link', { name: 'Favourites (2)' });
|
|
99
|
+
fireEvent.click(link);
|
|
100
|
+
|
|
101
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
102
|
+
expect(link).toHaveAttribute('target', '_blank');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('renders the linked header through renderLink', () => {
|
|
106
|
+
render(
|
|
107
|
+
<WidgetFavourites
|
|
108
|
+
heading="Favourites (2)"
|
|
109
|
+
headingHref="/favourites"
|
|
110
|
+
renderLink={({ href, className, children }) => (
|
|
111
|
+
<a href={href} className={className} data-router-link="true">
|
|
112
|
+
{children}
|
|
113
|
+
</a>
|
|
114
|
+
)}
|
|
115
|
+
items={mockItems}
|
|
116
|
+
/>,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
expect(screen.getByRole('link', { name: 'Favourites (2)' })).toHaveAttribute('data-router-link', 'true');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('rejects heading link props without headingHref at the type level', () => {
|
|
123
|
+
render(
|
|
124
|
+
<>
|
|
125
|
+
{/* @ts-expect-error linkProps requires headingHref */}
|
|
126
|
+
<WidgetFavourites heading="Favourites" items={mockItems} linkProps={{ onClick: vi.fn() }} />
|
|
127
|
+
{/* @ts-expect-error renderLink requires headingHref */}
|
|
128
|
+
<WidgetFavourites heading="Favourites" items={mockItems} renderLink={() => <a />} />
|
|
129
|
+
</>,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(screen.queryByRole('link', { name: 'Favourites' })).not.toBeInTheDocument();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('applies item linkProps to the row link', () => {
|
|
136
|
+
const onClick = vi.fn();
|
|
137
|
+
|
|
138
|
+
render(
|
|
139
|
+
<WidgetFavourites
|
|
140
|
+
heading="Favourites"
|
|
141
|
+
items={[{
|
|
142
|
+
id: 'daily',
|
|
143
|
+
label: 'Daily Attendance',
|
|
144
|
+
href: '/attendance/daily',
|
|
145
|
+
linkProps: { onClick, target: '_blank' },
|
|
146
|
+
}]}
|
|
147
|
+
/>,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const link = screen.getByRole('link', { name: 'Daily Attendance' });
|
|
151
|
+
fireEvent.click(link);
|
|
152
|
+
|
|
153
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
154
|
+
expect(link).toHaveAttribute('target', '_blank');
|
|
155
|
+
expect(link).toHaveAttribute('href', '/attendance/daily');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('WidgetFavourites.Item applies linkProps to the row link', () => {
|
|
159
|
+
const onClick = vi.fn();
|
|
160
|
+
|
|
161
|
+
render(
|
|
162
|
+
<ul>
|
|
163
|
+
<WidgetFavourites.Item
|
|
164
|
+
id="daily"
|
|
165
|
+
label="Daily Attendance"
|
|
166
|
+
href="/attendance/daily"
|
|
167
|
+
linkProps={{ onClick }}
|
|
168
|
+
/>
|
|
169
|
+
</ul>,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
fireEvent.click(screen.getByRole('link', { name: 'Daily Attendance' }));
|
|
173
|
+
|
|
174
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
175
|
+
});
|
|
176
|
+
|
|
78
177
|
test('uses default remove label on remove button', () => {
|
|
79
178
|
render(
|
|
80
179
|
<WidgetFavourites heading="Favourites" items={mockItems} onRemoveItem={vi.fn()} />,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
1
2
|
import { EmptyState } from 'Components/emptyState/EmptyState';
|
|
2
3
|
import { Widget } from 'Components/widget/Widget';
|
|
3
4
|
import type { Widget as WidgetComponent } from 'Components/widget/Widget';
|
|
@@ -18,6 +19,8 @@ export const WidgetFavourites = (props: WidgetFavouritesProps): React.JSX.Elemen
|
|
|
18
19
|
tooltip,
|
|
19
20
|
items,
|
|
20
21
|
headingHref,
|
|
22
|
+
renderLink,
|
|
23
|
+
linkProps,
|
|
21
24
|
isFloating = false,
|
|
22
25
|
onRemoveItem,
|
|
23
26
|
emptyState = defaultEmptyState,
|
|
@@ -31,7 +34,7 @@ export const WidgetFavourites = (props: WidgetFavouritesProps): React.JSX.Elemen
|
|
|
31
34
|
isFloating,
|
|
32
35
|
isEmpty,
|
|
33
36
|
emptyState,
|
|
34
|
-
className,
|
|
37
|
+
className: classNames('ds-widget-favourites', className),
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
const body = (
|
|
@@ -47,6 +50,7 @@ export const WidgetFavourites = (props: WidgetFavouritesProps): React.JSX.Elemen
|
|
|
47
50
|
label={item.label}
|
|
48
51
|
href={item.href}
|
|
49
52
|
removeLabel={item.removeLabel}
|
|
53
|
+
linkProps={item.linkProps}
|
|
50
54
|
onRemove={onRemoveItem ? () => onRemoveItem(item.id) : undefined}
|
|
51
55
|
/>
|
|
52
56
|
))}
|
|
@@ -60,7 +64,7 @@ export const WidgetFavourites = (props: WidgetFavouritesProps): React.JSX.Elemen
|
|
|
60
64
|
<Widget
|
|
61
65
|
{...({
|
|
62
66
|
...widgetCommonProps,
|
|
63
|
-
...(headingHref ? { href: headingHref } : {}),
|
|
67
|
+
...(headingHref ? { href: headingHref, renderLink, linkProps } : {}),
|
|
64
68
|
} as WidgetComponent.Props)}
|
|
65
69
|
>
|
|
66
70
|
{body}
|
|
@@ -11,6 +11,7 @@ export const WidgetFavouritesItem = (props: WidgetFavouritesItemProps): React.JS
|
|
|
11
11
|
label,
|
|
12
12
|
href,
|
|
13
13
|
removeLabel = FAVOURITE_TOOLTIP.remove,
|
|
14
|
+
linkProps,
|
|
14
15
|
onRemove,
|
|
15
16
|
className,
|
|
16
17
|
} = props;
|
|
@@ -20,7 +21,7 @@ export const WidgetFavouritesItem = (props: WidgetFavouritesItemProps): React.JS
|
|
|
20
21
|
className={classNames('ds-widget-favourites__item', className)}
|
|
21
22
|
data-testid={`widget-favourites-item-${id}`}
|
|
22
23
|
>
|
|
23
|
-
<a href={href} className={linkClassName}>
|
|
24
|
+
<a {...linkProps} href={href} className={linkClassName}>
|
|
24
25
|
{label}
|
|
25
26
|
</a>
|
|
26
27
|
{onRemove && (
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import type { WidgetHeadingLinkProps, WidgetLinkedProps } from 'Components/widget/types';
|
|
2
|
+
|
|
1
3
|
export type WidgetFavouritesItemData = {
|
|
2
4
|
id: string;
|
|
3
5
|
label: string;
|
|
4
6
|
href: string;
|
|
5
7
|
removeLabel?: string;
|
|
8
|
+
linkProps?: WidgetLinkedProps['linkProps'];
|
|
6
9
|
};
|
|
7
10
|
|
|
8
|
-
export type WidgetFavouritesProps = {
|
|
11
|
+
export type WidgetFavouritesProps = WidgetHeadingLinkProps & {
|
|
9
12
|
heading: React.ReactNode;
|
|
10
13
|
tooltip?: string;
|
|
11
14
|
items: WidgetFavouritesItemData[];
|
|
12
|
-
headingHref?: string;
|
|
13
15
|
isFloating?: boolean;
|
|
14
16
|
onRemoveItem?: (id: string) => void;
|
|
15
17
|
emptyState?: React.ReactNode;
|
|
@@ -21,6 +23,7 @@ export type WidgetFavouritesItemProps = {
|
|
|
21
23
|
label: string;
|
|
22
24
|
href: string;
|
|
23
25
|
removeLabel?: string;
|
|
26
|
+
linkProps?: WidgetLinkedProps['linkProps'];
|
|
24
27
|
onRemove?: () => void;
|
|
25
28
|
className?: string;
|
|
26
29
|
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
// Grid resolves its row against max-height, giving the content a definite height so only the body scrolls.
|
|
2
|
+
.ds-widget.ds-widget-favourites {
|
|
3
|
+
display: grid;
|
|
4
|
+
grid-template-rows: minmax(0, 1fr);
|
|
5
|
+
max-height: var(--widget-favourites-max-height);
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
.ds-widget-favourites__list {
|
|
2
9
|
list-style: none;
|
|
3
10
|
margin: 0;
|
package/src/tokens.scss
CHANGED
|
@@ -882,6 +882,7 @@
|
|
|
882
882
|
--widget-favourites-weight-border: var(--border-weight);
|
|
883
883
|
--widget-favourites-spacing-vertical: var(--spacing-small);
|
|
884
884
|
--widget-favourites-spacing-horizontal: var(--spacing-small);
|
|
885
|
+
--widget-favourites-max-height: 375px;
|
|
885
886
|
--widget-attachments-hover-color-icon: var(--color-grey-900);
|
|
886
887
|
--widget-attachments-hover-color-text: var(--color-grey-900);
|
|
887
888
|
--widget-attachments-hover-color-background: var(--color-grey-100);
|
package/tokens/json/Arbor.json
CHANGED