Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
"@adobe/leonardo-contrast-colors": "^1.0.0",
"@cloudscape-design/components": "^3.0.706",
"@dxc-technology/halstack-react": "*",
"@emotion/cache": "^11.14.0",
Expand Down
12 changes: 6 additions & 6 deletions apps/website/screens/common/images/dxc_logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ export const dxcLogo = (
gradientTransform="matrix(402.422 -113.55 49.0928 173.987 432 120.032)"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#FFB87E" />
<stop offset="0.163458" stop-color="#FFA962" />
<stop offset="0.337937" stop-color="#FEA15F" />
<stop offset="0.557693" stop-color="#FF7E51" />
<stop offset="0.839777" stop-color="#B88A99" />
<stop offset="1" stop-color="#6399F0" />
<stop stopColor="#FFB87E" />
<stop offset="0.163458" stopColor="#FFA962" />
<stop offset="0.337937" stopColor="#FEA15F" />
<stop offset="0.557693" stopColor="#FF7E51" />
<stop offset="0.839777" stopColor="#B88A99" />
<stop offset="1" stopColor="#6399F0" />
</radialGradient>
</defs>
</svg>
Expand Down
76 changes: 58 additions & 18 deletions apps/website/screens/theme-generator/ThemeGeneratorConfigPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useState } from "react";
import { useRef, useState } from "react";
import { DxcContainer, DxcFlex, DxcWizard } from "@dxc-technology/halstack-react";
import StepHeading from "./components/StepHeading";
import BottomButtons from "./components/BottomButtons";
// import { FileData } from "../../../../packages/lib/src/file-input/types";

export type Step = 0 | 1 | 2;
import { BrandingDetails } from "./steps/BrandingDetails";
import { generateTokens, handleExport } from "./utils";
import { Colors, FileData, Step } from "./types";

