diff --git a/common/changes/@uifabric/example-app-base/edit-docs-buttons_2018-03-31-00-27.json b/common/changes/@uifabric/example-app-base/edit-docs-buttons_2018-03-31-00-27.json new file mode 100644 index 00000000000000..df66dfe34204b1 --- /dev/null +++ b/common/changes/@uifabric/example-app-base/edit-docs-buttons_2018-03-31-00-27.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@uifabric/example-app-base", + "comment": "Add new APIs for editing sections on GitHub.", + "type": "minor" + } + ], + "packageName": "@uifabric/example-app-base", + "email": "v-jojanz@microsoft.com" +} \ No newline at end of file diff --git a/common/changes/office-ui-fabric-react/edit-docs-buttons_2018-03-31-00-27.json b/common/changes/office-ui-fabric-react/edit-docs-buttons_2018-03-31-00-27.json new file mode 100644 index 00000000000000..4f81ceaabfd170 --- /dev/null +++ b/common/changes/office-ui-fabric-react/edit-docs-buttons_2018-03-31-00-27.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "Add new component page prop for editing on GitHub.", + "type": "patch" + } + ], + "packageName": "office-ui-fabric-react", + "email": "v-jojanz@microsoft.com" +} \ No newline at end of file diff --git a/packages/example-app-base/src/components/ComponentPage/ComponentPage.scss b/packages/example-app-base/src/components/ComponentPage/ComponentPage.scss index 9e4557531f4f9a..4089033969d1f0 100644 --- a/packages/example-app-base/src/components/ComponentPage/ComponentPage.scss +++ b/packages/example-app-base/src/components/ComponentPage/ComponentPage.scss @@ -78,6 +78,23 @@ $dontColor: #A61E22; } } + .ComponentPage-usageHeader, + .ComponentPage-overviewSectionHeader, + .ComponentPage-doSectionHeader { + display: flex; + justify-content: space-between; + align-items: center; + } + + .ComponentPage-usageHeader { + margin-top: 10px; + margin-bottom: $componentSubHeadMargin; + + .ComponentPage-subHeading { + margin: 0; + } + } + .ComponentPage-related { min-width: 200px; @@ -141,17 +158,7 @@ $dontColor: #A61E22; margin-bottom: 20px; h3 { - margin: 16px 0 40px 0; @include ms-font-xl; - - &::after { - background-color: #a4cf0c; - border-radius: 3px; - content: ''; - display: block; - height: 8px; - margin: 12px 0; - } } ul { @@ -171,9 +178,26 @@ $dontColor: #A61E22; &:first-child { @include ms-margin-right(120px); } + + .ComponentPage-doSectionHeader { + margin: 16px 0 0 0; + + h3 { + margin: 0; + } + } + + .ComponentPage-doSectionLine { + background-color: #a4cf0c; + border-radius: 3px; + display: block; + height: 8px; + margin: 12px 0 40px; + border: 0; + } } - .ComponentPage-doSection--dont h3::after { + .ComponentPage-doSection--dont .ComponentPage-doSectionLine { background-color: #e74856; } diff --git a/packages/example-app-base/src/components/ComponentPage/ComponentPage.tsx b/packages/example-app-base/src/components/ComponentPage/ComponentPage.tsx index 133752d29f0fdd..30729325bb2445 100644 --- a/packages/example-app-base/src/components/ComponentPage/ComponentPage.tsx +++ b/packages/example-app-base/src/components/ComponentPage/ComponentPage.tsx @@ -7,6 +7,10 @@ import { Link } from 'office-ui-fabric-react/lib/Link'; import { MessageBar } from 'office-ui-fabric-react/lib/MessageBar'; +import { + EditSection, + ComponentPageSection, +} from '../EditSection'; import './ComponentPage.scss'; export interface IComponentPageSection { @@ -32,6 +36,40 @@ export interface IComponentPageProps { otherSections?: IComponentPageSection[]; allowNativeProps?: boolean | string; nativePropsElement?: string | string[] | undefined; + + /** + * Link to the Component root folder on GitHub. + * Enables 'View On GitHub' and all 'Edit' buttons. + */ + componentUrl?: string; + + /** + * Link to the BestPractices markdown file on GitHub. + * Enables the 'Edit Best Practices' button. + * Overrides URL from componentUrl. + */ + editBestPracticesUrl?: string; + + /** + * Link to the Donts markdown file on GitHub. + * Enables the 'Edit Don'ts' button. + * Overrides URL from componentUrl. + */ + editDontsUrl?: string; + + /** + * Link to the Dos markdown file on GitHub. + * Enables the 'Edit Dos' button. + * Overrides URL from componentUrl. + */ + editDosUrl?: string; + + /** + * Link to the Overview markdown file on GitHub. + * Enables the 'Edit Overview' button. + * Overrides URL from componentUrl. + */ + editOverviewUrl?: string; } export class ComponentPage extends React.Component { @@ -63,7 +101,15 @@ export class ComponentPage extends React.Component {
{ this._getComponentStatusBadges() }
-

Overview

+
+

Overview

+ +
{ overview } @@ -100,7 +146,7 @@ export class ComponentPage extends React.Component { let { bestPractices, dos, - donts + donts, } = this.props; if (bestPractices && dos && donts) { @@ -153,8 +199,8 @@ export class ComponentPage extends React.Component { private _getNativePropsInfo(): JSX.Element | undefined { if (this.props.allowNativeProps) { - let elementString: string | string[] | JSX.Element = this.props.nativePropsElement || 'div', - componentString: JSX.Element | undefined; + let elementString: string | string[] | JSX.Element = this.props.nativePropsElement || 'div'; + let componentString: JSX.Element | undefined; if (typeof elementString === 'object' && elementString.length > 1) { const elementArr = elementString.slice(); for (let _i = 0; _i < elementArr.length; _i++) { @@ -196,11 +242,18 @@ export class ComponentPage extends React.Component { private _getDosAndDonts(): JSX.Element | undefined { let dosAndDonts: Array = []; - if (this.props.bestPractices) { dosAndDonts.push(
-

Best Practices

+
+

Best Practices

+ +
{ this.props.bestPractices }
); @@ -210,11 +263,29 @@ export class ComponentPage extends React.Component { dosAndDonts.push(
-

Do

+
+

Do

+ +
+
{ this.props.dos }
-

Don’t

+
+

Don’t

+ +
+
{ this.props.donts }
@@ -287,4 +358,23 @@ export class ComponentPage extends React.Component { return undefined; } + + private _getURL(section: string, url?: string): string { + if (url) { + return url; + } + const componentName = (this.props.title || this.props.componentName).replace(/\s/g, ''); + // Generate edit URL from componentURL + let mdUrl; + if (this.props.componentUrl) { + mdUrl = `${this.props.componentUrl}/docs/${componentName}${section}.md`; + // Replace /tree/ or /blob/ with /edit/ to get straight to GitHub editor. + if (mdUrl!.includes('/tree/')) { + mdUrl = mdUrl!.replace('/tree/', '/edit/'); + } else if (mdUrl!.includes('/blob/')) { + mdUrl = mdUrl!.replace('/blob/', '/edit/'); + } + } + return mdUrl; + } } diff --git a/packages/example-app-base/src/components/EditSection/EditSection.tsx b/packages/example-app-base/src/components/EditSection/EditSection.tsx new file mode 100644 index 00000000000000..bb7546d9afbe33 --- /dev/null +++ b/packages/example-app-base/src/components/EditSection/EditSection.tsx @@ -0,0 +1,65 @@ +import * as React from 'react'; +import { + IEditSectionProps, + ComponentPageSection, +} from './EditSection.types'; +import { IconButton } from 'office-ui-fabric-react/lib/Button'; +import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip'; + +export class EditSection extends React.Component { + public render(): JSX.Element | null { + const { sectionContent } = this.props; + const isMarkdown = sectionContent ? typeof sectionContent.type === 'function' : false; + if (isMarkdown === false) { + return null; + } + + const { + title, + section: sectionIndex, + url, + } = this.props; + const section = ComponentPageSection[sectionIndex!]; + const readableSection = this._getReadableSection(); + + return ( + + + + ); + } + + private _getReadableSection(): string { + const { + section: sectionIndex, + readableSection: readableSectionProp, + } = this.props; + if (readableSectionProp) { + return readableSectionProp; + } + + const section = ComponentPageSection[sectionIndex!]; + let readableSection = section; + switch (sectionIndex) { + case ComponentPageSection.BestPractices: + readableSection = 'Best Practices'; + break; + case ComponentPageSection.Donts: + readableSection = 'Don\'ts'; + break; + default: + readableSection = section; + } + return readableSection; + } +} \ No newline at end of file diff --git a/packages/example-app-base/src/components/EditSection/EditSection.types.ts b/packages/example-app-base/src/components/EditSection/EditSection.types.ts new file mode 100644 index 00000000000000..93e426651dd71e --- /dev/null +++ b/packages/example-app-base/src/components/EditSection/EditSection.types.ts @@ -0,0 +1,47 @@ +import { EditSection } from './EditSection'; + +export enum ComponentPageSection { + BestPractices, + Donts, + Dos, + Overview, +} + +export interface IEditSection { + +} + +export interface IEditSectionProps extends React.HTMLAttributes { + /** + * Optional callback to access the IPersona interface. Use this instead of ref for accessing + * the public methods and properties of the component. + */ + componentRef?: (component: IEditSection | null) => void; + + /** + * The name of the Component + */ + title: string; + + /** + * The section of the page. + */ + section: ComponentPageSection; + + /** + * Pass the prop that has the content of the section. + * This checks if the content is a function before showing + * the EditSection button. + */ + sectionContent: JSX.Element; + + /** + * Override for section name. + */ + readableSection?: string; + + /** + * Url for the edit button. + */ + url: string; +} \ No newline at end of file diff --git a/packages/example-app-base/src/components/EditSection/index.ts b/packages/example-app-base/src/components/EditSection/index.ts new file mode 100644 index 00000000000000..0b132dae270ccd --- /dev/null +++ b/packages/example-app-base/src/components/EditSection/index.ts @@ -0,0 +1,2 @@ +export * from './EditSection'; +export * from './EditSection.types'; \ No newline at end of file diff --git a/packages/example-app-base/src/index.ts b/packages/example-app-base/src/index.ts index 5b271b3fd29478..12d6abe83f820c 100644 --- a/packages/example-app-base/src/index.ts +++ b/packages/example-app-base/src/index.ts @@ -1,7 +1,7 @@ export * from './components/App/App'; export * from './components/ComponentPage/ComponentPage'; -export * from './components/ComponentPage/ComponentPage'; export * from './components/ComponentPage/IComponentDemoPageProps'; +export * from './components/EditSection'; export * from './components/ExampleCard/ExampleCard'; export * from './components/Header/Header'; export * from './components/Highlight/Highlight'; diff --git a/packages/office-ui-fabric-react/src/components/ActivityItem/ActivityItemPage.tsx b/packages/office-ui-fabric-react/src/components/ActivityItem/ActivityItemPage.tsx index 99638c9cefbe2a..ad31ba2318ad1f 100644 --- a/packages/office-ui-fabric-react/src/components/ActivityItem/ActivityItemPage.tsx +++ b/packages/office-ui-fabric-react/src/components/ActivityItem/ActivityItemPage.tsx @@ -12,10 +12,6 @@ import { ActivityItemBasicExample } from './examples/ActivityItem.Basic.Example' import { ActivityItemPersonaExample } from './examples/ActivityItem.Persona.Example'; import { ActivityItemCompactExample } from './examples/ActivityItem.Compact.Example'; -const ActivityItemOverview = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemOverview.md'); -const ActivityItemDos = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemDos.md'); -const ActivityItemDonts = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemDonts.md'); - const ActivityItemBasicExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/examples/ActivityItem.Basic.Example.tsx') as string; const ActivityItemPersonaExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/examples/ActivityItem.Persona.Example.tsx') as string; const ActivityItemCompactExampleCode = require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/examples/ActivityItem.Compact.Example.tsx') as string; @@ -26,6 +22,7 @@ export class ActivityItemPage extends React.Component @@ -48,7 +45,7 @@ export class ActivityItemPage extends React.Component - { ActivityItemOverview } + { require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemOverview.md') } } bestPractices={ @@ -56,12 +53,12 @@ export class ActivityItemPage extends React.Component - { ActivityItemDos } + { require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemDos.md') } } donts={ - { ActivityItemDonts } + { require('!raw-loader!office-ui-fabric-react/src/components/ActivityItem/docs/ActivityItemDonts.md') } } isHeaderVisible={ this.props.isHeaderVisible }