Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add theme chooser for both Astro and Vite #2749

Merged
merged 4 commits into from
Dec 2, 2024
Merged
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
1 change: 1 addition & 0 deletions examples/ecommerce-jewellery-store/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
rel="stylesheet">
<link href="https://unpkg.com/@progress/[email protected]/dist/default-main.css" rel="stylesheet" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ecommerce Jewellery Store</title>

Expand Down
11 changes: 0 additions & 11 deletions examples/ecommerce-jewellery-store/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/ecommerce-jewellery-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"@progress/kendo-react-progressbars": "^9.0.0",
"@progress/kendo-react-treeview": "^9.0.0",
"@progress/kendo-svg-icons": "^4.0.0",
"@progress/kendo-theme-default": "^10.0.1",
"@progress/kendo-theme-utils": "^10.0.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
50 changes: 26 additions & 24 deletions examples/ecommerce-jewellery-store/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,42 @@ import ThankYou from "./pages/ThankYou";
import PaymentDetails from "./pages/PaymentDetails";
import { AllProductsListView } from "./pages/AllProductsListView";
import Home from "./pages/Home";
import "@progress/kendo-theme-default/dist/all.css";
import "@progress/kendo-theme-utils/dist/all.scss";
import { SizedParent } from "./components/SizedParent";
import { DetailedCategory } from "./pages/DetailedCategory";
import { ProductDetails } from "./pages/ProductsDetails";
import { CartProvider } from "./helpers/CartContext";
import { AdminProvider } from './helpers/AdminContext';
import { CategoriesProvider } from './helpers/CategoriesContext';
import { ShoppingCartList } from "./components/ShoppingCartList"; // Adjust path if necessary
import { ThemeProvider } from './helpers/ThemeContext';
import { ShoppingCartList } from "./components/ShoppingCartList";

