diff --git a/.gitignore b/.gitignore index a3dba856e3..4d562a4b41 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,10 @@ lib-cov # Coverage directory used by tools like istanbul coverage +# gatsby files +.cache/ +public + # nyc test coverage .nyc_output diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..466ea86eae --- /dev/null +++ b/docs/README.md @@ -0,0 +1,106 @@ +# Fluent Website Content + +__Key Concepts:__ +1. [Folder path === URL](#adding-new-content) +2. [Left hand navigation defined per folder/folder tree](#creating-navigation) +3. [Built with MD, MDX or TSX](#supported-page-formats) +4. [Host your content anywhere](#hosting-your-content) + +## Adding new content + +Files in the `docs` folders are built to a page with the same URL as the relative directory. `index` files will be rendered as the folder's root page. + +`docs/components/button.mdx` will be built to `example.com/components/button.html`. `docs/styles/index.tsx` will be built to `example.com/styles/index.html` + + +## Creating navigation + +The vertical navigation of each page is written in a `toc.yml` file that includes `name`, `link` and any children `items`. + +- `name` is the link text +- `link` is the full url to the page +- `items` is an array of name/link pairs and can be further nested + + +```yml +- name: Components + items: + - name: Button + link: components/button + - name: Toggle + link: components/toggle + +``` + +### Unique navigation for sub controls + +Often you'll want a subsection of the site to have its own navigation. The navigation of each page is based off of the closest `toc.yml` file to the page. + +```md +docs/ + styles.mdx + toc.yml + components/ + button.mdx + toc.yml + foo/ + bar.mdx + +``` + +The `styles` page will have the navigation from `docs/toc.yml` and `button` page will use the navigation found in `docs/components/toc.yml`. + +`docs/foo` does not contain a `toc.yml` so `docs/toc.yml` will be used for `bar.mdx`. + +## Supported page formats + +The Fluid UI Site supports multiple page formats. + +### MDX + +[MDX](https://mdxjs.com/) is a superset of markdown that adds the power of JSX to the file. +This means you can import JSX directly into your markdown content. + +#### Importing JSX into MDX + +```md +import {Button} from 'office-ui-fabric-react' + +## This is a Fabric button + + + +``` + +#### Importing MD into MDX + +Another great feature of MDX is the ability to import other MD or MDX files into a single file. +This is a great way to split content out into multiple files and combine/reuse it. + +```md +import Stuff from './somestuff.md' + +Hello, this is my +``` + +### TSX Files + +TSX files can be used when you need complete control over the page contents. No assumptions will be made about the page contents, styles or meta information (other than URL). + + +#### Leveraging site templates + +Unless your page is meant to be a standalone app, we recommend using the built in `PageTemplate` to render the default page shell. + +```tsx +import React from 'react'; +import PageTemplate from 'gatsby-theme-fluent-site/src/templates/PageTemplate' +import + +export default () => { + return Page Content +} +``` +## Hosting your content + +Gatsby can source pages from multiple locations. Content added to this repo under `docs/ios` could easily be moved to another repo under `fluentui-docs/ios` and produce the exact same page content. This workflow is not yet fully implemented, but it is a core tenent and fully supported by our tech choices. diff --git a/docs/content/toc.yml b/docs/content/toc.yml new file mode 100644 index 0000000000..666ea26121 --- /dev/null +++ b/docs/content/toc.yml @@ -0,0 +1,2 @@ +- name: Windows + link: /windows diff --git a/docs/pages/Components/Button.mdx b/docs/content/windows/components/button.mdx similarity index 100% rename from docs/pages/Components/Button.mdx rename to docs/content/windows/components/button.mdx diff --git a/docs/content/windows/components/index.mdx b/docs/content/windows/components/index.mdx new file mode 100644 index 0000000000..a93e0f59dc --- /dev/null +++ b/docs/content/windows/components/index.mdx @@ -0,0 +1,4 @@ +--- +title: Components +--- + diff --git a/docs/pages/Components/Link.mdx b/docs/content/windows/components/link.mdx similarity index 100% rename from docs/pages/Components/Link.mdx rename to docs/content/windows/components/link.mdx diff --git a/docs/pages/Components/RadioGroup.mdx b/docs/content/windows/components/radiogroup.mdx similarity index 100% rename from docs/pages/Components/RadioGroup.mdx rename to docs/content/windows/components/radiogroup.mdx diff --git a/docs/pages/Components/Separator.mdx b/docs/content/windows/components/separator.mdx similarity index 100% rename from docs/pages/Components/Separator.mdx rename to docs/content/windows/components/separator.mdx diff --git a/docs/pages/Components/Text.mdx b/docs/content/windows/components/text.mdx similarity index 100% rename from docs/pages/Components/Text.mdx rename to docs/content/windows/components/text.mdx diff --git a/docs/content/windows/components/toc.yml b/docs/content/windows/components/toc.yml new file mode 100644 index 0000000000..04fb6346b5 --- /dev/null +++ b/docs/content/windows/components/toc.yml @@ -0,0 +1,20 @@ +- name: Components + items: + - name: Button + link: windows/components/button + - name: Link + link: windows/components/link + - name: RadioGroup + link: windows/components/radiogroup + - name: Separator + link: windows/components/separator + - name: Text + link: windows/components/text +- name: Utilities + items: + - name: FocusTrapZone + link: windows/components/utilities/focustrapzone + - name: Pressable + link: windows/components/utilities/pressable + - name: Stack + link: windows/components/utilities/stack diff --git a/docs/pages/Utilities/FocusTrapZone.mdx b/docs/content/windows/components/utilities/focustrapzone.mdx similarity index 100% rename from docs/pages/Utilities/FocusTrapZone.mdx rename to docs/content/windows/components/utilities/focustrapzone.mdx diff --git a/docs/pages/Utilities/Pressable.mdx b/docs/content/windows/components/utilities/pressable.mdx similarity index 100% rename from docs/pages/Utilities/Pressable.mdx rename to docs/content/windows/components/utilities/pressable.mdx diff --git a/docs/pages/Utilities/Stack.mdx b/docs/content/windows/components/utilities/stack.mdx similarity index 100% rename from docs/pages/Utilities/Stack.mdx rename to docs/content/windows/components/utilities/stack.mdx diff --git a/docs/pages/counter.jsx b/docs/content/windows/counter.jsx similarity index 100% rename from docs/pages/counter.jsx rename to docs/content/windows/counter.jsx diff --git a/docs/content/windows/experiences/index.mdx b/docs/content/windows/experiences/index.mdx new file mode 100644 index 0000000000..7cc411d4c4 --- /dev/null +++ b/docs/content/windows/experiences/index.mdx @@ -0,0 +1,3 @@ +--- +title: Experiences +--- diff --git a/docs/content/windows/experiences/toc.yml b/docs/content/windows/experiences/toc.yml new file mode 100644 index 0000000000..736364a649 --- /dev/null +++ b/docs/content/windows/experiences/toc.yml @@ -0,0 +1,2 @@ +- name: Example + link: windows diff --git a/docs/content/windows/get-started/index.mdx b/docs/content/windows/get-started/index.mdx new file mode 100644 index 0000000000..46c855f0d1 --- /dev/null +++ b/docs/content/windows/get-started/index.mdx @@ -0,0 +1,5 @@ +--- +title: Get started +--- + +# diff --git a/docs/content/windows/get-started/toc.yml b/docs/content/windows/get-started/toc.yml new file mode 100644 index 0000000000..736364a649 --- /dev/null +++ b/docs/content/windows/get-started/toc.yml @@ -0,0 +1,2 @@ +- name: Example + link: windows diff --git a/docs/pages/index.mdx b/docs/content/windows/index.mdx similarity index 62% rename from docs/pages/index.mdx rename to docs/content/windows/index.mdx index 33c070f1a9..21cff006e3 100644 --- a/docs/pages/index.mdx +++ b/docs/content/windows/index.mdx @@ -15,16 +15,16 @@ You can import React components in an `.mdx` file. Like this: ## Components -- [Button](/Components/Button) -- [Link](/Components/Link) -- [Separator](/Components/Separator) -- [Text](/Components/Text) +- [Button](/windows/components/button) +- [Link](/windows/components/link) +- [Separator](/windows/components/separator) +- [Text](/windows/components/text) ## Utilities -- [FocusTrapZone](/Utilities/FocusTrapZone) -- [Pressable](/Utilities/Pressable) -- [Stack](/Utilities/Stack) +- [FocusTrapZone](/windows/components/utilities/focustrapzone) +- [Pressable](/windows/components/utilities/pressable) +- [Stack](/windows/components/utilities/stack) ## Contributing Docs diff --git a/docs/content/windows/styles/index.mdx b/docs/content/windows/styles/index.mdx new file mode 100644 index 0000000000..e61c6f46fb --- /dev/null +++ b/docs/content/windows/styles/index.mdx @@ -0,0 +1,5 @@ +--- +title: Styles +--- + +styles diff --git a/docs/content/windows/styles/toc.yml b/docs/content/windows/styles/toc.yml new file mode 100644 index 0000000000..736364a649 --- /dev/null +++ b/docs/content/windows/styles/toc.yml @@ -0,0 +1,2 @@ +- name: Example + link: windows diff --git a/docs/gatsby-config.js b/docs/gatsby-config.js new file mode 100644 index 0000000000..52670119aa --- /dev/null +++ b/docs/gatsby-config.js @@ -0,0 +1,16 @@ +module.exports = { + siteMetadata: { + siteURL: 'https://fluentui.z5.web.core.windows.net/', + }, + plugins: [ + `gatsby-plugin-typescript`, + `gatsby-plugin-sharp`, + 'gatsby-transformer-sharp', + { + resolve: `gatsby-theme-fluent-site`, + options: { + contentPath: `./content`, + }, + }, + ], +}; diff --git a/docs/next.config.js b/docs/next.config.js deleted file mode 100644 index 5a510190b3..0000000000 --- a/docs/next.config.js +++ /dev/null @@ -1,8 +0,0 @@ -const withMDX = require('@next/mdx')({ - extension: /\.mdx?$/ -}); - -module.exports = withMDX({ - pageExtensions: ['js', 'jsx', 'md', 'mdx'] -}); - diff --git a/docs/package.json b/docs/package.json index 8627f0cd92..b1dd005a34 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,16 +1,30 @@ { - "name": "fluentui-docs", - "version": "0.1.0", - "private": true, + "name": "fluent-website", + "version": "0.0.1", + "description": "Fluent website content", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/fluent-site" + }, + "license": "MIT", "scripts": { - "dev": "next", - "start": "next start", - "build": "next build && echo" + "clean": "gatsby clean", + "build": "gatsby build --prefix-paths", + "develop": "gatsby clean && gatsby develop --port 3000", + "serve": "gatsby serve", + "start": "npm run develop" + }, + "devDependencies": { + "gatsby-theme-fluent-site": "^0.1.1", + "gatsby-plugin-sharp": "^2.3.13", + "gatsby-transformer-sharp": "^2.3.12" }, "dependencies": { - "@mdx-js/loader": "^1.5.5", - "@mdx-js/mdx": "^1.5.5", - "@next/mdx": "^9.2.1", - "next": "^9.2.1" + "gatsby-plugin-typescript": "^2.1.26", + "typescript": "^3.5.1", + "gatsby": "^2.19.27", + "gatsby-plugin-emotion": "^4.1.23", + "react": "^16.13.0", + "react-dom": "^16.13.0" } } diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000000..de458acd8c --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["./src/**/*"], + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "lib": ["dom", "es2017"], + // "allowJs": true, + // "checkJs": true, + "jsx": "react", + "strict": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "noEmit": true, + "skipLibCheck": true, + "noImplicitAny": false + } +} diff --git a/packages/docs/gatsby-plugin-docs-creator/.gitignore b/packages/docs/gatsby-plugin-docs-creator/.gitignore new file mode 100644 index 0000000000..42b87d897a --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules + +decls +dist diff --git a/packages/docs/gatsby-plugin-docs-creator/.npmignore b/packages/docs/gatsby-plugin-docs-creator/.npmignore new file mode 100644 index 0000000000..e771d2c9fa --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/.npmignore @@ -0,0 +1,34 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules +*.un~ +yarn.lock +src +flow-typed +coverage +decls +examples diff --git a/packages/docs/gatsby-plugin-docs-creator/README.md b/packages/docs/gatsby-plugin-docs-creator/README.md new file mode 100644 index 0000000000..610374de88 --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/README.md @@ -0,0 +1,104 @@ +# gatsby-plugin-docs-creator + +Gatsby plugin that automatically creates pages from React components in specified directories. Gatsby +includes this plugin automatically in all sites for creating pages from components in `src/pages`. + +You may include another instance of this plugin if you'd like to create additional "pages" directories. + +With this plugin, _any_ file that lives in the specified pages folder (e.g. the default `src/pages`) or subfolders will be expected to export a React Component to generate a Page. The following files are automatically excluded: + +- `template-*` +- `__tests__/*` +- `*.test.jsx?` +- `*.spec.jsx?` +- `*.d.tsx?` +- `*.json` +- `*.yaml` +- `_*` +- `.*` + +To exclude custom patterns, see [Ignoring Specific Files](#ignoring-specific-files) + +## Install + +`npm install --save gatsby-plugin-docs-creator` + +## How to use + +```javascript +// gatsby-config.js + +module.exports = { + plugins: [ + // You can have multiple instances of this plugin + // to create pages from React components in different directories. + // + // The following sets up the pattern of having multiple + // "pages" directories in your project + { + resolve: `gatsby-plugin-docs-creator`, + options: { + path: `${__dirname}/src/account/pages`, + }, + }, + { + resolve: `gatsby-plugin-docs-creator`, + options: { + path: `${__dirname}/src/settings/pages`, + }, + }, + ], +} +``` + +### Ignoring Specific Files + +#### Shorthand + +```javascript +// The following example will disable the `/blog` index page + +// gatsby-config.js +module.exports = { + plugins: [ + { + resolve: `gatsby-plugin-docs-creator`, + options: { + path: `${__dirname}/src/indexes/pages`, + ignore: [`blog.(js|ts)?(x)`], + // See pattern syntax recognized by micromatch + // https://www.npmjs.com/package/micromatch#matching-features + }, + }, + ], +} +``` + +**NOTE**: The above code snippet will only stop the creation of the `/blog` page, which is defined as a React component. +This plugin does not affect programmatically generated pages from the [createPagesAPI](https://www.gatsbyjs.org/docs/node-apis/#createPages). + +#### Ignore Options + +```javascript +// The following example will ignore pages using case-insensitive matching + +// gatsby-config.js +module.exports = { + plugins: [ + { + resolve: `gatsby-plugin-docs-creator`, + options: { + path: `${__dirname}/src/examples/pages`, + ignore: { + // Example: Ignore `file.example.js`, `dir/s/file.example.tsx` + patterns: [`**/*.example.(js|ts)?(x)`], + // Example: Match both `file.example.js` and `file.EXAMPLE.js` + options: { nocase: true }, + // See all available micromatch options + // https://www.npmjs.com/package/micromatch#optionsnocase + }, + }, + }, + ], +} +``` diff --git a/packages/docs/gatsby-plugin-docs-creator/gatsby-node.js b/packages/docs/gatsby-plugin-docs-creator/gatsby-node.js new file mode 100644 index 0000000000..42ac6f9c4a --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/gatsby-node.js @@ -0,0 +1 @@ +module.exports = require('./dist/gatsby-node') diff --git a/packages/docs/gatsby-plugin-docs-creator/package.json b/packages/docs/gatsby-plugin-docs-creator/package.json new file mode 100644 index 0000000000..73b08e5d1f --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/package.json @@ -0,0 +1,50 @@ +{ + "name": "gatsby-plugin-docs-creator", + "version": "2.1.40", + "description": "Gatsby plugin that automatically creates pages from React components in specified directories with additional docs related data", + "main": "dist/gatsby-node.js", + "scripts": { + "build": "tsc", + "start": "yarn watch", + "watch": "tsc -w --preserveWatchOutput", + "prepare": "cross-env NODE_ENV=production npm run build" + }, + "keywords": [ + "gatsby", + "gatsby-plugin" + ], + "author": "Micah Godbolt ", + "contributors": [ + "Steven Natera (https://twitter.com/stevennatera)", + "Kyle Mathews " + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/fluent-site.git", + "directory": "packages/gatsby-plugin-docs-creator" + }, + "dependencies": { + "@types/bluebird": "^3.5.29", + "@types/js-yaml": "^3.12.2", + "@types/lodash": "^4.14.149", + "@types/node": "^13.7.4", + "bluebird": "^3.7.2", + "fs-exists-cached": "^1.0.0", + "gatsby-page-utils": "^0.0.39", + "glob": "^7.1.6", + "js-yaml": "^3.13.1", + "lodash": "^4.17.15", + "micromatch": "^3.1.10" + }, + "devDependencies": { + "cross-env": "^5.2.1", + "tslib": "^1.10.0" + }, + "peerDependencies": { + "gatsby": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } +} diff --git a/packages/docs/gatsby-plugin-docs-creator/src/gatsby-node.ts b/packages/docs/gatsby-plugin-docs-creator/src/gatsby-node.ts new file mode 100644 index 0000000000..b0087c34bf --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/src/gatsby-node.ts @@ -0,0 +1,136 @@ +import _ from 'lodash'; +import yaml from 'js-yaml'; +import { createPath, validatePath, ignorePath, watchDirectory } from 'gatsby-page-utils'; + +const BBPromise = require('bluebird'); +const existsSync = require(`fs-exists-cached`).sync; +const systemPath = require(`path`); +const { readFileSync } = require(`fs`); +const globCB = require(`glob`); +const glob = BBPromise.promisify(globCB); + +// Path creator. +// Auto-create pages. +// algorithm is glob /pages directory for js/jsx/cjsx files *not* +// underscored. Then create url w/ our path algorithm *unless* user +// takes control of that page component in gatsby-node. +export const createPagesStatefully = async ({ store, actions, reporter }, { path: pagesPath, pathCheck = true, ignore }, doneCb) => { + const { createPage, deletePage } = actions; + const program = store.getState().program; + const exts = program.extensions.map(e => `${e.slice(1)}`).join(`,`); + + if (!pagesPath) { + reporter.panic( + ` + "path" is a required option for gatsby-plugin-page-creator + + See docs here - https://www.gatsbyjs.org/plugins/gatsby-plugin-page-creator/ + ` + ); + } + + // Validate that the path exists. + if (pathCheck && !existsSync(pagesPath)) { + reporter.panic( + ` + The path passed to gatsby-plugin-page-creator does not exist on your file system: + + ${pagesPath} + + Please pick a path to an existing directory. + ` + ); + } + + const findNearestFile = (matchPath: string, filePaths: string[]): string | undefined => { + if (filePaths === undefined) { + return undefined; + } + const matchParts = matchPath.split('/'); + do { + const match = filePaths.find(filePath => { + const fileRelPath = systemPath.dirname(filePath); + const matchRelPath = systemPath.dirname(matchParts.join('/')); + return fileRelPath === matchRelPath; + }); + if (match !== undefined) { + return match; + } else matchParts.splice(-1, 1); + } while (matchParts.length > 0); + + return undefined; + }; + + const pagesDirectory = systemPath.resolve(process.cwd(), pagesPath); + const pagesGlob = `**/*.{${exts}}`; + const tocGlob = '**/toc.yml'; + + // Get initial list of files. + let files = await glob(pagesGlob, { cwd: pagesPath }); + const tocs = await glob(tocGlob, { cwd: pagesPath }); + + files.forEach(file => { + const tocPath = findNearestFile(file, tocs); + _createPage(file, pagesDirectory, createPage, ignore, tocPath); + }); + + watchDirectory( + pagesPath, + pagesGlob, + addedPath => { + if (!_.includes(files, addedPath)) { + const tocPath = findNearestFile(addedPath, tocs); + _createPage(addedPath, pagesDirectory, createPage, ignore, tocPath); + files.push(addedPath); + } + }, + removedPath => { + // Delete the page for the now deleted component. + const componentPath = systemPath.join(pagesDirectory, removedPath); + store.getState().pages.forEach(page => { + if (page.component === componentPath) { + deletePage({ + path: createPath(removedPath), + component: componentPath + }); + } + }); + files = files.filter(f => f !== removedPath); + } + ).then(() => doneCb()); +}; +const _createPage = (filePath, pagesDirectory, createPage, ignore, tocPath) => { + // Filter out special components that shouldn't be made into + // pages. + if (!validatePath(filePath)) { + return; + } + + // Filter out anything matching the given ignore patterns and options + if (ignorePath(filePath, ignore)) { + return; + } + + let toc = undefined; + if (tocPath !== undefined) { + try { + toc = yaml.safeLoad(readFileSync(systemPath.join(pagesDirectory, tocPath), 'utf8')); + } catch (e) { + console.log(e); + } + } + + // Create page object + const createdPath = createPath(filePath); + const page = { + path: createdPath, + component: systemPath.join(pagesDirectory, filePath), + context: { + toc: toc, + rootPath: filePath.substring(0, filePath.indexOf('/')) + } + }; + + // Add page + createPage(page); +}; diff --git a/packages/docs/gatsby-plugin-docs-creator/tsconfig.json b/packages/docs/gatsby-plugin-docs-creator/tsconfig.json new file mode 100644 index 0000000000..f94888c406 --- /dev/null +++ b/packages/docs/gatsby-plugin-docs-creator/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "outDir": "dist", + "target": "es5", + "module": "commonjs", + "jsx": "react", + "declaration": true, + "sourceMap": true, + "experimentalDecorators": true, + "importHelpers": true, + "noUnusedLocals": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true, + "noImplicitAny": false, + "moduleResolution": "node", + "preserveConstEnums": true, + "lib": ["es5", "dom"], + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src"] +} diff --git a/packages/docs/gatsby-theme-fluent-site/.eslintrc b/packages/docs/gatsby-theme-fluent-site/.eslintrc new file mode 100644 index 0000000000..b0d3cca7be --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/.eslintrc @@ -0,0 +1,12 @@ +{ + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + } + }, + "rules": { + "semi": "off" + } +} diff --git a/packages/docs/gatsby-theme-fluent-site/.storybook/main.js b/packages/docs/gatsby-theme-fluent-site/.storybook/main.js new file mode 100644 index 0000000000..24b7233c4a --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/.storybook/main.js @@ -0,0 +1,23 @@ +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') + +module.exports = { + stories: ['../src/**/*.story.tsx'], + addons: ['@storybook/addon-actions', '@storybook/addon-links'], + webpackFinal: async config => { + config.module.rules.push({ + test: /\.(ts|tsx)$/, + loader: require.resolve('babel-loader'), + options: { + presets: [['react-app', { flow: false, typescript: true }]], + }, + }) + + config.plugins.push( + new MonacoWebpackPlugin({ + languages: ['typescript'], + }) + ) + config.resolve.extensions.push('.ts', '.tsx') + return config + }, +} diff --git a/packages/docs/gatsby-theme-fluent-site/ApplicationInsights.md b/packages/docs/gatsby-theme-fluent-site/ApplicationInsights.md new file mode 100644 index 0000000000..ea90c314e4 --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/ApplicationInsights.md @@ -0,0 +1,96 @@ + +# Application Insights README +Fluent website telementry information + +**Table of Contents** + + +- [Application Insights README](#application-insights-readme) + - [Description](#description) + - [Usage](#usage) + - [IMPORTANT! Build notes](#important-build-notes) + - [NPM Packages](#npm-packages) + - [Resources](#resources) + + + + +## Description +The Application Insights interface has be designed as a client side only react component. It hooks into the equivelent of + onComponentDidMount event (via hooks) and runs once per instantiation. + +## Usage + +*PageView* +```typescript +import { usePageViewTelemetry } from '../components/ApplicationInsights' + +... + + let pathName = "Home" // if pathName is null, it will use the window.location.pathName value + const [pageView, setPageView] = usePageViewTelemetry({ name: props.path }) + + // since the call is made immediately, you can just do the following if you are not updating the value + usePageViewTelemetry({ name: props.path }) + +``` +*EventView* +```jsx +import { useEventTelemetry } from '../components/ApplicationInsights' + +... + + const [myEvent, invokeMyEventTelemetry] = useEventTelemetry({ name: 'MyEvent' }) + + const buttonClick = () => { + invokeMyEventTelemetry(); + } + +return ( + +) + +``` + +*EventView With Name/Value Property* +```jsx +import { useEventTelemetry } from '../components/ApplicationInsights' + +... + + const [myEvent, invokeMyEventTelemetry] = useEventTelemetry({ name: 'MyEvent' }) + + const sendEvent = (buttonId:number) => { + myEvent.properties = myEvent.properties ? myEvent.properties : [] + myEvent.properties["Button_Clicked"] = buttonId + // this call will send the update and send the telementry data + invokeMyEventTelemetry(myEvent) + + } + +return ( + + +) + +``` + +## IMPORTANT! Build notes +*NOTE +For production builds you need to set GATBSY_APPLICATIONINSIGHTS_KEY to the value of the production key *prior* to +a production build. This can be done as an evironment variable or in the .env.production file under src/website. +The key is retrieved from the Application Insights app on https://portal.azure.com + +For development/test builds, modify the .env.developement file. + +## NPM Packages +NPM package(s): +@microsoft/applicationinsights-web +@microsoft/applicationinsights-react-js + +## Resources +[Azure Portal Resource](https://ms.portal.azure.com/#@microsoft.onmicrosoft.com/resource/subscriptions/9ccbac18-03d3-485b-a43e-87dc09014817/resourcegroups/OXOSharedRG/providers/microsoft.insights/components/FluentUI-Website/overview) + +[Javascript NPM Setup](https://docs.microsoft.com/en-us/azure/azure-monitor/app/javascript#npm-based-setup) + +[Application Insights React](https://github.com/microsoft/ApplicationInsights-JS/blob/17ef50442f73fd02a758fbd74134933d92607ecf/extensions/applicationinsights-react-js/README.md) diff --git a/packages/docs/gatsby-theme-fluent-site/CHANGELOG.json b/packages/docs/gatsby-theme-fluent-site/CHANGELOG.json new file mode 100644 index 0000000000..3fd9067fb9 --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/CHANGELOG.json @@ -0,0 +1,24 @@ +{ + "name": "gatsby-starter-uifabric-doc", + "entries": [ + { + "date": "Sat, 27 Jul 2019 05:29:12 GMT", + "tag": "gatsby-starter-uifabric-doc_v0.1.1", + "version": "0.1.1", + "comments": { + "patch": [ + { + "comment": "initial publish", + "author": "kchau@microsoft.com", + "commit": "d5ff88bc7ddf21d5e9035f4a95503df50709f55c" + }, + { + "comment": "initial release", + "author": "kchau@microsoft.com", + "commit": "e9f0dccdd68a5890a3a063b79314d3ea446a95da" + } + ] + } + } + ] +} diff --git a/packages/docs/gatsby-theme-fluent-site/CHANGELOG.md b/packages/docs/gatsby-theme-fluent-site/CHANGELOG.md new file mode 100644 index 0000000000..af5c8f1f6b --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/CHANGELOG.md @@ -0,0 +1,11 @@ +# Change Log - gatsby-starter-uifabric-doc + +This log was last generated on Sat, 27 Jul 2019 05:29:12 GMT and should not be manually modified. + +## 0.1.1 +Sat, 27 Jul 2019 05:29:12 GMT + +### Patches + +- initial publish (kchau@microsoft.com) +,- initial release (kchau@microsoft.com) diff --git a/packages/docs/gatsby-theme-fluent-site/LICENSE b/packages/docs/gatsby-theme-fluent-site/LICENSE new file mode 100644 index 0000000000..20f91f2b3c --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 gatsbyjs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/docs/gatsby-theme-fluent-site/README.md b/packages/docs/gatsby-theme-fluent-site/README.md new file mode 100644 index 0000000000..b51a594804 --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/README.md @@ -0,0 +1,86 @@ +## πŸš€ Quick start + + +1. **Start developing.** + + ```sh + yarn + yarn start + ``` + +1. **Open the source code and start editing!** + + Your site is now running at `http://localhost:3000`! + + _Note: You'll also see a second link: _`http://localhost:3000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ + +1. Working with [NetlifyCMS](https://www.netlifycms.org/) + + NetlifyCMS is a React application that sites on top of the markdown content in git and provides a user friendly interface for creating, editing, and reviewing proposed content changes. + + To develop new collections and work within NetlifyCMS's `static/admin/config.yml` file, you can now run a local server and allow the CMS to create and edit your local files + + ```sh + npx netlify-cms-proxy-server + # while server is running, in a seperate terminal run + yarn start + ``` + + Now when you navigate to `http://localhost:3000/admin/` you will be allowed to log in without authentication, and any file change will only change your local data. No git involved. + + +## 🧐 What's inside? + +A quick look at the top-level files and directories you'll see in a the Website package. + + . + β”œβ”€β”€ src + β”œβ”€β”€ gatsby-browser.js + β”œβ”€β”€ gatsby-config.js + β”œβ”€β”€ gatsby-node.js + β”œβ”€β”€ gatsby-ssr.js + β”œβ”€β”€ LICENSE + β”œβ”€β”€ package-lock.json + β”œβ”€β”€ package.json + └── README.md + + + +2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for β€œsource code”. + + +5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. + +6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). + +7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. + +8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. + +9. **`LICENSE`**: Gatsby is licensed under the MIT license. + +11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. + +12. **`README.md`**: A text file containing useful reference information about your project. + +## πŸŽ“ Learning Gatsby + +Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: + +- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. + +- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. + +## πŸ’« Deploy + +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-hello-world) + + + +## Developing Components + +Check out [README](./src/components/CONTRIBUTING.md) in the components directory. + +## Storybook + +A playground for developing components in isolation [README](./src/components/STORYBOOK.md) diff --git a/packages/docs/gatsby-theme-fluent-site/gatsby-config.js b/packages/docs/gatsby-theme-fluent-site/gatsby-config.js new file mode 100644 index 0000000000..39c023d420 --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/gatsby-config.js @@ -0,0 +1,145 @@ +require('dotenv').config({ + path: `.env.${process.env.NODE_ENV}`, +}) +module.exports = themeOptions => { + const { contentPath, pathPrefix } = themeOptions + return { + pathPrefix: pathPrefix || '', + siteMetadata: { + title: 'Microsoft Design - Fluent', + description: + 'Fluent brings the fundamentals of principled design, innovation in technology, and customer needs together as one. It’s a collective approach to creating simplicity and coherence through a shared, open design system across platforms.', + siteURL: 'https://fluentui.z5.web.core.windows.net/', + headerLinks: [ + { + name: 'Fundamentals', + link: '/fundamentals', + headerOnly: true, + }, + { + name: 'Web', + link: '/web', + }, + { + name: 'Windows', + link: '/windows', + }, + { + name: 'iOS', + link: '/ios', + }, + { + name: 'Android', + link: '/android', + }, + { + name: 'Mac', + link: '/mac', + }, + ], + topLinks: [ + { name: 'Get started', link: 'get-started' }, + { name: 'Styles & Theming', link: 'styles' }, + { name: 'Experiences', link: 'experiences' }, + { name: 'Components', link: 'components' }, + ], + footerLinks: [ + { + name: 'Resources', + link: '/resources', + ariaLabel: 'This link will take you to the Resources page', + }, + { + name: "What's new", + link: '/whatsnew', + ariaLabel: "This link will take you to the What's new page", + }, + { + name: 'GitHub', + link: 'https://github.com/microsoft/fluent-site', + target: '_blank', + ariaLabel: 'This link will take you to the Microsoft Fluent UI GitHub site in a new window.', + }, + { + name: 'Privacy & cookies', + link: 'https://privacy.microsoft.com/en-us/privacystatement', + ariaLabel: 'This link will take you to the Microsoft privacy statement.', + }, + ], + homePageData: { + news: [ + { + title: 'Lorem ipsum dolor sit amet, consectet adipiscing elit. Vivamus ut max velit, ut iaculis est. Nullam tincidunt.', + link: '#', + }, + { + title: 'Lorem ipsum dolor sit amet, consectet adipiscing elit. Vivamus ut max velit, ut iaculis est. Nullam tincidunt.', + link: '#', + }, + { + title: 'Lorem ipsum dolor sit amet, consectet adipiscing elit. Vivamus ut max velit, ut iaculis est. Nullam tincidunt.', + link: '#', + }, + { + title: 'Lorem ipsum dolor sit amet, consectet adipiscing elit. Vivamus ut max velit, ut iaculis est. Nullam tincidunt.', + link: '#', + }, + ], + }, + }, + plugins: [ + `gatsby-plugin-emotion`, + `gatsby-transformer-yaml`, + `gatsby-plugin-react-helmet`, + `gatsby-plugin-typescript`, + 'gatsby-plugin-sharp', + 'gatsby-transformer-sharp', + `gatsby-plugin-offline`, + { + resolve: `gatsby-plugin-netlify-cms`, + options: { + modulePath: `${__dirname}/src/cms/cms.js`, + }, + }, + { + resolve: `gatsby-plugin-manifest`, + options: { + name: `Fabric Website 2.0`, + short_name: `fabricwebsite`, + start_url: `/`, + background_color: `#f7f0eb`, + theme_color: `#a2466c`, + display: `standalone`, + }, + }, + { + resolve: `gatsby-plugin-mdx`, + options: { + defaultLayouts: { + default: require.resolve('./src/templates/MDXTemplate.tsx'), + }, + gatsbyRemarkPlugins: [ + { + resolve: `gatsby-remark-images`, + options: { + maxWidth: 400, + withWebp: true, + tracedSVG: true, + linkImagesToOriginal: false, + }, + }, + { + resolve: `gatsby-remark-copy-linked-files`, + }, + ], + }, + }, + { + resolve: `gatsby-plugin-docs-creator`, + options: { + path: contentPath, + }, + }, + ], + } +} diff --git a/packages/docs/gatsby-theme-fluent-site/gatsby-node.js b/packages/docs/gatsby-theme-fluent-site/gatsby-node.js new file mode 100644 index 0000000000..4f9d7fcb5c --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/gatsby-node.js @@ -0,0 +1,29 @@ +const path = require('path') +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') + +exports.onCreatePage = ({ page, actions }) => { + const { createPage, deletePage } = actions +} + +exports.createPages = async ({ actions, graphql }) => { + const { createPage } = actions +} + +exports.onCreateWebpackConfig = ({ stage, actions }) => { + if (stage.startsWith('develop')) { + actions.setWebpackConfig({ + resolve: { + alias: { + 'react-dom': '@hot-loader/react-dom', + }, + }, + }) + } + actions.setWebpackConfig({ + plugins: [ + new MonacoWebpackPlugin({ + languages: ['typescript'], + }), + ], + }) +} diff --git a/packages/docs/gatsby-theme-fluent-site/gatsby-ssr.js b/packages/docs/gatsby-theme-fluent-site/gatsby-ssr.js new file mode 100644 index 0000000000..9255a63c8a --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/gatsby-ssr.js @@ -0,0 +1,20 @@ +import { Stylesheet, InjectionMode } from '@uifabric/merge-styles' +import { renderStatic } from '@uifabric/merge-styles/lib/server' +import { renderToString } from 'react-dom/server' +import React from 'react' + +const config = require('./gatsby-config') + +export const replaceRenderer = ({ bodyComponent, replaceBodyHTMLString, setHeadComponents }) => { + const { html, css } = renderStatic(() => { + return renderToString(bodyComponent) + }) + + replaceBodyHTMLString(html) + + setHeadComponents([
`) + doc.close() + this._setInitialContent = true + } + + const mountTarget = this.getMountTarget() + const win = doc.defaultView || doc.parentView + + // Do not allow elements to be focused within the iframe + win.HTMLElement.prototype.focus = () => {} + + const ctx = { window: win, document: doc } + const content = this.props.children(ctx) || null + return ReactDOM.createPortal(content, mountTarget) + } + + render() { + const { children, ...rest } = this.props + return ( + + ) + } +} diff --git a/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.story.tsx b/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.story.tsx new file mode 100644 index 0000000000..03803a3595 --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.story.tsx @@ -0,0 +1,89 @@ +import React from 'react' +import { Playground } from '.' +import { Global, css } from '@emotion/core' + +export default { + title: 'Playground', + component: Playground, +} + +// TODO: should share this with the main app and other stories. +const GlobalStyles = () => ( + +) + +export const ToStorybook = () => { + const examples = [ + { + title: 'Hello World', + description: 'Description for the first example', + source: `import * as React from "react" + +export default () =>