const steps = [
{
Expand Down Expand Up @@ -34,29 +34,65 @@ const wizardSteps = steps.map(({ label, description }) => ({

const ThemeGeneratorConfigPage = () => {
const [currentStep, setCurrentStep] = useState<Step>(0);
// Uncomment when implementing the Branding details screen
/** const [colors, setColors] = useState({
primary: "#5f249f",
secondary: "#00b4d8",
tertiary: "#ffa500",
neutral: "#666666",
info: "#0095FF",
success: "#2FD05D",
error: "#FE0123",
warning: "#F38F20",
const [colors, setColors] = useState<Colors>({
primary: "#5F249F",
secondary: "#0067B3",
tertiary: "#F7CF2B",
neutral: "#999999",
info: "#0067B3",
success: "#59D97D",
error: "#FE344F",
warning: "#F59F3D",
});
const [logos, setLogos] = useState({
mainLogo: [] as FileData[],
footerLogo: [] as FileData[],
footerReducedLogo: [] as FileData[],
favicon: [] as FileData[],
});
*/
const [tokens, setTokens] = useState<Record<string, string>>({});
const lastGeneratedColorsRef = useRef<string>("");

const generateTokensFromColors = () => {
try {
const mappedColors = {
primary: colors.primary,
secondary: colors.secondary,
tertiary: colors.tertiary,
semantic01: colors.info,
semantic02: colors.success,
semantic03: colors.warning,
semantic04: colors.error,
neutral: colors.neutral,
};

const handleChangeStep = (step: Step) => {
const generatedTokens = generateTokens(mappedColors);

setTokens(generatedTokens);
lastGeneratedColorsRef.current = JSON.stringify(colors);
} catch (error) {
console.error("Error generating tokens:", error);
}
};

const handleChangeStep = (step: 0 | 1 | 2) => {
if (currentStep === 0 && JSON.stringify(colors) !== lastGeneratedColorsRef.current) {
generateTokensFromColors();
}
setCurrentStep(step);
};

const renderStepContent = () => {
switch (currentStep) {
case 0:
return <BrandingDetails colors={colors} onColorsChange={setColors} logos={logos} onLogosChange={setLogos} />;
case 1:
return <></>;
case 2:
return <></>;
}
};

return (
<DxcContainer
height="100%"
Expand Down Expand Up @@ -84,11 +120,15 @@ const ThemeGeneratorConfigPage = () => {
>
<DxcFlex direction="column" alignItems="center" gap="var(--spacing-gap-xl)">
<StepHeading title={steps[currentStep].title} subtitle={steps[currentStep].subtitle} />
{currentStep === 0 ? <></> : currentStep === 1 ? <></> : <></>}
{renderStepContent()}
</DxcFlex>
</DxcContainer>

<BottomButtons currentStep={currentStep} onChangeStep={handleChangeStep} />
<BottomButtons
currentStep={currentStep}
onChangeStep={handleChangeStep}
onExport={() => handleExport(tokens)}
/>
</DxcFlex>
</DxcContainer>
);
Expand Down
76 changes: 31 additions & 45 deletions apps/website/screens/theme-generator/components/BottomButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,40 @@
import { DxcButton, DxcContainer, DxcFlex } from "@dxc-technology/halstack-react";
import { Step } from "../ThemeGeneratorConfigPage";
import { Step } from "../types";

const MIN_STEP: Step = 0;
const MAX_STEP: Step = 2;

interface BottomButtonsProps {
const BottomButtons = ({
currentStep,
onChangeStep,
onExport,
}: {
currentStep: Step;
onChangeStep: (step: Step) => void;
}

const BottomButtons = ({ currentStep, onChangeStep }: BottomButtonsProps) => {
const goToStep = (step: number) => {
if (step >= MIN_STEP && step <= MAX_STEP) {
onChangeStep(step as Step);
}
};

return (
<DxcContainer
width="100%"
padding="var(--spacing-padding-s) var(--spacing-padding-l)"
background={{ color: "var(--color-bg-neutral-lightest)" }}
boxSizing="border-box"
>
<DxcFlex justifyContent="flex-end" alignItems="center" gap="var(--spacing-gap-m)">
<DxcButton
label="Back"
icon="arrow_back"
mode="tertiary"
onClick={() => goToStep(currentStep - 1)}
disabled={currentStep === 0}
size={{ height: "medium", width: "fitContent" }}
/>
{currentStep === 2 ? (
<DxcButton
label="Export theme"
//TODO: replace with actual export functionality
onClick={() => console.log("download theme")}
size={{ height: "medium", width: "fitContent" }}
/>
) : (
<DxcButton
label="Next"
onClick={() => goToStep(currentStep + 1)}
size={{ height: "medium", width: "fitContent" }}
/>
)}
</DxcFlex>
</DxcContainer>
);
};
onExport: () => void;
}) => (
<DxcContainer
width="100%"
padding="var(--spacing-padding-s) var(--spacing-padding-l)"
background={{ color: "var(--color-bg-neutral-lightest)" }}
boxSizing="border-box"
>
<DxcFlex justifyContent="flex-end" alignItems="center" gap="var(--spacing-gap-m)">
<DxcButton
label="Back"
icon="arrow_back"
mode="tertiary"
onClick={() => onChangeStep((currentStep - 1) as Step)}
disabled={currentStep === MIN_STEP}
size={{ height: "medium" }}
/>
{currentStep === MAX_STEP ? (
<DxcButton label="Export theme" onClick={onExport} size={{ height: "medium" }} />
) : (
<DxcButton label="Next" onClick={() => onChangeStep((currentStep + 1) as Step)} size={{ height: "medium" }} />
)}
</DxcFlex>
</DxcContainer>
);

export default BottomButtons;
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { DxcFlex, DxcHeading, DxcContainer, DxcTypography } from "@dxc-technology/halstack-react";

interface PageHeadingProps {
title: string;
subtitle: string;
}

const StepHeading = ({ title, subtitle }: PageHeadingProps) => (
const StepHeading = ({ title, subtitle }: { title: string; subtitle: string }) => (
<DxcContainer width="100%" maxWidth="711px">
<DxcFlex direction="column" alignItems="center" gap="var(--spacing-gap-xs)">
<DxcHeading level={3} text={title} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react";
import { ColorCard } from "./ColorCard";
import { Colors } from "../../types";
import { BrandingColorGridProps } from "./types";

const BrandingColorGrid = ({ section, colors, onColorChange }: BrandingColorGridProps) => (
<DxcFlex direction="column" alignItems="flex-start" gap="var(--spacing-gap-m)" alignSelf="stretch">
<DxcFlex alignItems="center" gap="var(--spacing-gap-xs)">
<DxcTypography
as="div"
color="var(--color-fg-primary-strong)"
fontSize="var(--typography-body-xxl)"
lineHeight="var(--height-xxs)"
>
{section.icon}
</DxcTypography>
<DxcTypography
as="h3"
fontSize="var(--typography-title-l)"
fontWeight="var(--typography-title-bold)"
lineHeight="normal"
>
{section.title}
</DxcTypography>
</DxcFlex>
<DxcGrid placeSelf="stretch" templateColumns={["repeat(4, 1fr)"]} gap="var(--spacing-gap-m)">
{section.fields.map(({ id, label, helperText }) => (
<ColorCard
key={id}
label={label}
helperText={helperText}
color={colors[id as keyof Colors]}
onChange={onColorChange(id)}
/>
))}
</DxcGrid>
</DxcFlex>
);

export default BrandingColorGrid;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DxcFileInput, DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react";
import { Logos } from "../../types";
import { BrandingLogoGridProps } from "./types";

const BrandingLogoGrid = ({ section, logos, onLogoChange }: BrandingLogoGridProps) => (
<DxcFlex direction="column" alignItems="flex-start" gap="var(--spacing-gap-m)" alignSelf="stretch">
<DxcFlex alignItems="center" gap="var(--spacing-gap-xs)">
<DxcTypography
as="div"
color="var(--color-fg-primary-strong)"
fontSize="var(--typography-body-xxl)"
lineHeight="var(--height-xxs)"
>
{section.icon}
</DxcTypography>
<DxcTypography
as="h3"
fontSize="var(--typography-title-l)"
fontWeight="var(--typography-title-bold)"
lineHeight="normal"
>
{section.title}
</DxcTypography>
</DxcFlex>
<DxcGrid templateColumns={["repeat(4, 1fr)"]} gap="var(--spacing-gap-m)" placeSelf="stretch">
{section.fields.map(({ id, label, helperText }) => (
<DxcFileInput
key={id}
size="fillParent"
label={label}
helperText={helperText}
buttonLabel="Select file"
mode="filedrop"
accept="image/*"
showPreview
multiple={false}
callbackFile={(files) => onLogoChange(id, files)}
value={logos[id as keyof Logos]}
/>
))}
</DxcGrid>
</DxcFlex>
);

export default BrandingLogoGrid;
Loading