From 48819d4833b0afe41223ef260a52814bcfe3b907 Mon Sep 17 00:00:00 2001 From: Thayanan Tharmapalan Date: Mon, 7 Feb 2022 13:23:40 +0100 Subject: [PATCH] feat(VisuallyHidden): Add VisuallyHidden component (#1246) --- .../docs/uilib/components/visually-hidden.md | 12 ++ .../components/visually-hidden/Examples.js | 41 +++++++ .../uilib/components/visually-hidden/demos.md | 31 +++++ .../components/visually-hidden/events.md | 7 ++ .../uilib/components/visually-hidden/info.md | 9 ++ .../components/visually-hidden/properties.md | 14 +++ .../stories/components/VisuallyHidden.tsx | 53 +++++++++ .../src/components/VisuallyHidden.js | 14 +++ packages/dnb-eufemia/src/components/index.js | 2 + packages/dnb-eufemia/src/components/lib.js | 3 + .../visually-hidden/VisuallyHidden.tsx | 74 ++++++++++++ .../VisuallyHidden.screenshot.test.js | 41 +++++++ .../__tests__/VisuallyHidden.test.tsx | 83 +++++++++++++ .../VisuallyHidden.test.tsx.snap | 112 ++++++++++++++++++ ...h-visually-hidden-default-1-23973.snap.png | Bin 0 -> 105 bytes ...visually-hidden-focusable-1-bcae1.snap.png | Bin 0 -> 105 bytes ...visually-hidden-focusable-2-da59f.snap.png | Bin 0 -> 105 bytes ...visually-hidden-focusable-3-960a2.snap.png | Bin 0 -> 105 bytes ...ually-hidden-span-element-1-b53dc.snap.png | Bin 0 -> 105 bytes ...-visually-hidden-use-case-1-6d23e.snap.png | Bin 0 -> 105 bytes .../src/components/visually-hidden/index.js | 8 ++ .../src/components/visually-hidden/style.js | 6 + .../style/_visually-hidden.scss | 20 ++++ .../style/dnb-visually-hidden.scss | 12 ++ .../components/visually-hidden/style/index.js | 6 + packages/dnb-eufemia/src/index.js | 2 + packages/dnb-eufemia/src/shared/Context.js | 1 + .../src/style/dnb-ui-components.scss | 1 + 28 files changed, 552 insertions(+) create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden.md create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/Examples.js create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/demos.md create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/events.md create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/info.md create mode 100644 packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/properties.md create mode 100644 packages/dnb-eufemia-sandbox/stories/components/VisuallyHidden.tsx create mode 100644 packages/dnb-eufemia/src/components/VisuallyHidden.js create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/VisuallyHidden.tsx create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.screenshot.test.js create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.test.tsx create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/VisuallyHidden.test.tsx.snap create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-default-1-23973.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-1-bcae1.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-2-da59f.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-3-960a2.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-span-element-1-b53dc.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-use-case-1-6d23e.snap.png create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/index.js create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/style.js create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/style/_visually-hidden.scss create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/style/dnb-visually-hidden.scss create mode 100644 packages/dnb-eufemia/src/components/visually-hidden/style/index.js diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden.md b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden.md new file mode 100644 index 00000000000..5a6af72cacc --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden.md @@ -0,0 +1,12 @@ +--- +title: 'VisuallyHidden' +description: 'VisuallyHidden has all the styles necessary to hide it from visual clients, but keep it for screen readers.' +status: 'new' +showTabs: true +--- + +import VisuallyHiddenInfo from 'Docs/uilib/components/visually-hidden/info' +import VisuallyHiddenDemos from 'Docs/uilib/components/visually-hidden/demos' + + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/Examples.js b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/Examples.js new file mode 100644 index 00000000000..90bfafcaa2b --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/Examples.js @@ -0,0 +1,41 @@ +/** + * UI lib Component Example + * + */ + +import ComponentBox from 'dnb-design-system-portal/src/shared/tags/ComponentBox' + + +export const VisuallyHiddenDefault = () => ( + + {() => /* jsx */ ` +Hidden content +`} + +) + +export const VisuallyHiddenFocusable = () => ( + + {() => /* jsx */ ` + + Hidden, but focusable content + +`} + +) + +export const VisuallyHiddenUseCase = () => ( + + {() => /* jsx */ ` +Read more about Eufemia +`} + +) + +export const VisuallyHiddenSpan = () => ( + + {() => /* jsx */ ` +Hidden, with custom HTML element +`} + +) \ No newline at end of file diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/demos.md b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/demos.md new file mode 100644 index 00000000000..5128064376a --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/demos.md @@ -0,0 +1,31 @@ +--- +showTabs: true +--- + +import { +VisuallyHiddenDefault, +VisuallyHiddenFocusable, +VisuallyHiddenSpan, +VisuallyHiddenUseCase, +} from 'Docs/uilib/components/visually-hidden/Examples' + +## Demos + +#### VisuallyHidden + + + +#### VisuallyHidden with focusable content + + +Use `VisuallyHidden` with `focusable={true}` to visually hide an element by default, but to display it when it’s focused (e.g. by a keyboard-only user). The container will be displayed when any child element of the container receives focus. + + + +#### VisuallyHidden with example of use case + + + +#### VisuallyHidden with custom element + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/events.md b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/events.md new file mode 100644 index 00000000000..875df1bbea9 --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/events.md @@ -0,0 +1,7 @@ +--- +showTabs: true +--- + +## Events + +No events are supported at the moment. diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/info.md b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/info.md new file mode 100644 index 00000000000..61f74652c1e --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/info.md @@ -0,0 +1,9 @@ +--- +showTabs: true +--- + +## Description + +`VisuallyHidden` is a utility component that can be used to hide its children visually, while keeping them visible to screen readers and other assistive technology. + +NOTE: Many semantic elements, such as button elements, have meaning to assistive devices and browsers that provide context for the user and, in many cases, provide or restrict interactive behaviors. Use caution when overriding our defaults and make sure that the element you choose to render provides the same experience for all users. In short: The component shouldn’t be used to hide interactive content. \ No newline at end of file diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/properties.md b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/properties.md new file mode 100644 index 00000000000..39b4da77ba8 --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/visually-hidden/properties.md @@ -0,0 +1,14 @@ +--- +showTabs: true +--- + +## Properties + +### `VisuallyHidden` properties + +| Properties | Description | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `children` | _(optional)_ The content you want to be visually hidden.It can be a `string` or a `React Element`. | +| `className` | _(optional)_ Custom className for the component root. | +| `element` | _(optional)_ Custom root HTML element for the component. Defaults to `
` | +| `focusable` | _(optional)_ Set to `true` to hide an element by default, but to display it when it’s focused (e.g. by a keyboard-only user) root. Defaults to false | \ No newline at end of file diff --git a/packages/dnb-eufemia-sandbox/stories/components/VisuallyHidden.tsx b/packages/dnb-eufemia-sandbox/stories/components/VisuallyHidden.tsx new file mode 100644 index 00000000000..264b5fb423a --- /dev/null +++ b/packages/dnb-eufemia-sandbox/stories/components/VisuallyHidden.tsx @@ -0,0 +1,53 @@ +/** + * @dnb/eufemia Component Story + * + */ + +import React from 'react' +import { VisuallyHidden } from '@dnb/eufemia/src/components' +import { Provider } from '@dnb/eufemia/src/shared' +import { Box, Wrapper } from '../helpers' + +export default { + title: 'Eufemia/Components/VisuallyHidden', +} + +export const Default = () => { + return ( + + Default + + ) +} + +export const VisuallyHiddenSandbox = () => { + return ( + + + + + + + + + ) +} + +export const VisuallyHiddenMultiple = () => { + return ( + + + + + + + ) +} + +export const VisuallyHiddenWithProvider = () => { + return ( + + + + ) +} diff --git a/packages/dnb-eufemia/src/components/VisuallyHidden.js b/packages/dnb-eufemia/src/components/VisuallyHidden.js new file mode 100644 index 00000000000..21cd0c284ba --- /dev/null +++ b/packages/dnb-eufemia/src/components/VisuallyHidden.js @@ -0,0 +1,14 @@ +/** + * ATTENTION: This file is auto generated by using "prepareTemplates". + * Do not change the content! + * + */ + +/** + * Library Index visually-hidden to autogenerate all the components and extensions + * Used by "prepareVisuallyHiddens" + */ + +import VisuallyHidden from './visually-hidden/VisuallyHidden' +export * from './visually-hidden/VisuallyHidden' +export default VisuallyHidden diff --git a/packages/dnb-eufemia/src/components/index.js b/packages/dnb-eufemia/src/components/index.js index c9d8f5862b0..62d4a4f21ed 100644 --- a/packages/dnb-eufemia/src/components/index.js +++ b/packages/dnb-eufemia/src/components/index.js @@ -49,6 +49,7 @@ import Textarea from './textarea/Textarea' import Timeline from './timeline/Timeline' import ToggleButton from './toggle-button/ToggleButton' import Tooltip from './tooltip/Tooltip' +import VisuallyHidden from './visually-hidden/VisuallyHidden' // define / export all the available components export { @@ -91,4 +92,5 @@ export { Timeline, ToggleButton, Tooltip, + VisuallyHidden, } diff --git a/packages/dnb-eufemia/src/components/lib.js b/packages/dnb-eufemia/src/components/lib.js index 9a3e4f07e1b..72ddaab3d93 100644 --- a/packages/dnb-eufemia/src/components/lib.js +++ b/packages/dnb-eufemia/src/components/lib.js @@ -51,6 +51,7 @@ import Textarea from './textarea/Textarea' import Timeline from './timeline/Timeline' import ToggleButton from './toggle-button/ToggleButton' import Tooltip from './tooltip/Tooltip' +import VisuallyHidden from './visually-hidden/VisuallyHidden' // define / export all the available components export { @@ -93,6 +94,7 @@ export { Timeline, ToggleButton, Tooltip, + VisuallyHidden, } export const getComponents = () => { @@ -136,6 +138,7 @@ export const getComponents = () => { Timeline, ToggleButton, Tooltip, + VisuallyHidden, } } diff --git a/packages/dnb-eufemia/src/components/visually-hidden/VisuallyHidden.tsx b/packages/dnb-eufemia/src/components/visually-hidden/VisuallyHidden.tsx new file mode 100644 index 00000000000..c63d40f5884 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/VisuallyHidden.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import classnames from 'classnames' + +// Shared +import Context from '../../shared/Context' +import { extendPropsWithContext } from '../../shared/component-helper' + +export interface VisuallyHiddenProps { + /** + * The content of the visually hidden element, can be a string or a React Element + * Default: null + */ + children?: string | React.ReactNode // ReactNode allows multiple elements, strings, numbers, fragments, portals... + + /** + * Custom className on the component root + * Default: null + */ + className?: string + + /** + * Hide an element by default, but to display it when it’s focused (e.g. by a keyboard-only user) + * Default: false + */ + focusable?: boolean + + /** + * Root element of the component + * Default: div + */ + element?: string | React.ReactNode +} + +export const defaultProps = { + className: null, + children: null, + focusable: false, + element: 'div', +} + +const VisuallyHidden = (localProps: VisuallyHiddenProps) => { + // Every component should have a context + const context = React.useContext(Context) + + // Extract additional props from global context + const { element, children, className, focusable, ...props } = + extendPropsWithContext( + { ...defaultProps, ...localProps }, + defaultProps, + context?.translation?.VisuallyHidden, + context?.VisuallyHidden + ) + + const visuallyHiddenClassNames = classnames( + 'dnb-visually-hidden', + focusable + ? 'dnb-visually-hidden--focusable' + : 'dnb-visually-hidden--default', + className + ) + const Element = element + + return ( + + {children} + + ) +} + +export default VisuallyHidden diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.screenshot.test.js b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.screenshot.test.js new file mode 100644 index 00000000000..10d22067bec --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.screenshot.test.js @@ -0,0 +1,41 @@ +/** + * Screenshot Test + * This file will not run on "test:staged" because we don't require any related files + */ + + import { + testPageScreenshot, + setupPageScreenshot, +} from '../../../core/jest/jestSetupScreenshots' + +describe('VisuallyHidden screenshot', () => { + setupPageScreenshot({ url: '/uilib/components/visually-hidden/demos' }) + + it('have to match VisuallyHidden default', async () => { + const screenshot = await testPageScreenshot({ + selector: '[data-visual-test="visually-hidden-default"] .dnb-visually-hidden', + }) + expect(screenshot).toMatchImageSnapshot() + }) + + it('have to match VisuallyHidden focusable', async () => { + const screenshot = await testPageScreenshot({ + selector: '[data-visual-test="visually-hidden-focusable"] .dnb-visually-hidden', + }) + expect(screenshot).toMatchImageSnapshot() + }) + + it('have to match VisuallyHidden use case', async () => { + const screenshot = await testPageScreenshot({ + selector: '[data-visual-test="visually-hidden-use-case"] .dnb-visually-hidden', + }) + expect(screenshot).toMatchImageSnapshot() + }) + + it('have to match VisuallyHidden span element', async () => { + const screenshot = await testPageScreenshot({ + selector: '[data-visual-test="visually-hidden-span"] .dnb-visually-hidden', + }) + expect(screenshot).toMatchImageSnapshot() + }) +}) \ No newline at end of file diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.test.tsx b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.test.tsx new file mode 100644 index 00000000000..83e51615729 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/VisuallyHidden.test.tsx @@ -0,0 +1,83 @@ +import React from 'react' +import { render, screen } from '@testing-library/react' +import VisuallyHidden from '../VisuallyHidden' +import { axeComponent, loadScss } from '../../../core/jest/jestSetup' +import { Provider } from '../../../shared' + +describe('VisuallyHidden', () => { + it('renders without properties', () => { + render() + + expect(screen.queryByTestId('visually-hidden')).not.toBeNull() + }) + + it('renders the content by children prop', () => { + render(children) + + expect(screen.queryByTestId('visually-hidden')).not.toBeNull() + }) + + it('renders the default className', () => { + const defaultClassName = 'default' + + render(ClassName) + expect(screen.queryByTestId('visually-hidden').className).toMatch( + defaultClassName + ) + }) + + it('renders with className if className is provided', () => { + const customClassName = 'custom-class' + + render( + + ClassName + + ) + expect(screen.queryByTestId('visually-hidden').className).toMatch( + customClassName + ) + }) + + it('renders with the correct attributes if focusable is true', () => { + const focusableClassName = 'focusable' + + render(focusable) + expect(screen.queryByTestId('visually-hidden').className).toMatch( + focusableClassName + ) + }) + + it('renders with custom HTML element', () => { + render(Span) + expect(document.querySelector('span') instanceof HTMLElement).toBe( + true + ) + }) + + it('renders with provider', () => { + render( + + Provider + + ) + + expect(screen.queryByTestId('visually-hidden')).not.toBeNull() + }) + + describe('VisuallyHidden aria', () => { + it('should validate', async () => { + const Component = render(Aria) + expect(await axeComponent(Component)).toHaveNoViolations() + }) + }) + + describe('VisuallyHidden scss', () => { + it('have to match snapshot', () => { + const scss = loadScss( + require.resolve('../style/dnb-visually-hidden.scss') + ) + expect(scss).toMatchSnapshot() + }) + }) +}) diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/VisuallyHidden.test.tsx.snap b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/VisuallyHidden.test.tsx.snap new file mode 100644 index 00000000000..aea70135cf2 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/VisuallyHidden.test.tsx.snap @@ -0,0 +1,112 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`VisuallyHidden VisuallyHidden scss have to match snapshot 1`] = ` +"/* +* DNB Visually Hidden +* +*/ +/** + * This file is only used to make components independent + * so that they can get imported individually, without the core styles + * + */ +/* + * Utilities + */ +/* + * Scopes + * + */ +/* + * Document Reset + * + */ +.dnb-visually-hidden { + font-family: var(--font-family-default); + font-weight: var(--font-weight-basis); + font-size: var(--font-size-small); + font-style: normal; + line-height: var(--line-height-basis); + color: var(--color-black-80, #333); + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + /** + * Ensure consistency and use the same as HTML reset -> html {...} + * between base and code package + */ + -moz-tab-size: 4; + tab-size: 4; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + word-break: break-word; + /** + * 1. Remove repeating backgrounds in all browsers (opinionated). + * 2. Add border box sizing in all browsers (opinionated). + */ + /** + * 1. Add text decoration inheritance in all browsers (opinionated). + * 2. Add vertical alignment inheritance in all browsers (opinionated). + */ + margin: 0; + padding: 0; } + .dnb-visually-hidden *, + .dnb-visually-hidden ::before, + .dnb-visually-hidden ::after { + background-repeat: no-repeat; + /* 1 */ + box-sizing: border-box; + /* 2 */ } + .dnb-visually-hidden ::before, + .dnb-visually-hidden ::after { + text-decoration: inherit; + /* 1 */ + vertical-align: inherit; + /* 2 */ } + +/* +* VisuallyHidden component +* +*/ +.dnb-visually-hidden--default { + user-select: none; + -webkit-touch-callout: none; + pointer-events: none; + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + white-space: nowrap; + height: 1px; + width: 1px; + margin: -1px 0 0 -1px; + padding: 0; + border: 0; } + .dnb-visually-hidden--default:not(:focus):not(:active) { + user-select: none; + -webkit-touch-callout: none; + pointer-events: none; + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + white-space: nowrap; + height: 1px; + width: 1px; + margin: -1px 0 0 -1px; + padding: 0; + border: 0; } + +.dnb-visually-hidden--focusable:not(:focus):not(:focus-within) { + user-select: none; + -webkit-touch-callout: none; + pointer-events: none; + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + white-space: nowrap; + height: 1px; + width: 1px; + margin: -1px 0 0 -1px; + padding: 0; + border: 0; } +" +`; diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-default-1-23973.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-default-1-23973.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-1-bcae1.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-1-bcae1.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-2-da59f.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-2-da59f.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-3-960a2.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-focusable-3-960a2.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-span-element-1-b53dc.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-span-element-1-b53dc.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-use-case-1-6d23e.snap.png b/packages/dnb-eufemia/src/components/visually-hidden/__tests__/__snapshots__/visually-hidden-screenshot-test-js-visually-hidden-screenshot-have-to-match-visually-hidden-use-case-1-6d23e.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7a39e7a773e637f38ff558b2e61b11bf3879f4ab GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yL!3HFEsI3eHQU;zbjv*1PZ_gPrGB9u)HaM{V sxgvAl6^F~7LG5Rs$^ca$fd{M!j0I0v?B;DfY6lYbboFyt=akR{0MXVOF8}}l literal 0 HcmV?d00001 diff --git a/packages/dnb-eufemia/src/components/visually-hidden/index.js b/packages/dnb-eufemia/src/components/visually-hidden/index.js new file mode 100644 index 00000000000..b7eb350d582 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/index.js @@ -0,0 +1,8 @@ +/** + * Component Entry + * + */ + +import VisuallyHidden from './VisuallyHidden' +export default VisuallyHidden +export * from './VisuallyHidden' diff --git a/packages/dnb-eufemia/src/components/visually-hidden/style.js b/packages/dnb-eufemia/src/components/visually-hidden/style.js new file mode 100644 index 00000000000..5ff6d73bbba --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/style.js @@ -0,0 +1,6 @@ +/** + * Web Style Import + * + */ + +import './style/dnb-visually-hidden.scss' diff --git a/packages/dnb-eufemia/src/components/visually-hidden/style/_visually-hidden.scss b/packages/dnb-eufemia/src/components/visually-hidden/style/_visually-hidden.scss new file mode 100644 index 00000000000..e401efc0df8 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/style/_visually-hidden.scss @@ -0,0 +1,20 @@ +/* +* VisuallyHidden component +* +*/ + +.dnb-visually-hidden { + &--default { + @include srOnly(); + + &:not(:focus):not(:active) { + @include srOnly(); + } + } + + &--focusable { + &:not(:focus):not(:focus-within) { + @include srOnly(); + } + } +} diff --git a/packages/dnb-eufemia/src/components/visually-hidden/style/dnb-visually-hidden.scss b/packages/dnb-eufemia/src/components/visually-hidden/style/dnb-visually-hidden.scss new file mode 100644 index 00000000000..41ee6864bf5 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/style/dnb-visually-hidden.scss @@ -0,0 +1,12 @@ +/* +* DNB Visually Hidden +* +*/ + +@import '../../../style/components/imports.scss'; + +.dnb-visually-hidden { + @include componentReset(); +} + +@import './_visually-hidden.scss'; diff --git a/packages/dnb-eufemia/src/components/visually-hidden/style/index.js b/packages/dnb-eufemia/src/components/visually-hidden/style/index.js new file mode 100644 index 00000000000..b22ad777988 --- /dev/null +++ b/packages/dnb-eufemia/src/components/visually-hidden/style/index.js @@ -0,0 +1,6 @@ +/** + * Web Style Import + * + */ + +import './dnb-visually-hidden.scss' diff --git a/packages/dnb-eufemia/src/index.js b/packages/dnb-eufemia/src/index.js index 5244c86e2fb..74e6fe038e4 100644 --- a/packages/dnb-eufemia/src/index.js +++ b/packages/dnb-eufemia/src/index.js @@ -49,6 +49,7 @@ import Textarea from './components/textarea/Textarea' import Timeline from './components/timeline/Timeline' import ToggleButton from './components/toggle-button/ToggleButton' import Tooltip from './components/tooltip/Tooltip' +import VisuallyHidden from './components/visually-hidden/VisuallyHidden' import Anchor from './elements/Anchor' import Blockquote from './elements/Blockquote' import Code from './elements/Code' @@ -120,6 +121,7 @@ export { Timeline, ToggleButton, Tooltip, + VisuallyHidden, Anchor, Blockquote, Code, diff --git a/packages/dnb-eufemia/src/shared/Context.js b/packages/dnb-eufemia/src/shared/Context.js index ac45e2002aa..85577ab3f66 100644 --- a/packages/dnb-eufemia/src/shared/Context.js +++ b/packages/dnb-eufemia/src/shared/Context.js @@ -56,6 +56,7 @@ export const prepareContext = (props = {}) => { TagGroup: {}, Timeline: {}, TimelineItem: {}, + VisuallyHidden: {}, ...props, translation, // make sure we set this after props, since we update this one! } diff --git a/packages/dnb-eufemia/src/style/dnb-ui-components.scss b/packages/dnb-eufemia/src/style/dnb-ui-components.scss index 3b0b22089af..16bc4f6a816 100644 --- a/packages/dnb-eufemia/src/style/dnb-ui-components.scss +++ b/packages/dnb-eufemia/src/style/dnb-ui-components.scss @@ -44,3 +44,4 @@ @import '../components/timeline/style/_timeline.scss'; @import '../components/toggle-button/style/_toggle-button.scss'; @import '../components/tooltip/style/_tooltip.scss'; +@import '../components/visually-hidden/style/_visually-hidden.scss';