From d0334a1bb0a1834ce9a357971ae0360702782190 Mon Sep 17 00:00:00 2001 From: James Ah Yong Date: Fri, 4 Sep 2020 18:18:01 -0400 Subject: [PATCH 1/3] refactor: file hierarchy - components should all be in components folder - entry point should not always return a promise - entry point should be primary component - remove old RisingYouth terminology BREAKING CHANGE --- index.js | 5 - package.json | 2 +- src/components/A11yWrapper.js | 589 ------------------ src/components/A11yWrapper.stories.js | 2 +- .../index.js => components/ColorizeFilter.js} | 0 src/components/Panel.js | 35 ++ src/index.js | 565 ++++++++++++++++- src/with-react.js | 2 +- 8 files changed, 600 insertions(+), 600 deletions(-) delete mode 100644 index.js delete mode 100644 src/components/A11yWrapper.js rename src/{ColorizeFilter/index.js => components/ColorizeFilter.js} (100%) create mode 100644 src/components/Panel.js diff --git a/index.js b/index.js deleted file mode 100644 index 4d75547..0000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// eslint-disable-next-line import/no-unresolved -const bare = require('./dist/bare'); - -// Only export the bare version, anything else should be imported from dist -module.exports = bare; diff --git a/package.json b/package.json index 097056e..e66e11c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@takingitglobal/a11ize", "repository": "https://github.com/takingitglobal/a11ize.git", - "main": "index.js", + "main": "src/index.js", "jsdelivr": "dist/with-react-cjs/index.js", "version": "0.0.0-development", "description": "A React and JS Accessibility Toolkit", diff --git a/src/components/A11yWrapper.js b/src/components/A11yWrapper.js deleted file mode 100644 index cb79f8b..0000000 --- a/src/components/A11yWrapper.js +++ /dev/null @@ -1,589 +0,0 @@ -// react button goes here -import React, { useState, useEffect, useRef } from 'react'; -import PropTypes from 'prop-types'; -import cx from 'classnames'; -import { - FaTextHeight, - FaTextWidth, - FaUniversalAccess, - FaBan, -} from 'react-icons/fa'; - -import { MdFormatLineSpacing } from 'react-icons/md'; -import styles from './A11yWrapper.module.scss'; -import ColorizeFilter from '../ColorizeFilter'; - -const i18n = { - // eslint-disable-next-line global-require - en: require('../i18n/en.yml'), - // eslint-disable-next-line global-require - fr: require('../i18n/fr.yml'), -}; - -const AccessibilityPanel = ({ - id, - activePanels, - heading, - label, - children: panelChildren, -}) => { - const panelId = id.split('-')[id.split('-').length - 1]; - return ( - activePanels.includes(panelId) && ( -
-

{heading}

