Skip to content

Commit 67b35a8

Browse files
committed
Add disabled state to CircularButton and toolkit buttons
Introduces a 'disabled' prop to CircularButton for visual and interaction changes. Updates installation and trainings pages to use a disabledMap for toggling button availability, refactors button rendering to a map, and adjusts trainings page text for clarity.
1 parent 4486c6d commit 67b35a8

File tree

3 files changed

+80
-89
lines changed

3 files changed

+80
-89
lines changed

app/installation/page.tsx

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ function InstallationContent({ section, type }: InstallationContentProps) {
138138
export default function Page() {
139139
const [activeSection, setActiveSection] = useState<Section | null>(null);
140140
const [activeInstallType, setActiveInstallType] = useState<'coder' | 'noncoder' | null>(null);
141+
// Toggle buttons by editing this map in code. Set true to disable, false to enable.
142+
const disabledMap: Record<Section, boolean> = {
143+
data4health: false,
144+
clim4health: false,
145+
land4health: false,
146+
socio4health: false,
147+
cube4health: false,
148+
};
141149

142150
const handleToolkitClick = (section: Section) => {
143151
if (section === activeSection) {
@@ -161,41 +169,27 @@ export default function Page() {
161169
</p>
162170

163171
<div className="mb-8 mt-6 flex flex-wrap justify-center gap-8">
164-
<CircularButton
165-
icon={D4H_LOGO}
166-
label="data4Health"
167-
onClick={() => handleToolkitClick('data4health')}
168-
isImage={true}
169-
isActive={activeSection === 'data4health'}
170-
/>
171-
<CircularButton
172-
icon={C4H_LOGO}
173-
label="clim4health"
174-
onClick={() => handleToolkitClick('clim4health')}
175-
isImage={true}
176-
isActive={activeSection === 'clim4health'}
177-
/>
178-
<CircularButton
179-
icon={L4H_LOGO}
180-
label="land4health"
181-
onClick={() => handleToolkitClick('land4health')}
182-
isImage={true}
183-
isActive={activeSection === 'land4health'}
184-
/>
185-
<CircularButton
186-
icon={S4H_LOGO}
187-
label="socio4health"
188-
onClick={() => handleToolkitClick('socio4health')}
189-
isImage={true}
190-
isActive={activeSection === 'socio4health'}
191-
/>
192-
<CircularButton
193-
icon={CU4H_LOGO}
194-
label="cube4health"
195-
onClick={() => handleToolkitClick('cube4health')}
196-
isImage={true}
197-
isActive={false}
198-
/>
172+
{[
173+
{ key: 'data4health', logo: D4H_LOGO, label: 'data4Health' },
174+
{ key: 'clim4health', logo: C4H_LOGO, label: 'clim4health' },
175+
{ key: 'land4health', logo: L4H_LOGO, label: 'land4health' },
176+
{ key: 'socio4health', logo: S4H_LOGO, label: 'socio4health' },
177+
{ key: 'cube4health', logo: CU4H_LOGO, label: 'cube4health' },
178+
].map((tk) => {
179+
const section = tk.key as Section;
180+
return (
181+
<div key={tk.key} className="flex flex-col items-center">
182+
<CircularButton
183+
icon={tk.logo}
184+
label={tk.label}
185+
onClick={() => handleToolkitClick(section)}
186+
isImage={true}
187+
isActive={activeSection === section}
188+
disabled={disabledMap[section]}
189+
/>
190+
</div>
191+
);
192+
})}
199193
</div>
200194

201195
{activeSection && (

app/trainings/page.tsx

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ function SubButtons({ section }: { section: Section }) {
6767

6868
return (
6969
<article className="prose mx-auto mt-8 w-full max-w-4xl">
70-
<h2 className="text-2xl font-semibold">Installation & resources</h2>
71-
<p className="text-gray-600">Embedded installation guide and related materials for <strong>{section}</strong>.</p>
7270

7371
{entry?.pdf ? (
7472
<div className="mt-6 border rounded overflow-hidden" style={{ height: 720 }}>
@@ -116,6 +114,14 @@ function SubButtons({ section }: { section: Section }) {
116114

117115
export default function Page() {
118116
const [activeSection, setActiveSection] = useState<Section | null>(null);
117+
// Toggle buttons by editing this map in code. Set true to disable, false to enable.
118+
const disabledMap: Record<Section, boolean> = {
119+
data4health: false,
120+
clim4health: true,
121+
land4health: true,
122+
socio4health: true,
123+
cube4health: true,
124+
};
119125

120126
const handleToolkitClick = (section: Section) => {
121127
if (section === activeSection) {
@@ -127,48 +133,33 @@ export default function Page() {
127133

128134
return (
129135
<div className="container mx-auto px-4">
130-
<h1 className="mb-2 mt-6 text-3xl font-semibold md:mt-0">Installation</h1>
136+
<h1 className="mb-2 mt-6 text-3xl font-semibold md:mt-0">Trainings</h1>
131137
<p className="text-justify text-l text-gray-500">
132-
Before using our toolkits, ensure you have the necessary software and packages installed.
133-
Select a toolkit below to view the installation guide and related materials.
138+
This section contains the workshop development support materials.
134139
</p>
135140

136141
<div className="mb-8 mt-6 flex flex-wrap justify-center gap-8">
137-
<CircularButton
138-
icon={D4H_LOGO}
139-
label="data4Health"
140-
onClick={() => handleToolkitClick('data4health')}
141-
isImage={true}
142-
isActive={activeSection === 'data4health'}
143-
/>
144-
<CircularButton
145-
icon={C4H_LOGO}
146-
label="clim4health"
147-
onClick={() => handleToolkitClick('clim4health')}
148-
isImage={true}
149-
isActive={activeSection === 'clim4health'}
150-
/>
151-
<CircularButton
152-
icon={L4H_LOGO}
153-
label="land4health"
154-
onClick={() => handleToolkitClick('land4health')}
155-
isImage={true}
156-
isActive={activeSection === 'land4health'}
157-
/>
158-
<CircularButton
159-
icon={S4H_LOGO}
160-
label="socio4health"
161-
onClick={() => handleToolkitClick('socio4health')}
162-
isImage={true}
163-
isActive={activeSection === 'socio4health'}
164-
/>
165-
<CircularButton
166-
icon={CU4H_LOGO}
167-
label="cube4health"
168-
onClick={() => handleToolkitClick('cube4health')}
169-
isImage={true}
170-
isActive={activeSection === 'cube4health'}
171-
/>
142+
{[
143+
{ key: 'data4health', logo: D4H_LOGO, label: 'data4Health' },
144+
{ key: 'clim4health', logo: C4H_LOGO, label: 'clim4health' },
145+
{ key: 'land4health', logo: L4H_LOGO, label: 'land4health' },
146+
{ key: 'socio4health', logo: S4H_LOGO, label: 'socio4health' },
147+
{ key: 'cube4health', logo: CU4H_LOGO, label: 'cube4health' },
148+
].map((tk) => {
149+
const section = tk.key as Section;
150+
return (
151+
<div key={tk.key} className="flex flex-col items-center">
152+
<CircularButton
153+
icon={tk.logo}
154+
label={tk.label}
155+
onClick={() => handleToolkitClick(section)}
156+
isImage={true}
157+
isActive={activeSection === section}
158+
disabled={disabledMap[section]}
159+
/>
160+
</div>
161+
);
162+
})}
172163
</div>
173164

174165
{activeSection && (

app/ui/components/circular-button.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,57 @@ export interface CircularButtonProps {
77
onClick: () => void;
88
isImage?: boolean;
99
isActive?: boolean;
10+
disabled?: boolean;
1011
size?: 'sm' | 'md';
1112
}
1213

13-
export default function CircularButton({ icon, label, onClick, isImage = false, isActive = false }: CircularButtonProps) {
14+
export default function CircularButton({ icon, label, onClick, isImage = false, isActive = false, disabled = false }: CircularButtonProps) {
1415
const Icon = icon as React.ElementType;
16+
// stronger fade when disabled and remove hover effects
17+
const containerClasses = `transform transition-all duration-300 ease-in-out rounded-full p-4 w-24 h-24 flex items-center justify-center ${
18+
disabled ? 'opacity-30 cursor-not-allowed' : 'cursor-pointer hover:scale-110 hover:shadow-lg'
19+
}`;
20+
21+
const activeBg = isActive ? 'bg-purple-100 shadow-lg scale-105 rotate-3' : (disabled ? '' : 'hover:bg-purple-50 hover:rotate-3');
22+
1523
return (
1624
<div className="flex flex-col items-center space-y-2 group">
1725
<div
1826
role="button"
19-
tabIndex={0}
20-
onClick={onClick}
27+
tabIndex={disabled ? -1 : 0}
28+
aria-disabled={disabled}
29+
onClick={() => {
30+
if (!disabled) onClick();
31+
}}
2132
onKeyDown={(e) => {
33+
if (disabled) return;
2234
if (e.key === 'Enter' || e.key === ' ') {
2335
e.preventDefault();
2436
onClick();
2537
}
2638
}}
27-
className={`cursor-pointer transform transition-all duration-300 ease-in-out hover:scale-110 hover:shadow-lg rounded-full p-4 w-24 h-24 flex items-center justify-center
28-
${isActive
29-
? 'bg-purple-100 shadow-lg scale-105 rotate-3'
30-
: 'hover:bg-purple-50 hover:rotate-3'}`}
39+
className={`${containerClasses} ${activeBg}`}
3140
>
3241
{isImage ? (
3342
<Image
3443
src={icon as string}
3544
alt={label}
3645
width={80}
3746
height={80}
38-
className={`text-current transform transition-transform duration-300
39-
${isActive ? '-rotate-3' : 'group-hover:-rotate-3'}`}
47+
className={`text-current transform transition-transform duration-300 ${disabled ? 'filter grayscale' : ''} ${isActive ? '-rotate-3' : (disabled ? '' : 'group-hover:-rotate-3')}`}
4048
/>
4149
) : (
4250
typeof icon === 'string' ? (
43-
<span className={`text-2xl transition-all duration-300 ${isActive ? 'text-purple-700' : 'text-dark-purple group-hover:text-purple-700'}`}>
51+
<span className={`text-2xl transition-all duration-300 ${isActive ? 'text-purple-700' : 'text-dark-purple'} ${disabled ? 'text-gray-400' : 'group-hover:text-purple-700'}`}>
4452
{icon}
4553
</span>
4654
) : (
47-
<Icon className={`h-12 w-12 transition-all duration-300
48-
${isActive ? 'text-purple-700' : 'text-dark-purple group-hover:text-purple-700'}`}
55+
<Icon className={`h-12 w-12 transition-all duration-300 ${isActive ? 'text-purple-700' : 'text-dark-purple'} ${disabled ? 'filter grayscale text-gray-400' : 'group-hover:text-purple-700'}`}
4956
/>
5057
)
5158
)}
5259
</div>
53-
<span className={`text-sm font-medium transition-all duration-300
54-
${isActive ? 'text-purple-700' : 'group-hover:text-purple-700'}`}>
60+
<span className={`text-sm font-medium transition-all duration-300 ${isActive ? 'text-purple-700' : (disabled ? 'text-gray-400' : 'group-hover:text-purple-700')}`}>
5561
{label}
5662
</span>
5763
</div>

0 commit comments

Comments
 (0)