function App() {
return (
<CartProvider>
<AdminProvider>
<CategoriesProvider>
<Router basename="/kendo-react/ecommerce-jewellery-store">
<Header />
<SizedParent>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/paymentdetails" element={<PaymentDetails />} />
<Route path="/thankyou" element={<ThankYou />} />
<Route path="/contacts" element={<Contacts />} />
<Route path="/products" element={<AllProductsListView />} />
<Route path="/category" element={<DetailedCategory />} />
<Route path="/product/:id" element={<ProductDetails />} />
<Route path="/shoppingcart" element={<ShoppingCartList />} />
</Routes>
</SizedParent>
<Footer />
</Router>
</CategoriesProvider>
</AdminProvider>
</CartProvider>
<ThemeProvider>
<CartProvider>
<AdminProvider>
<CategoriesProvider>
<Router basename="/kendo-react/ecommerce-jewellery-store">
<Header />
<SizedParent>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/paymentdetails" element={<PaymentDetails />} />
<Route path="/thankyou" element={<ThankYou />} />
<Route path="/contacts" element={<Contacts />} />
<Route path="/products" element={<AllProductsListView />} />
<Route path="/category" element={<DetailedCategory />} />
<Route path="/product/:id" element={<ProductDetails />} />
<Route path="/shoppingcart" element={<ShoppingCartList />} />
</Routes>
</SizedParent>
<Footer />
</Router>
</CategoriesProvider>
</AdminProvider>
</CartProvider>
</ThemeProvider>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import viloraLogo from '@/assets/vilora-logo.png';

const Footer: React.FC = () => {
return (
<section className="k-py-10 k-px-12 header">
<section className="k-py-10 k-px-12 footer">
<div className="k-d-flex k-flex-wrap k-justify-content-between k-gap-8 k-text-align-left">
<div className="k-flex-basis-250 k-flex-grow-1 k-mb-4 k-mt-6" style={{marginLeft: '50px'}}>
<a href="#" className="k-d-block k-mb-4 k-text-align-center">
Expand Down
55 changes: 33 additions & 22 deletions examples/ecommerce-jewellery-store/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
import React from "react";
import { useNavigate } from "react-router-dom";
import { Menu, MenuItemModel, MenuSelectEvent } from "@progress/kendo-react-layout";
import { Button } from "@progress/kendo-react-buttons";
import { Button, DropDownButton } from "@progress/kendo-react-buttons";
import { SvgIcon } from "@progress/kendo-react-common";
import { InputPrefix, InputSeparator, TextBox, Switch } from "@progress/kendo-react-inputs";
import { searchIcon, userIcon, cartIcon } from "@progress/kendo-svg-icons";
import { searchIcon, userIcon, cartIcon, paletteIcon } from "@progress/kendo-svg-icons";
import viloraLogo from "@/assets/vilora-logo.png";
import items from "../data/items";
import themeItems from "../data/themeItems";
import { AppBar, AppBarSection } from "@progress/kendo-react-layout";
import { useAdminContext } from "../helpers/AdminContext";
import { useCategoriesContext } from "../helpers/CategoriesContext";
import { useCategoriesContext } from "../helpers/CategoriesContext";
import { useThemeContext } from "../helpers/ThemeContext";

interface CustomMenuItemModel extends MenuItemModel {
page?: string;
}


const Header: React.FC = () => {
const navigate = useNavigate();
const { toggleRole } = useAdminContext();
const { setSelectedCategory } = useCategoriesContext();
const { theme, setTheme } = useThemeContext();

const handleThemeChange = (event: any) => {
const selectedTheme = themeItems.find((item) => item.themeName === event.item.themeName);
if (selectedTheme) {
setTheme(selectedTheme.link);
console.log("Theme changed to:", selectedTheme.link);
} else {
console.error("Selected theme not found:", event.item.themeName);
}
};

const handleCartClick = () => {
navigate("/shoppingcart");
};

const handleSwitchChange = () => {
toggleRole();
toggleRole();
};

const handleMenuSelect = (event: MenuSelectEvent) => {
Expand All @@ -36,25 +48,26 @@ const Header: React.FC = () => {
navigate(selectedItem.page);
return;
}

const selectedCategory = selectedItem.text;
if (selectedCategory === "All") {
setSelectedCategory(null);
setSelectedCategory(null);
} else {
setSelectedCategory(selectedCategory ?? null);
navigate("/category");
setSelectedCategory(selectedCategory ?? null);
navigate("/category");
}
};

return (
<>
<link id="theme-link" rel="stylesheet" href={theme} />
<AppBar themeColor="inherit">
<AppBarSection className="k-flex-basis-0 k-flex-grow k-gap-2 k-align-items-center" style={{ paddingLeft: "50px" }}>
<a href="#" className="k-d-sm-flex" style={{ marginRight: "50px" }}>
<a href="/" className="k-d-sm-flex" style={{ marginRight: "50px" }}>
<img src={viloraLogo} alt="Logo" />
</a>
<Menu items={items} onSelect={handleMenuSelect} />
</AppBarSection>

<AppBarSection className="k-flex-basis-0 k-flex-grow k-justify-content-end k-gap-1.5">
<TextBox
placeholder="Search"
Expand All @@ -71,21 +84,19 @@ const Header: React.FC = () => {
style={{ width: 300 }}
/>
<Button svgIcon={userIcon} fillMode="flat" className="k-ml-2" />
<Button
svgIcon={cartIcon}
<Button svgIcon={cartIcon} fillMode="flat" className="k-ml-2" onClick={handleCartClick} />
<DropDownButton
svgIcon={paletteIcon}
items={themeItems}
textField="themeName"
fillMode="flat"
className="k-ml-2"
onClick={handleCartClick}
/>
<Switch
className="switch-width"
onLabel="Admin"
offLabel="Client"
onChange={handleSwitchChange}
onItemClick={handleThemeChange}
/>
<Switch className="switch-width" onLabel="Admin" offLabel="Client" onChange={handleSwitchChange} />
</AppBarSection>
</AppBar>
</>
);
};

export default Header;
export default Header;
24 changes: 24 additions & 0 deletions examples/ecommerce-jewellery-store/src/data/themeItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const themeItems = [
{
themeName: "Main",
link: "https://unpkg.com/@progress/[email protected]/dist/default-main.css",
},
{
themeName: "Main Dark",
link: "https://unpkg.com/@progress/[email protected]/dist/default-main-dark.css",
},
{
themeName: "Ocean Blue",
link: "https://unpkg.com/@progress/[email protected]/dist/default-ocean-blue-a11y.css",
},
{
themeName: "Nordic",
link: "https://unpkg.com/@progress/[email protected]/dist/default-nordic.css",
},
{
themeName: "Purple",
link: "https://unpkg.com/@progress/[email protected]/dist/default-purple.css",
},
];

export default themeItems;
48 changes: 48 additions & 0 deletions examples/ecommerce-jewellery-store/src/helpers/ThemeContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { createContext, useContext, useState, useEffect } from "react";

interface ThemeContextProps {
theme: string;
setTheme: (theme: string) => void;
}

const ThemeContext = createContext<ThemeContextProps>({
theme: "https://unpkg.com/@progress/[email protected]/dist/default-main.css",
setTheme: () => {},
});

export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [theme, setThemeState] = useState<string>(() =>
typeof window !== "undefined"
? localStorage.getItem("theme") ||
"https://unpkg.com/@progress/[email protected]/dist/default-main.css"
: "https://unpkg.com/@progress/[email protected]/dist/default-main.css"
);

const setTheme = (newTheme: string) => {
setThemeState(newTheme);
if (typeof window !== "undefined") {
localStorage.setItem("theme", newTheme);
}
};

useEffect(() => {
const themeLink = document.getElementById("theme-link") as HTMLLinkElement;
if (themeLink) {
themeLink.href = theme;
}

document.body.classList.add("k-body");

return () => {
document.body.classList.remove("k-body");
};
}, [theme]);

return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
};

export const useThemeContext = () => useContext(ThemeContext);
Loading