Hello World!

`, + }, + { + title: 'Goodbye World', + description: 'Description for the second example', + source: `import * as React from "react" + +export default () =>

Goodbye World?

`, + }, + { + title: 'RTL Example', + description: 'Description for the third example', + source: `import * as React from "react" + +export default () => ( +
+ + +
+)`, + }, + { + title: 'Theme Example', + description: 'Description for the third example', + source: `import * as React from "react" + +export default ({ theme }) => { + const style = { + padding: "1rem" + } + switch (theme) { + case "Dark": + style.background = "#333" + style.color = "#eee" + break + case "High Contrast": + style.background = "#000" + style.color = "#fff" + break + } + return

Current theme: {theme}

+}`, + }, + ] + const themes = ['Light', 'Dark', 'High Contrast'] + return ( + <> + + + + ) +} + +ToStorybook.story = { + name: 'Basic', +} diff --git a/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.tsx b/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.tsx new file mode 100644 index 0000000000..79e86b89dd --- /dev/null +++ b/packages/docs/gatsby-theme-fluent-site/src/components/Playground/Playground.tsx @@ -0,0 +1,66 @@ +import * as React from 'react' +import styled from '@emotion/styled' +import { PlaygroundProvider, IPlayground, IExample } from './context' +import { Sidebar } from './Sidebar' +import { Viewport } from './Viewport' +import { Footer } from './Footer' + +function handleAction(state: IPlayground, action: any): IPlayground { + switch (action.type) { + case 'TOGGLE_RTL': + return { ...state, rtl: !state.rtl } + case 'CHANGE_THEME': + return { ...state, currentTheme: action.payload } + case 'CHANGE_EXAMPLE': + return { ...state, currentExample: action.payload } + case 'CHANGE_RESOLUTION': + return { ...state, resolution: action.payload } + case 'CHANGE_ZOOM_LEVEL': + return { ...state, zoomLevel: action.payload } + case 'CHANGE_CURRENT_EXAMPLE_SOURCE': + return { ...state, currentExample: { ...state.currentExample, source: action.payload } } + case 'TOGGLE_PLUGIN': + return { ...state, currentPlugin: state.currentPlugin === action.payload ? null : action.payload } + default: + console.warn('Missing handler for action: %s', action.type) + return state + } +} + +export const Playground = ({ examples = [], themes = [] }: { examples: IExample[]; themes: string[] }) => { + // TODO: ensure state stays in sync with changes to examples/themes props. + const playground = React.useReducer(handleAction, { + examples, + themes, + rtl: false, + zoomLevel: 1, + resolution: 'Responsive', + currentExample: examples[0], + currentTheme: themes[0], + currentPlugin: null, + }) + + return ( + + + + + + +