From 69dc6bf68d653d1796ac8e889331ebd53c19a7de Mon Sep 17 00:00:00 2001 From: Keith Stevens Date: Mon, 9 Jan 2023 09:44:01 +0900 Subject: [PATCH] Adding a bare bones feature flag setup --- website/README.md | 28 ++++++++++++++++++++++++ website/package-lock.json | 17 ++++++++++++++ website/package.json | 1 + website/src/components/Header/Header.tsx | 4 ++++ website/src/flags.ts | 3 +++ website/src/pages/_app.tsx | 10 ++++++--- 6 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 website/src/flags.ts diff --git a/website/README.md b/website/README.md index 11e3ccc4..37f6991b 100644 --- a/website/README.md +++ b/website/README.md @@ -153,6 +153,34 @@ When writing code for the website, we have a few best practices: 1. Define functional React components (with types for all properties when feasible). +### Developing New Features + +When working on new features or making significant changes that can't be done +within a single Pull Request, we ask that you make use of Feature Flags. + +We've set up +[`react-feature-flags`](https://www.npmjs.com/package/react-feature-flags) to +make this easier. To get started: + +1. Add a new flag entry to `website/src/flags.ts`. We have an example flag you + can copy as an example. Be sure to `isActive` to true when testing your + features but false when submitting your PR. +1. Use your flag wherever you add a new UI element. This can be done with: + +```js +import { Flags } from "react-feature-flags"; +... + + + +``` + + You can see an example of how this works by checking `website/src/components/Header/Headers.tsx` where we use `flagTest`. + +1. Once you've finished building out the feature and it is ready for everyone + to use, it's safe to remove the `Flag` wrappers around your component and + the entry in `flags.ts`. + ### URL Paths To use stable and consistent URL paths, we recommend the following strategy for diff --git a/website/package-lock.json b/website/package-lock.json index ef867a98..81a9cd5d 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -39,6 +39,7 @@ "postcss-focus-visible": "^7.1.0", "react": "18.2.0", "react-dom": "18.2.0", + "react-feature-flags": "^1.0.0", "react-icons": "^4.7.1", "swr": "^2.0.0", "tailwindcss": "^3.2.4", @@ -26424,6 +26425,16 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "node_modules/react-feature-flags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-feature-flags/-/react-feature-flags-1.0.0.tgz", + "integrity": "sha512-KBFUkXjF7ifGWEQr2Ida4LdAtKGDOwFdTRlXipWxGP9a43vUBxP6IscpYQofGjlzlBcgmFKuzubcVheB6NliEg==", + "peerDependencies": { + "prop-types": "^15.5.4", + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-focus-lock": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.2.tgz", @@ -50838,6 +50849,12 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "react-feature-flags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-feature-flags/-/react-feature-flags-1.0.0.tgz", + "integrity": "sha512-KBFUkXjF7ifGWEQr2Ida4LdAtKGDOwFdTRlXipWxGP9a43vUBxP6IscpYQofGjlzlBcgmFKuzubcVheB6NliEg==", + "requires": {} + }, "react-focus-lock": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.2.tgz", diff --git a/website/package.json b/website/package.json index d00a3f4d..032125dd 100644 --- a/website/package.json +++ b/website/package.json @@ -53,6 +53,7 @@ "postcss-focus-visible": "^7.1.0", "react": "18.2.0", "react-dom": "18.2.0", + "react-feature-flags": "^1.0.0", "react-icons": "^4.7.1", "swr": "^2.0.0", "tailwindcss": "^3.2.4", diff --git a/website/src/components/Header/Header.tsx b/website/src/components/Header/Header.tsx index 4ea453c6..d0dc8a06 100644 --- a/website/src/components/Header/Header.tsx +++ b/website/src/components/Header/Header.tsx @@ -2,6 +2,7 @@ import { Box, Button, Text, useColorMode } from "@chakra-ui/react"; import Image from "next/image"; import Link from "next/link"; import { useSession } from "next-auth/react"; +import { Flags } from "react-feature-flags"; import { FaUser } from "react-icons/fa"; import { UserMenu } from "./UserMenu"; @@ -42,6 +43,9 @@ export function Header(props) {
+ +
FlagTest
+
diff --git a/website/src/flags.ts b/website/src/flags.ts new file mode 100644 index 00000000..2e59ec1a --- /dev/null +++ b/website/src/flags.ts @@ -0,0 +1,3 @@ +const flags = [{ name: "flagTest", isActive: false }]; + +export default flags; diff --git a/website/src/pages/_app.tsx b/website/src/pages/_app.tsx index ab7655cd..69d212e8 100644 --- a/website/src/pages/_app.tsx +++ b/website/src/pages/_app.tsx @@ -3,7 +3,9 @@ import "focus-visible"; import type { AppProps } from "next/app"; import { SessionProvider } from "next-auth/react"; +import { FlagsProvider } from "react-feature-flags"; import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout"; +import flags from "src/flags"; import { Chakra, getServerSideProps } from "../styles/Chakra"; @@ -16,9 +18,11 @@ function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: App const page = getLayout(); return ( - - {page} - + + + {page} + + ); } export { getServerSideProps };