Skip to content

Commit bda1abe

Browse files
authored
Merge branch 'main' into jh-md-scss
2 parents 011cf9c + 6ba486b commit bda1abe

File tree

9 files changed

+162
-10
lines changed

9 files changed

+162
-10
lines changed

packages/gamut-kit/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
### [0.6.511](https://github.com/Codecademy/gamut/compare/@codecademy/gamut-kit@0.6.510...@codecademy/gamut-kit@0.6.511) (2025-06-04)
7+
8+
**Note:** Version bump only for package @codecademy/gamut-kit
9+
610
### [0.6.510](https://github.com/Codecademy/gamut/compare/@codecademy/gamut-kit@0.6.509...@codecademy/gamut-kit@0.6.510) (2025-06-04)
711

812
**Note:** Version bump only for package @codecademy/gamut-kit

packages/gamut-kit/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "@codecademy/gamut-kit",
33
"description": "Styleguide & Component library for Codecademy",
4-
"version": "0.6.510",
4+
"version": "0.6.511",
55
"author": "Codecademy Engineering <dev@codecademy.com>",
66
"dependencies": {
7-
"@codecademy/gamut": "64.0.1",
7+
"@codecademy/gamut": "64.0.2",
88
"@codecademy/gamut-icons": "9.44.0",
99
"@codecademy/gamut-illustrations": "0.54.4",
1010
"@codecademy/gamut-patterns": "0.10.10",

packages/gamut/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
### [64.0.2](https://github.com/Codecademy/gamut/compare/@codecademy/gamut@64.0.1...@codecademy/gamut@64.0.2) (2025-06-04)
7+
8+
**Note:** Version bump only for package @codecademy/gamut
9+
610
### [64.0.1](https://github.com/Codecademy/gamut/compare/@codecademy/gamut@64.0.0...@codecademy/gamut@64.0.1) (2025-06-04)
711

812
**Note:** Version bump only for package @codecademy/gamut

packages/gamut/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@codecademy/gamut",
33
"description": "Styleguide & Component library for Codecademy",
4-
"version": "64.0.1",
4+
"version": "64.0.2",
55
"author": "Codecademy Engineering <dev@codecademy.com>",
66
"dependencies": {
77
"@codecademy/gamut-icons": "9.44.0",
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import { setupRtl } from '@codecademy/gamut-tests';
2+
import userEvent from '@testing-library/user-event';
3+
import { act, useState } from 'react';
4+
5+
import { Tab, TabList, TabPanel, TabPanels, Tabs, TabsProps } from '../index';
6+
7+
const FullTabs = (props: TabsProps) => (
8+
<Tabs {...props}>
9+
<TabList>
10+
<Tab id="tab1">Tab 1</Tab>
11+
<Tab id="tab2">Tab 2</Tab>
12+
<Tab id="tab3" isDisabled>
13+
Tab 3
14+
</Tab>
15+
</TabList>
16+
<TabPanels>
17+
<TabPanel id="tab1">
18+
<p>tab 1 content</p>
19+
</TabPanel>
20+
<TabPanel id="tab2">
21+
<p>tab 2 content</p>
22+
</TabPanel>
23+
<TabPanel id="tab3">
24+
<p>tab 3 content</p>
25+
</TabPanel>
26+
</TabPanels>
27+
</Tabs>
28+
);
29+
30+
const FullTabsControlled = (props: TabsProps) => {
31+
const [activeTab, setActiveTab] = useState(props.selectedKey ?? 'tab1');
32+
return (
33+
<Tabs
34+
{...props}
35+
selectedKey={activeTab}
36+
onSelectionChange={(newTab) => {
37+
props.onSelectionChange?.(newTab);
38+
setActiveTab(newTab);
39+
}}
40+
>
41+
<TabList>
42+
<Tab id="tab1">Tab 1</Tab>
43+
<Tab id="tab2">Tab 2</Tab>
44+
<Tab id="tab3" isDisabled>
45+
Tab 3
46+
</Tab>
47+
</TabList>
48+
<TabPanels>
49+
<TabPanel id="tab1">
50+
<p>tab 1 content</p>
51+
</TabPanel>
52+
<TabPanel id="tab2">
53+
<p>tab 2 content</p>
54+
</TabPanel>
55+
<TabPanel id="tab3">
56+
<p>tab 3 content</p>
57+
</TabPanel>
58+
</TabPanels>
59+
</Tabs>
60+
);
61+
};
62+
63+
const mockOnSelectionChange = jest.fn();
64+
const renderView = setupRtl(FullTabs, {
65+
onSelectionChange: mockOnSelectionChange,
66+
});
67+
const renderViewControlled = setupRtl(FullTabsControlled, {
68+
onSelectionChange: mockOnSelectionChange,
69+
});
70+
71+
describe('Tabs', () => {
72+
describe('Uncontrolled', () => {
73+
it('renders the first tab and first tab panel when no default selected key is passed', () => {
74+
const { view } = renderView();
75+
76+
view.getByText('Tab 1');
77+
view.getByText('tab 1 content');
78+
});
79+
80+
it('renders the second tab tab panel and calls onSelectionChange when second tab is clicked', async () => {
81+
const { view } = renderView();
82+
83+
view.getByText('tab 1 content');
84+
85+
await act(() => userEvent.click(view.getByText('Tab 2')));
86+
87+
view.getByText('tab 2 content');
88+
expect(mockOnSelectionChange).toHaveBeenCalledWith('tab2');
89+
});
90+
91+
it('renders the default selected key when passed', () => {
92+
const { view } = renderView({ defaultSelectedKey: 'tab2' });
93+
94+
view.getByText('Tab 2');
95+
view.getByText('tab 2 content');
96+
});
97+
});
98+
describe('Controlled', () => {
99+
it('renders the first tab and first tab panel', () => {
100+
const { view } = renderViewControlled();
101+
102+
view.getByText('Tab 1');
103+
view.getByText('tab 1 content');
104+
});
105+
106+
it('renders new tab panel and calls onSelectionChange when a tab is clicked', async () => {
107+
const { view } = renderViewControlled();
108+
109+
view.getByText('tab 1 content');
110+
111+
await act(() => userEvent.click(view.getByText('Tab 2')));
112+
113+
expect(mockOnSelectionChange).toHaveBeenCalledWith('tab2');
114+
view.getByText('tab 2 content');
115+
});
116+
});
117+
describe('Disabled', () => {
118+
it('renders tab as disabled when isDisabled is passed', () => {
119+
const { view } = renderView();
120+
121+
const tab = view.getByText('Tab 3');
122+
expect(tab).toHaveAttribute('aria-disabled', 'true');
123+
expect(tab).toHaveStyle('opacity: 0.25');
124+
});
125+
126+
it('renders tab keys as disabled when disabledKeys is passed', () => {
127+
const { view } = renderView({ disabledKeys: ['tab2'] });
128+
129+
const tab = view.getByText('Tab 2');
130+
expect(tab).toHaveAttribute('aria-disabled', 'true');
131+
expect(tab).toHaveStyle('opacity: 0.25');
132+
});
133+
});
134+
});

packages/styleguide/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
### [75.0.1](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@75.0.0...@codecademy/styleguide@75.0.1) (2025-06-04)
7+
8+
**Note:** Version bump only for package @codecademy/styleguide
9+
610
## [75.0.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@74.1.0...@codecademy/styleguide@75.0.0) (2025-06-03)
711

812
### ⚠ BREAKING CHANGES

packages/styleguide/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@codecademy/styleguide",
33
"description": "Styleguide & Component library for codecademy.com",
4-
"version": "75.0.0",
4+
"version": "75.0.1",
55
"author": "Codecademy Engineering",
66
"license": "MIT",
77
"publishConfig": {

packages/styleguide/src/lib/Typography/Text/Text.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ Text has some special props with common use cases to make your life easier.
9595

9696
<Canvas of={TextStories.Screenreader} />
9797

98+
If you need the focus indicator of a screenreader to stay on the screen, you can wrap the screenreader `Text` inside a parent element, like `Box` and set its `aria-labeledby` attribute to that matches the `id` of the `Text`. Depending on your use case, you might need to also set `aria-hidden` on the `Text` in order for the screenreader to not read the same text twice. Inspect the example above to see how it works.
99+
98100
### Highlight
99101

100102
<Canvas of={TextStories.Highlight} />

packages/styleguide/src/lib/Typography/Text/Text.stories.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Column, LayoutGrid, Text } from '@codecademy/gamut';
1+
import { Box, Column, LayoutGrid, Text } from '@codecademy/gamut';
22
// eslint-disable-next-line gamut/import-paths
33
import {
44
typographyElementVariants,
@@ -131,11 +131,15 @@ export const Screenreader: Story = {
131131
</Text>
132132
</Column>
133133
<Column size={9}>
134-
<Text screenreader={variant}>
135-
{variant
136-
? 'Visible only to screenreaders'
137-
: 'When set to "false", this text is visible to non-screenreaders.'}
138-
</Text>
134+
{variant ? (
135+
<Box aria-labelledby="example-sr-text" role="note" width={4}>
136+
<Text aria-hidden id="example-sr-text" screenreader>
137+
Visible only to screenreaders
138+
</Text>
139+
</Box>
140+
) : (
141+
<Text>This text is visible to non-screenreaders.</Text>
142+
)}
139143
</Column>
140144
</Fragment>
141145
))}

0 commit comments

Comments
 (0)