Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ const props: supportUsButtonProps = {
name: "", // ← your organization name
description: "", // ← short org description
logo: { src: "", alt: "" }, // ← Add file path to src and alt text for accessibility. Note: Accepts a string path/url.
url: "https://example.com", // ← optional: if a valid https:// URL is provided, the logo becomes clickable
projectInformation: {
name: "", // ← your project name
description: "",// ← short project description
Expand Down Expand Up @@ -334,6 +335,7 @@ Information about the organization and project.
| `name` | string | Yes | Organization name |
| `description` | string | Yes | Organization description |
| `logo` | `Image` / string | No | Organization logo |
| `url` | string | No | Organization link |
| `projectInformation` | `projectInformation` | No | Project details |

</details>
Expand Down
62 changes: 42 additions & 20 deletions src/components/SupportUsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ function getButtonClasses(buttonVariant: ButtonVariant): string {
return `${base} bg-primary hover:bg-primary/90 text-black font-black py-4 transition-all active:scale-[0.98] shadow-lg shadow-primary/20`;
}

// Helper function to validate URLs and prevent XSS through 'javascript:' protocol
function validateUrl(url?: string): string | undefined {
if (!url) return undefined;
const lowerUrl = url.toLowerCase();
if (lowerUrl.startsWith("http://") || lowerUrl.startsWith("https://")) {
return url;
}
return undefined;
}

// Main component function that renders the support us button, taking in various props for customization and rendering different sections such as hero, organization information, sponsors, and call-to-action based on the provided data and selected theme and button variant
function SupportUsButton({
Theme = "AOSSIE",
Expand All @@ -70,6 +80,21 @@ function SupportUsButton({
},
buttonVariant = "AOSSIE",
}: supportUsButtonProps): React.JSX.Element {
const validatedUrl = validateUrl(organizationInformation?.url);
const logoContent =
typeof organizationInformation.logo === "string" ? (
<span className="block h-fit w-fit p-4 bg-black text-white rounded-2xl">
<b className="text-2xl italic">{organizationInformation.logo}</b>
</span>
) : (
<img
className="w-24 h-24 bg-white/80 select-none rounded-2xl object-cover object-center"
src={organizationInformation.logo?.src}
alt={organizationInformation.logo?.alt}
title={organizationInformation.logo?.alt}
draggable={false}
/>
);
return (
// Container for the support us button, with dynamic classes based on the selected theme and custom class names
<div
Expand Down Expand Up @@ -161,25 +186,22 @@ function SupportUsButton({
)}

{/* Organization logo */}
<div>
{typeof organizationInformation.logo === "string" ? (
<span
className="block h-fit w-fit p-4 bg-black text-white rounded-2xl"
title={organizationInformation.logo}
>
<b className="text-2xl italic">
{organizationInformation.logo}
</b>
</span>
) : (
<img
className="w-24 h-24 bg-white/80 pointer-none:cursor-none select-none rounded-2xl object-cover object-center"
src={organizationInformation.logo?.src}
alt={organizationInformation.logo?.alt}
title={organizationInformation.logo?.alt}
draggable={false}
/>
)}

<div>
{organizationInformation?.logo &&
(validatedUrl ? (
<a
href={validatedUrl}
target="_blank"
rel="noopener noreferrer"
title={`Visit ${organizationInformation.name}`}
className="inline-block transition-transform duration-200 hover:scale-105 hover:shadow-lg cursor-pointer"
>
{logoContent}
</a>
) : (
logoContent
))}
</div>

{/* Organization name and description */}
Expand Down Expand Up @@ -454,4 +476,4 @@ function SupportUsButton({
);
}

export default SupportUsButton;
export default SupportUsButton;
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export type organizationInformation = {

/** Organization logo */
logo?: Image | string;

url?: string;
projectInformation?: projectInformation;
};

Expand Down
Loading