Open 72gm opened 1 year ago
Hello, it sounds like you're not initialising the tabs component. The 'js-initialised' class is added by JavaScript when the component is set up.
If you are including the compiled pattern-library.js file, you would want to do something like:
const tabSets = [].slice.call(document.querySelectorAll('[data-module="ds-tabs"]'));
tabSets.forEach(tabSet => new window.DS.components.Tabs(tabSet).init());
Alternatively, calling window.DS.initAll(myElement) will initialise all Design System components inside 'myElement' ('myElement' defaults to window.document if it's not specified).
Hi,
Can you provide advice on how to best import the JS into a React Typescript app?
We've had a few issues trying to get this to work so have written our own as and when we need it but going forward I'm not sure that is the best solution?
Thanks
We do not have any React expertise on the team I'm afraid. However, we are considering a move to TypeScript.
Component scripts are written as ES6 modules and can be found in the /src folder, if that helps at all. That is likely to change if we move to TypeScript, after which we would have the .ts files in /src and provide compiled JS for each component elsewhere.
If we load the javascript that is in the dist folder via a script tag it doesn't work in the application - I'm guessing because it is SIF and it would need the html to be there to attach whatever functionality it needs to attach? Which isn't going to work in a dynamic SPA? right?
The stuff that's in the src folder doesn't seem to import properly so we are probably quicker writing our own as and when required
Or am I misunderstanding?
Thanks
The JavaScript file doesn't do anything on its own, but it does add a "DS" object to the global scope. When your page is ready to set up the components, you can do window.DS.initAll().
window.DS.initAll();
You can also do that whenever the view in your SPA changes and you need to set up new components, and restrict it to the new part of the page.
window.DS.initAll(myNewSection);
If you need finer control, the classes for each component are in window.DS.components. If you wanted to set up some new accordions, for example, you would select them and then initialise them.
const myNewAccordions = [].slice.call(myNewSection.querySelectorAll('[data-module="ds_accordion"]'));
myNewAccordions.forEach(accordion => new window.DS.components.Accordion(accordion).init());
sorry meant to say... we can't do that in typescript as the DS doesn't exist at design time so we would need a different solution.. couple of teams in the org haven't been able to get this to work
tried the following after looking at the GDS guidance
It loaded the JS according to the Network tab but still doesn't appear to work
@72gm I think the reason that might not work is that — because React does client-side rendering of components — you may find that the elements don't exist in the DOM at the time you're running window.DS.initAll()
.
If you're using the design system with React, the way we've implemented this at Social Security Scotland is to import the relevant script for each component, and init based on a ref
. For example, something like this:
import React, { useEffect, useRef } from 'react';
import DesignSystemTabs from '@scottish-government/design-system/src/components/tabs/tabs';
export const Tabs:ReactFC<SocialSecurityScotland.Components.Tabs> = function Tabs({
// …props
}) {
const tabsRef = useRef(null);
/*
* When component mounts, if we're in a user-space, and if the ref is set, initialise
* the component.
*
* The `tabsRef` dependency means this will only run if `tabsRef` changes.
*/
useEffect(() => {
if (tabsRef.current && typeof window !== 'undefined') {
new DesignSystemTabs(tabsRef.current).init();
}
}, [tabsRef]);
return (
<div className="ds_tabs" ref={tabsRef}>
{ /* rest of tabs code goes here */ }
</div>
);
}
export default Tabs;
@lewisdorigoSoSec yeah absolutely was... we tried a couple of ways, none satisfactory, so we just wrote our own as there wasn't much ;)
Your sample HTML for tabs is missing a few things for the desktop version e.g. js-initialised and the classes to hide content tabs
Not sure what else is missing as the tabs won't switch - can you advise and update your documentation?
It still doesn't appear to work if I copy your actual running example code (not the sample code) so there may be something wrong with the JS also? ... another team in my org had tried this and ended up just using React Bootstrap Tab component as were unable to get this to work
A bit of clarity on this would be good.
thanks