Skip to content

Instantly share code, notes, and snippets.

@koistya
Created January 9, 2022 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koistya/54320473a36e1bdc30a20e164804a914 to your computer and use it in GitHub Desktop.
Save koistya/54320473a36e1bdc30a20e164804a914 to your computer and use it in GitHub Desktop.
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
import * as React from "react";
import { TextField, Autocomplete } from "@mui/material";
import type { AutocompleteProps } from "@mui/material";
import { projects } from "./data";
type Option = { id: string; label: string };
type ComboboxProps = Omit<
AutocompleteProps<Option, undefined, undefined, undefined, undefined>,
"renderInput" | "options"
>;
/**
* TODO: Build a combobox based on Material UI Autocomplete component.
*
* @see https://mui.com/components/autocomplete/
*/
function Combobox(props: ComboboxProps): JSX.Element {
const { sx, ...other } = props;
const renderInput = React.useCallback(
(props) => <TextField placeholder="Select a project..." {...props} />,
[]
);
return (
<Autocomplete
sx={{ /* CSS */ ...sx }}
options={projects}
renderInput={renderInput}
{...other}
/>
);
}
export { Combobox };
export type { ComboboxProps };
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
const projects = [
{
id: "1",
label: "google.com",
},
{
id: "2",
label: "facebook.com",
},
{
id: "3",
label: "github.com",
},
{
id: "4",
label: "apple.com",
},
{
id: "5",
label: "amazon.com",
},
{
id: "6",
label: "youtube.com",
},
{
id: "7",
label: "wikipedia.org",
},
{
id: "8",
label: "reddit.com",
},
{
id: "9",
label: "bing.com",
},
{
id: "10",
label: "ebay.com",
},
{
id: "11",
label: "twitter.com",
},
{
id: "12",
label: "instagram.com",
},
];
export { projects };
<div id="root"></div>
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Typography, CssBaseline, Container } from "@mui/material";
import { Combobox } from "./combobox";
import { AppToolbar } from "./toolbar";
import { ThemeProvider } from "./theme";
/**
* The top-level (root) React component.
*
* @see https://reactjs.org/
* @see https://mui.com/core/
*/
function App(): JSX.Element {
return (
<ThemeProvider>
<CssBaseline />
<AppToolbar />
<Container sx={{ my: 4 }}>
<Typography sx={{ mb: 2 }} variant="body2">
Material UI Autocomplete playground 😁 See{" "}
<b>
<code>./src/combobox.tsx</code>
</b>
</Typography>
<Combobox />
</Container>
</ThemeProvider>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
{
"name": "app",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "webpack serve"
},
"dependencies": {
"@babel/core": "^7.16.7",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.16.7",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.7",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"babel-loader": "^8.2.3",
"html-webpack-plugin": "^5.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"typescript": "^4.5.4",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.2"
},
"prettier": {
"singleQuote": false
}
}
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
import * as React from "react";
import {
PaletteMode,
ThemeProvider as MuiThemeProvider,
useTheme as useMuiTheme,
} from "@mui/material";
import type { Theme } from "@mui/material";
import { createTheme as createMuiTheme } from "@mui/material/styles";
type ThemeProviderProps = { children: React.ReactNode };
const ToggleThemeContext = React.createContext(() => {});
/**
* Creates a customized version of Material UI theme.
*
* @see https://mui.com/customization/theming/
* @see https://mui.com/customization/default-theme/
*/
function createTheme(mode: PaletteMode): Theme {
return createMuiTheme({
palette: {
mode,
background: {
default: mode === "light" ? "rgba(242,246,252,1)" : "#121212",
},
},
});
}
function ThemeProvider(props: ThemeProviderProps): JSX.Element {
const [theme, setTheme] = React.useState(() => createTheme("light"));
const changeTheme = React.useCallback(() => {
setTheme(createTheme(theme.palette.mode === "light" ? "dark" : "light"));
}, [theme.palette.mode]);
return (
<MuiThemeProvider theme={theme}>
<ToggleThemeContext.Provider value={changeTheme}>
{props.children}
</ToggleThemeContext.Provider>
</MuiThemeProvider>
);
}
function useTheme(): [Theme, () => void] {
return [useMuiTheme(), React.useContext(ToggleThemeContext)];
}
export { ThemeProvider, useTheme };
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
import * as React from "react";
import { Typography, Toolbar, AppBar, IconButton } from "@mui/material";
import { LightMode, DarkMode } from "@mui/icons-material";
import type { ToolbarProps } from "@mui/material";
import { useTheme } from "./theme";
type AppToolbarProps = Omit<ToolbarProps, "children">;
/**
* Application toolbar.
*
* @see https://mui.com/components/app-bar/
*/
function AppToolbar(props: AppToolbarProps): JSX.Element {
const [theme, toggleTheme] = useTheme();
return (
<React.Fragment>
<AppBar {...props}>
<Toolbar>
<Typography sx={{ fontSize: "1.5rem", flexGrow: 1 }} variant="h3">
Material UI Playground
</Typography>
<IconButton color="inherit" onClick={toggleTheme}>
{theme.palette.mode === "light" ? <DarkMode /> : <LightMode />}
</IconButton>
</Toolbar>
</AppBar>
<Toolbar />
</React.Fragment>
);
}
export { AppToolbar };
export type { AppToolbarProps };
{
"compilerOptions": {
"target": "ESnext",
"module": "ESNext",
"jsx": "preserve",
"allowJs": true,
"noImplicitAny": true,
"noEmit": true,
"moduleResolution": "node",
"sourceMap": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
/* SPDX-FileCopyrightText: 2021-present Konstantin Tarkus (hello@endtest.dev) */
/* SPDX-License-Identifier: MIT */
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index",
mode: "development",
output: {
publicPath: "auto",
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: [
[
"@babel/preset-react",
{
jsx: "react-jsx",
jsxImportSource: "@emotion/react",
},
],
"@babel/preset-typescript",
],
plugins: ["@emotion"],
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
],
devServer: {
port: 3000,
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment