PluginProbe
Extendify / 3.0.6
Extendify v3.0.6
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Launch / pages / SiteStructure.jsx

SiteStructure.jsx in Extendify 3.0.6, at src/Launch/pages/SiteStructure.jsx

118 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Title } from '@launch/components/Title';
2 import { PageLayout } from '@launch/layouts/PageLayout';
3 import { pageState } from '@launch/state/factory';
4 import { useUserSelectionStore } from '@launch/state/user-selections';
5 import {
6 useEffect,
7 useLayoutEffect,
8 useMemo,
9 useState,
10 } from '@wordpress/element';
11 import { __, isRTL } from '@wordpress/i18n';
12 import { arrowLeft, arrowRight, Icon } from '@wordpress/icons';
13 import classNames from 'classnames';
14
15 export const state = pageState('Site Template Type', () => ({
16 ready: false,
17 canSkip: false,
18 useNav: true,
19 onRemove: () => {},
20 }));
21
22 export const SiteStructure = () => {
23 const { siteStructure, setSiteStructure } = useUserSelectionStore();
24 const [firstButton, setFirstButton] = useState(siteStructure);
25
26 useLayoutEffect(() => {
27 if (firstButton || siteStructure) return;
28 // Randomize the order of the buttons
29 const random = ['single-page', 'multi-page'].sort(
30 () => Math.random() - 0.5,
31 );
32 setFirstButton(random[0]);
33 setSiteStructure(random[0]);
34 }, [setSiteStructure, firstButton, siteStructure]);
35
36 useEffect(() => {
37 state.setState({ ready: !!siteStructure && firstButton });
38 }, [siteStructure, firstButton]);
39
40 const buttons = useMemo(
41 () => [
42 <ButtonSelect
43 key="single-page"
44 onClick={() => setSiteStructure('single-page')}
45 selected={siteStructure === 'single-page'}
46 imageSrc="https://images.extendify-cdn.com/launch/single-page-website.webp"
47 title={__('Single-Page Website', 'extendify-local')}
48 description={__(
49 'All content displayed on one scrolling page.',
50 'extendify-local',
51 )}
52 />,
53 <ButtonSelect
54 key="multi-page"
55 onClick={() => setSiteStructure('multi-page')}
56 selected={siteStructure === 'multi-page'}
57 imageSrc="https://images.extendify-cdn.com/launch/multi-page-website.webp"
58 title={__('Multi-Page Website', 'extendify-local')}
59 description={__('Multiple interconnected pages.', 'extendify-local')}
60 />,
61 ],
62 [siteStructure, setSiteStructure],
63 );
64 const buttonsOrdered =
65 firstButton === 'multi-page' ? buttons.toReversed() : buttons;
66
67 return (
68 <PageLayout>
69 <div className="grow overflow-y-auto px-6 py-8 md:p-12 3xl:p-16">
70 <Title title={__('Pick Your Site Structure', 'extendify-local')} />
71 <div className="relative mx-auto flex w-full max-w-2xl flex-col gap-8 lg:flex-row 3xl:max-w-4xl">
72 {buttonsOrdered}
73 </div>
74 </div>
75 </PageLayout>
76 );
77 };
78
79 const ButtonSelect = ({ title, description, onClick, selected, imageSrc }) => (
80 // biome-ignore lint: keep the button role until a refactor is done
81 <div
82 data-test="site-template-type"
83 className={classNames(
84 'relative flex-1 cursor-pointer overflow-hidden rounded-sm border border-gray-200 ring-offset-2 ring-offset-white focus-within:outline-hidden focus-within:ring-4 focus-within:ring-design-main focus-within:ring-offset-2 focus-within:ring-offset-white hover:outline-hidden hover:ring-4',
85 {
86 'ring-4 ring-design-main ring-offset-2 ring-offset-white hover:ring-design-main':
87 selected,
88 'hover:ring-gray-300': !selected,
89 },
90 )}
91 role="radio"
92 tabIndex={0}
93 aria-label={__('Press to select', 'extendify-local')}
94 aria-checked={selected}
95 onKeyDown={(e) => {
96 if (!['Enter', 'Space', ' '].includes(e.key)) return;
97 e.preventDefault();
98 onClick();
99 }}
100 onClick={onClick}
101 >
102 <div className="relative aspect-[4/3] w-full overflow-hidden bg-gray-100 group-hover:opacity-75 lg:flex">
103 <img
104 alt=""
105 src={imageSrc}
106 className="absolute inset-0 h-full w-full object-cover"
107 />
108 </div>
109 <div className="p-4 lg:p-6">
110 <p className="m-0 mb-3 p-0 text-gray-700 3xl:mb-4">{description}</p>
111 <div className="flex items-center justify-between">
112 <h1 className="m-0 p-0 text-lg font-semibold">{title}</h1>
113 <Icon icon={isRTL() ? arrowLeft : arrowRight} />
114 </div>
115 </div>
116 </div>
117 );
118