aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/atoms/index.ts1
-rw-r--r--src/components/atoms/links/sharing-link/sharing-link.tsx4
-rw-r--r--src/components/atoms/visually-hidden/index.ts1
-rw-r--r--src/components/atoms/visually-hidden/visually-hidden.module.scss7
-rw-r--r--src/components/atoms/visually-hidden/visually-hidden.stories.tsx48
-rw-r--r--src/components/atoms/visually-hidden/visually-hidden.test.tsx13
-rw-r--r--src/components/atoms/visually-hidden/visually-hidden.tsx26
7 files changed, 98 insertions, 2 deletions
diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts
index 4aa367a..399fdde 100644
--- a/src/components/atoms/index.ts
+++ b/src/components/atoms/index.ts
@@ -9,3 +9,4 @@ export * from './loaders';
export * from './modal';
export * from './notice';
export * from './sidebar';
+export * from './visually-hidden';
diff --git a/src/components/atoms/links/sharing-link/sharing-link.tsx b/src/components/atoms/links/sharing-link/sharing-link.tsx
index 186000e..a460a4d 100644
--- a/src/components/atoms/links/sharing-link/sharing-link.tsx
+++ b/src/components/atoms/links/sharing-link/sharing-link.tsx
@@ -1,4 +1,5 @@
import type { AnchorHTMLAttributes, FC } from 'react';
+import { VisuallyHidden } from '../../visually-hidden';
import styles from './sharing-link.module.scss';
export type SharingMedium =
@@ -44,8 +45,7 @@ export const SharingLink: FC<SharingLinkProps> = ({
return (
<a {...props} className={linkClass} href={url}>
- {/* eslint-disable-next-line -- SR class allowed */}
- <span className="screen-reader-text">{label}</span>
+ <VisuallyHidden>{label}</VisuallyHidden>
</a>
);
};
diff --git a/src/components/atoms/visually-hidden/index.ts b/src/components/atoms/visually-hidden/index.ts
new file mode 100644
index 0000000..76fd520
--- /dev/null
+++ b/src/components/atoms/visually-hidden/index.ts
@@ -0,0 +1 @@
+export * from './visually-hidden';
diff --git a/src/components/atoms/visually-hidden/visually-hidden.module.scss b/src/components/atoms/visually-hidden/visually-hidden.module.scss
new file mode 100644
index 0000000..c616615
--- /dev/null
+++ b/src/components/atoms/visually-hidden/visually-hidden.module.scss
@@ -0,0 +1,7 @@
+@use "../../../styles/abstracts/mixins" as mix;
+
+.wrapper {
+ &:not(:focus-within, :active) {
+ @include mix.visually-hidden;
+ }
+}
diff --git a/src/components/atoms/visually-hidden/visually-hidden.stories.tsx b/src/components/atoms/visually-hidden/visually-hidden.stories.tsx
new file mode 100644
index 0000000..24ac921
--- /dev/null
+++ b/src/components/atoms/visually-hidden/visually-hidden.stories.tsx
@@ -0,0 +1,48 @@
+import type { ComponentMeta, ComponentStory } from '@storybook/react';
+import { Link } from '../links';
+import { VisuallyHidden } from './visually-hidden';
+
+/**
+ * Sidebar - Storybook Meta
+ */
+export default {
+ title: 'Atoms/VisuallyHidden',
+ component: VisuallyHidden,
+ argTypes: {
+ children: {
+ control: {
+ type: 'text',
+ },
+ description: 'The contents to visually hide.',
+ type: {
+ name: 'string',
+ required: true,
+ },
+ },
+ },
+} as ComponentMeta<typeof VisuallyHidden>;
+
+const Template: ComponentStory<typeof VisuallyHidden> = (args) => (
+ <VisuallyHidden {...args} />
+);
+
+/**
+ * VisuallyHidden Stories - Not focusable
+ */
+export const NotFocusable = Template.bind({});
+NotFocusable.args = {
+ children: 'Esse quia deserunt animi id sit voluptatem aperiam.',
+};
+
+/**
+ * VisuallyHidden Stories - Focusable
+ */
+export const Focusable = Template.bind({});
+Focusable.args = {
+ children: (
+ <>
+ {'Esse quia deserunt animi id sit voluptatem aperiam. '}
+ <Link href="#">Any link.</Link>
+ </>
+ ),
+};
diff --git a/src/components/atoms/visually-hidden/visually-hidden.test.tsx b/src/components/atoms/visually-hidden/visually-hidden.test.tsx
new file mode 100644
index 0000000..c5eb647
--- /dev/null
+++ b/src/components/atoms/visually-hidden/visually-hidden.test.tsx
@@ -0,0 +1,13 @@
+import { describe, expect, it } from '@jest/globals';
+import { render, screen as rtlScreen } from '@testing-library/react';
+import { VisuallyHidden } from './visually-hidden';
+
+describe('VisuallyHidden', () => {
+ it('renders its body', () => {
+ const body = 'natus vero doloremque';
+
+ render(<VisuallyHidden>{body}</VisuallyHidden>);
+
+ expect(rtlScreen.getByText(body)).toBeInTheDocument();
+ });
+});
diff --git a/src/components/atoms/visually-hidden/visually-hidden.tsx b/src/components/atoms/visually-hidden/visually-hidden.tsx
new file mode 100644
index 0000000..a877321
--- /dev/null
+++ b/src/components/atoms/visually-hidden/visually-hidden.tsx
@@ -0,0 +1,26 @@
+import type { FC, HTMLAttributes, ReactNode } from 'react';
+import styles from './visually-hidden.module.scss';
+
+export type VisuallyHiddenProps = Omit<
+ HTMLAttributes<HTMLSpanElement>,
+ 'children'
+> & {
+ /**
+ * The contents to visually hide.
+ */
+ children: ReactNode;
+};
+
+export const VisuallyHidden: FC<VisuallyHiddenProps> = ({
+ children,
+ className = '',
+ ...props
+}) => {
+ const wrapperClass = `${styles.wrapper} ${className}`;
+
+ return (
+ <span {...props} className={wrapperClass}>
+ {children}
+ </span>
+ );
+};