- -
{panelChildren}
-
- ) - ); -}; - -AccessibilityPanel.propTypes = { - id: PropTypes.string.isRequired, - heading: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - children: PropTypes.element.isRequired, - activePanels: PropTypes.arrayOf(PropTypes.string).isRequired, -}; - -const AccessibilityButton = ({ - id, - children, - dangerouslySet, - lang = 'en', - primaryColor = '#921d5b', - secondaryColor = '#01364c', - buttonColor = '#fff', - activePanels, -}) => { - const [active, setActive] = useState(false); - const contentRef = useRef(); - // font size - const [fontScale, setFontScaleRaw] = useState(1); - const setFontScale = (value) => { - if (value >= 0.5 && value <= 2.0) { - setFontScaleRaw(value); - } - }; - // font family - const [fontFamily, setFontFamily] = useState('Default'); - // line height - const [lineSpacing, setLineSpacingRaw] = useState(1); - const setLineSpacing = (value) => { - if (value >= 1 && value <= 2.0) { - setLineSpacingRaw(value); - } - }; - // letter spacing - const [letterSpacing, setLetterSpacingRaw] = useState(0); - const setLetterSpacing = (value) => { - if (value >= 0 && value <= 5) { - setLetterSpacingRaw(value); - } - }; - // word spacing - const [wordSpacing, setWordSpacingRaw] = useState(0); - const setWordSpacing = (value) => { - if (value >= 0 && value <= 10) { - setWordSpacingRaw(value); - } - }; - // theme - const [theme, setTheme] = useState('Default'); - // switches - const [clickableHighlight, setClickableHighlight] = useState(false); - const [tableOfContents, setTableOfContents] = useState(false); - - useEffect(() => { - if (typeof document === 'object') { - // modify definition of 1 rem - document.documentElement.style.fontSize = `${fontScale}rem`; - // push window resize event for polyfills - if (typeof window === 'object') { - const evt = document.createEvent('Event'); - evt.initEvent('resize', true, false); - window.dispatchEvent(evt); - } - } - }, [fontScale, fontFamily, lineSpacing, letterSpacing, wordSpacing]); - - // persist on page changes - const restoreState = () => { - if (typeof window === 'object') { - const stateString = window.localStorage.getItem('a11y-state'); - const state = stateString ? JSON.parse(stateString) : {}; - // console.log(state); - setActive(false); - setFontScaleRaw(state.fontScale || 1); - setFontFamily(state.fontFamily || 'Default'); - setLineSpacingRaw(state.lineSpacing || 1); - setLetterSpacingRaw(state.letterSpacing || 0); - setWordSpacingRaw(state.wordSpacing || 0); - setTheme(state.theme || 'Default'); - setClickableHighlight(state.clickableHighlight || false); - setTableOfContents(state.tableOfContents || false); - } - }; - - // initial load - const text = i18n[lang] ? i18n[lang] : i18n.en; - useEffect(async () => { - restoreState(); - // lazily load font - await import('../opendyslexic.scss'); - }, []); - - useEffect(() => { - if (typeof window === 'object') { - const state = { - fontScale, - fontFamily, - lineSpacing, - letterSpacing, - wordSpacing, - theme, - clickableHighlight, - tableOfContents, - }; - window.localStorage.setItem('a11y-state', JSON.stringify(state)); - } - }, [ - fontScale, - fontFamily, - lineSpacing, - letterSpacing, - wordSpacing, - theme, - clickableHighlight, - tableOfContents, - ]); - - // i18n helpers - const toggleText = (what, on) => - `${text.toggle} ${what.toLowerCase()} (${text.currently} ${ - on ? text.toggleOn : text.toggleOff - })`; - const increase = (what) => `${text.up} ${what.toLowerCase()}`; - const decrease = (what) => `${text.down} ${what.toLowerCase()}`; - - const themes = ['Default', 'Bw', 'Wb', 'By', 'Yb', 'Brown']; - - const headers = contentRef.current - ? Array.from(contentRef.current.querySelectorAll('h1, h2, h3, h4, h5, h6')) - : []; - let toc = ''; - let currentHeader = 0; - headers.forEach((header) => { - const level = Number.parseInt(header.tagName.substring(1), 10); - if (level > currentHeader) { - toc += new Array(level - currentHeader + 1).join(''); - } - - let href = header.getAttribute('id'); - if (!href) { - const slug = header.innerHTML.toLowerCase().replace(/[^0-9a-z]+/g, '-'); - header.setAttribute('id', slug); - href = slug; - } - toc += ` -
  • - ${header.innerHTML} -
  • - `; - currentHeader = level; - }); - if (currentHeader) toc += new Array(currentHeader + 1).join(''); - - return ( - // menu -
    -
    -
    - - - - setFontScale(e.currentTarget.value)} - /> - - - - - - - - - - setLineSpacing(e.currentTarget.value)} - /> - - - - - - - setLetterSpacing(e.currentTarget.value)} - /> - - - - - - setWordSpacing(e.currentTarget.value)} - /> - - - -
    - {themes.map((className) => ( - - ))} - - {/* svg mask over the entire page go brrrr */} - -
    -
    - - {text.off} - - {text.on} - - - {text.off} - - {text.on} - -
    -
    -
    - -
    - -
    -
    1 ? `${lineSpacing * 1.6}` : 'normal', - }} - ref={contentRef} - > - {tableOfContents && ( -
    -
    -
    - {text.toc} -
      -
    -
    -
    - )} - {children} - {dangerouslySet && ( -
    - )} -
    -
    - ); -}; - -AccessibilityButton.propTypes = { - id: PropTypes.string, - children: PropTypes.element, - dangerouslySet: PropTypes.string, - lang: PropTypes.string, - primaryColor: PropTypes.string, - secondaryColor: PropTypes.string, - buttonColor: PropTypes.string, - activePanels: PropTypes.arrayOf(PropTypes.string), -}; - -AccessibilityButton.defaultProps = { - id: 'a11ize', - children: undefined, - dangerouslySet: undefined, - lang: 'en', - primaryColor: '#921d5b', - secondaryColor: '#01364c', - buttonColor: '#fff', - activePanels: [ - 'textsize', - 'fontfamily', - 'linespacing', - 'letterspacing', - 'wordspacing', - 'contrast', - 'clickables', - 'toc', - ], -}; - -export default AccessibilityButton; diff --git a/src/components/A11yWrapper.stories.js b/src/components/A11yWrapper.stories.js index c60d670..56688b3 100644 --- a/src/components/A11yWrapper.stories.js +++ b/src/components/A11yWrapper.stories.js @@ -1,7 +1,7 @@ import React from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies import { withKnobs, text } from '@storybook/addon-knobs'; -import A11yWrapper from './A11yWrapper'; +import A11yWrapper from '../index'; export default { title: 'a11ize', diff --git a/src/ColorizeFilter/index.js b/src/components/ColorizeFilter.js similarity index 100% rename from src/ColorizeFilter/index.js rename to src/components/ColorizeFilter.js diff --git a/src/components/Panel.js b/src/components/Panel.js new file mode 100644 index 0000000..c6ea5ae --- /dev/null +++ b/src/components/Panel.js @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import styles from './A11yWrapper.module.scss'; + +const Panel = ({ + id, + activePanels, + heading, + label, + children: panelChildren, +}) => { + const panelId = id.split('-')[id.split('-').length - 1]; + return ( + activePanels.includes(panelId) && ( +
    +

    {heading}

    + +
    {panelChildren}
    +
    + ) + ); +}; + +Panel.propTypes = { + id: PropTypes.string.isRequired, + heading: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + children: PropTypes.element.isRequired, + activePanels: PropTypes.arrayOf(PropTypes.string).isRequired, +}; + +export default Panel; diff --git a/src/index.js b/src/index.js index 3bc656c..b04c565 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,562 @@ -const { A11yWrapper } = import('./components/A11yWrapper'); -// eslint-disable-next-line import/prefer-default-export -export { A11yWrapper }; +// react button goes here +import React, { useState, useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import cx from 'classnames'; +import { + FaTextHeight, + FaTextWidth, + FaUniversalAccess, + FaBan, +} from 'react-icons/fa'; +import { MdFormatLineSpacing } from 'react-icons/md'; + +import styles from './components/A11yWrapper.module.scss'; +import ColorizeFilter from './components/ColorizeFilter'; +import Panel from './components/Panel'; + +// TODO: dynamic require to minimize bundle size +const i18n = { + // eslint-disable-next-line global-require + en: require('./i18n/en.yml'), + // eslint-disable-next-line global-require + fr: require('./i18n/fr.yml'), +}; + +const A11yWrapper = ({ + id, + children, + dangerouslySet, + lang = 'en', + primaryColor = '#921d5b', + secondaryColor = '#01364c', + buttonColor = '#fff', + activePanels, +}) => { + const [active, setActive] = useState(false); + const contentRef = useRef(); + // font size + const [fontScale, setFontScaleRaw] = useState(1); + const setFontScale = (value) => { + if (value >= 0.5 && value <= 2.0) { + setFontScaleRaw(value); + } + }; + // font family + const [fontFamily, setFontFamily] = useState('Default'); + // line height + const [lineSpacing, setLineSpacingRaw] = useState(1); + const setLineSpacing = (value) => { + if (value >= 1 && value <= 2.0) { + setLineSpacingRaw(value); + } + }; + // letter spacing + const [letterSpacing, setLetterSpacingRaw] = useState(0); + const setLetterSpacing = (value) => { + if (value >= 0 && value <= 5) { + setLetterSpacingRaw(value); + } + }; + // word spacing + const [wordSpacing, setWordSpacingRaw] = useState(0); + const setWordSpacing = (value) => { + if (value >= 0 && value <= 10) { + setWordSpacingRaw(value); + } + }; + // theme + const [theme, setTheme] = useState('Default'); + // switches + const [clickableHighlight, setClickableHighlight] = useState(false); + const [tableOfContents, setTableOfContents] = useState(false); + + useEffect(() => { + if (typeof document === 'object') { + // modify definition of 1 rem + document.documentElement.style.fontSize = `${fontScale}rem`; + // push window resize event for polyfills + if (typeof window === 'object') { + const evt = document.createEvent('Event'); + evt.initEvent('resize', true, false); + window.dispatchEvent(evt); + } + } + }, [fontScale, fontFamily, lineSpacing, letterSpacing, wordSpacing]); + + // persist on page changes + const restoreState = () => { + if (typeof window === 'object') { + const stateString = window.localStorage.getItem('a11y-state'); + const state = stateString ? JSON.parse(stateString) : {}; + // console.log(state); + setActive(false); + setFontScaleRaw(state.fontScale || 1); + setFontFamily(state.fontFamily || 'Default'); + setLineSpacingRaw(state.lineSpacing || 1); + setLetterSpacingRaw(state.letterSpacing || 0); + setWordSpacingRaw(state.wordSpacing || 0); + setTheme(state.theme || 'Default'); + setClickableHighlight(state.clickableHighlight || false); + setTableOfContents(state.tableOfContents || false); + } + }; + + // initial load + const text = i18n[lang] ? i18n[lang] : i18n.en; + useEffect(async () => { + restoreState(); + // lazily load font + await import('./opendyslexic.scss'); + }, []); + + useEffect(() => { + if (typeof window === 'object') { + const state = { + fontScale, + fontFamily, + lineSpacing, + letterSpacing, + wordSpacing, + theme, + clickableHighlight, + tableOfContents, + }; + window.localStorage.setItem('a11y-state', JSON.stringify(state)); + } + }, [ + fontScale, + fontFamily, + lineSpacing, + letterSpacing, + wordSpacing, + theme, + clickableHighlight, + tableOfContents, + ]); + + // i18n helpers + const toggleText = (what, on) => + `${text.toggle} ${what.toLowerCase()} (${text.currently} ${ + on ? text.toggleOn : text.toggleOff + })`; + const increase = (what) => `${text.up} ${what.toLowerCase()}`; + const decrease = (what) => `${text.down} ${what.toLowerCase()}`; + + const themes = ['Default', 'Bw', 'Wb', 'By', 'Yb', 'Brown']; + + const headers = contentRef.current + ? Array.from(contentRef.current.querySelectorAll('h1, h2, h3, h4, h5, h6')) + : []; + let toc = ''; + let currentHeader = 0; + headers.forEach((header) => { + const level = Number.parseInt(header.tagName.substring(1), 10); + if (level > currentHeader) { + toc += new Array(level - currentHeader + 1).join(''); + } + + let href = header.getAttribute('id'); + if (!href) { + const slug = header.innerHTML.toLowerCase().replace(/[^0-9a-z]+/g, '-'); + header.setAttribute('id', slug); + href = slug; + } + toc += ` +
  • + ${header.innerHTML} +
  • + `; + currentHeader = level; + }); + if (currentHeader) toc += new Array(currentHeader + 1).join(''); + + return ( + // menu +
    +
    +
    + + + + setFontScale(e.currentTarget.value)} + /> + + + + + + + + + + setLineSpacing(e.currentTarget.value)} + /> + + + + + + + setLetterSpacing(e.currentTarget.value)} + /> + + + + + + setWordSpacing(e.currentTarget.value)} + /> + + + +
    + {themes.map((className) => ( + + ))} + + {/* svg mask over the entire page go brrrr */} + +
    +
    + + {text.off} + + {text.on} + + + {text.off} + + {text.on} + +
    +
    +
    + +
    + +
    +
    1 ? `${lineSpacing * 1.6}` : 'normal', + }} + ref={contentRef} + > + {tableOfContents && ( +
    +
    +
    + {text.toc} +
      +
    +
    +
    + )} + {children} + {dangerouslySet && ( +
    + )} +
    +
    + ); +}; + +A11yWrapper.propTypes = { + id: PropTypes.string, + children: PropTypes.element, + dangerouslySet: PropTypes.string, + lang: PropTypes.string, + primaryColor: PropTypes.string, + secondaryColor: PropTypes.string, + buttonColor: PropTypes.string, + activePanels: PropTypes.arrayOf(PropTypes.string), +}; + +A11yWrapper.defaultProps = { + id: 'a11ize', + children: undefined, + dangerouslySet: undefined, + lang: 'en', + primaryColor: '#921d5b', + secondaryColor: '#01364c', + buttonColor: '#fff', + activePanels: [ + 'textsize', + 'fontfamily', + 'linespacing', + 'letterspacing', + 'wordspacing', + 'contrast', + 'clickables', + 'toc', + ], +}; + +export default A11yWrapper; diff --git a/src/with-react.js b/src/with-react.js index 07ff5be..ac78b00 100644 --- a/src/with-react.js +++ b/src/with-react.js @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import getBundleURL from './getBundleUrl'; -import A11yWrapper from './components/A11yWrapper'; +import A11yWrapper from './index'; // eslint-disable-next-line import/no-extraneous-dependencies import 'regenerator-runtime/runtime'; From 87deda08edc73ea3a78bc6a18c9d15076bf766aa Mon Sep 17 00:00:00 2001 From: James Ah Yong Date: Fri, 4 Sep 2020 18:27:26 -0400 Subject: [PATCH 2/3] refactor: sass to css for OpenDyslexic begin migrating off Sass dependence for styling with low hanging fruit --- src/index.js | 2 +- src/{opendyslexic.scss => opendyslexic.css} | 0 webpack.config.js | 4 ++++ 3 files changed, 5 insertions(+), 1 deletion(-) rename src/{opendyslexic.scss => opendyslexic.css} (100%) diff --git a/src/index.js b/src/index.js index b04c565..34ddd96 100644 --- a/src/index.js +++ b/src/index.js @@ -106,7 +106,7 @@ const A11yWrapper = ({ useEffect(async () => { restoreState(); // lazily load font - await import('./opendyslexic.scss'); + await import('./opendyslexic.css'); }, []); useEffect(() => { diff --git a/src/opendyslexic.scss b/src/opendyslexic.css similarity index 100% rename from src/opendyslexic.scss rename to src/opendyslexic.css diff --git a/webpack.config.js b/webpack.config.js index 895b880..8c91c44 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -58,6 +58,10 @@ module.exports = [ }, ], }, + { + test: /\.css$/, + loader: ['style-loader', 'css-loader'], + }, { test: /\.(js|jsx)$/, exclude: /node_modules/, From 59cbbcac3bbf15e1435c5eba528643716ea9079c Mon Sep 17 00:00:00 2001 From: Jason Huang Date: Sun, 15 Nov 2020 20:59:20 -0500 Subject: [PATCH 3/3] fix: patch defining fonts through css file - css loader added to webpack --- webpack.config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webpack.config.js b/webpack.config.js index 8c91c44..0008650 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -161,6 +161,10 @@ module.exports = [ }, ], }, + { + test: /\.css$/, + loader: ['style-loader', 'css-loader'], + }, { test: /\.(js|jsx)$/, exclude: /node_modules/, @@ -250,6 +254,10 @@ module.exports = [ }, ], }, + { + test: /\.css$/, + loader: ['style-loader', 'css-loader'], + }, { test: /\.(js|jsx)$/, exclude: /node_modules/,