Skip to content

Commit

Permalink
chore: documented technical parts of the library
Browse files Browse the repository at this point in the history
  • Loading branch information
g-cheishvili authored and droshev committed Aug 23, 2023
1 parent 0731226 commit b7f8078
Show file tree
Hide file tree
Showing 18 changed files with 168 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .storybook/MainDocPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {DocsPage, SAPContainer} from "fundamental-styles/doc-ui";

/**
* Component which creates and renders the DocsPage component
* in a SAPContext provided environment.
* This component is used in the storybook preview
*/
export function MainDocPage() {
return <SAPContainer>
<DocsPage />
Expand Down
11 changes: 11 additions & 0 deletions .storybook/custom/addons/utilities/get-owner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ const {sortedProjects} = require('./projects');

const ownersCache = new Map();


/**
* Function to get the owner package of a story
*
* if file path is defined, it will be used to understand under which package directory the story is located
* and then the package will be returned
*
* the execution is cached to avoid multiple calls from multiple places, because these calls are common
* @param story
* @returns {undefined|any}
*/
module.exports.getOwner = (story) => {
if (!story) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ function useMemoizedDeps(deps, comparator) {
return memoizedDeps.current;
}

/**
* useMemo with comparator
* default comparator is shallow equal (===) comparison of deps
* but you can pass your own comparator to compare deps
*/
module.exports.useMemoWithComparator = function (callback, deps, comparator) {
const memoizedDeps = useMemoizedDeps(deps, comparator);

Expand Down
10 changes: 10 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ export default {
}
},
options: {
/**
* We want to sort the stories in the following order:
* 1. Introduction
* 2. Docs of Stories in alphabetical order
*
* This function can not use `typescript` or anything from outer scope
* because during compilation it will be extracted into separate chunk
* as-is and executed in the browser! Only `javascript` is allowed
* and it has to be self-contained.
*/
storySort: (a, b) => {
const introductionName = 'Introduction',
aIsIntroduction = a.title.includes(introductionName),
Expand Down
30 changes: 23 additions & 7 deletions CONTRIBUTORS.md → docs/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
## Directories and files

First of all, project is using NX workspaces, so everything that is applicable to NX workspaces is applicable to this project as well.
This file describes the specific things that are done for the `fundamental-styles`.
* `./packages` - Here resides packages that are publishable or are for internal use.
* `./packages/doc-ui` - Components, hooks and contexts for the documentation pages.
* `./packages/storybook` - Storybook decorators and interfaces
* `./packages/configuration` - Configuration for the project, things like list of
* `./packages/configuration` - Configuration for the project, things like the list of
packages for storybook UI, previous versions and etc.
* `./packages/workspace-plugins` - Plugin for workspace management. Executors for building, version syncing and etc.
* `./packages/**` - Packages that are publishable
* `./projects.js` - List of the projects, computed from the `./workspace.json` file and with the contents of the `./projects.js`;
This file exists, because it is consumable by both storybook manager and preview parts. In general, they work in different
environments. Manager is running with ESBuild and preview is running with Vite. ESBuild can only include in itself JS or TS
files, but we also need to have access to other types of files, things like `scss` files for theming and etc. List of the
available themes is described in this file, but what stands behind particular theme is resolved in the
`packages/configuration/src/lib/packages.ts` file. Per project themes are described in their folders.
* `./projects.js` - List of the projects; This file exists, because it is consumable by both storybook manager and preview parts.
In general, they work in different environments. Manager is running with ESBuild and preview is running with Vite.
ESBuild can only include in itself Js or Ts files, but we also need to have access to other types of files, things
like `scss` files for theming and etc. List of the available themes is described in this file, but what stands behind
particular theme is resolved in the `packages/configuration/src/lib/packages.ts` file. Per project themes are
described in their folders at `packages/*/package-config.ts` files.
* `./packages/*/theming/*.scss` - are files, where the variables for themes are defined or collected from various places.
* `./packages/*/package-config.ts` - are files, where the already collected data from `./projects.js` is consumed and combined
with the data from `./packages/*/theming/*.scss` files. These files are later imported in `packages/configuration/src/lib/packages.ts`
Expand Down Expand Up @@ -78,4 +79,19 @@ StoryFunction.parameters = {
};
```

## Versioning

fundamental-styles consists of multiple sub-packages and the versions for all of them
are managed by the root package.json file. This is done to ensure that all the packages
are in sync with each other. The versioning of the packages is done using
[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and [Semantic Versioning](https://semver.org/).

All the information about the versioning is given in the links above
but TL;DR is that before we reach version 1, every fix, feature or chore is resulting in the patch version change,
if those changes do not break the API, and if they do, then the minor version is changed.

After version 1, the patch version is the result of the bug fixes, minor version is the result of the new features,
and major version is the result of the breaking changes.

After every merge into the main, `rc` version is released automatically with the changes it includes,
this ensures fast feedback loop for the users of the library, and allows us to test the changes in the real world.
4 changes: 4 additions & 0 deletions packages/doc-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Doc-ui package

This package contains the UI components, contexts, types and hooks for the documentation site.
Things like package selector, header, version switcher, theme switcher and more.
5 changes: 5 additions & 0 deletions packages/doc-ui/src/components/DocsPage/DocsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import InfoLabels from '../InfoLabels';
import Toc from '../Toc/Toc';
import {SAPContext} from "../../contexts/SAPContext";


/**
* DocsPage component that wraps all the components that make up the DocsPage
* in the Storybook Docs view.
*/
const DocsPage = () => {
const {storyContext} = useContext(SAPContext);

Expand Down
5 changes: 5 additions & 0 deletions packages/doc-ui/src/components/SAPContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { SAPContext } from '../contexts/SAPContext';
import { contentDensities, directionalities } from 'fundamental-styles/configuration';
import { getPackage } from 'fundamental-styles/utils';

/**
* Main container which wraps any component in the Storybook Docs view
* and enriches it with the SAPContext.
* This component is a single source of truth for the SAPContext.
*/
export const SAPContainer = ({children}) => {
const channel = useMemo(() => addons.getChannel(), []);
const docsContext = useContext(DocsContext);
Expand Down
6 changes: 6 additions & 0 deletions packages/doc-ui/src/contexts/SAPContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ export interface SAPContextType {
contentDensities: { value: string, title: string }[],
}

/**
* Main context for SAP documentation site.
* This context is used to store and share state between components.
* The state includes theme, directionality, content density and selected package information,
* as well as functions to update the state.
*/
export const SAPContext = createContext<SAPContextType>({} as unknown as SAPContextType);
1 change: 0 additions & 1 deletion packages/storybook/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './lib/storybook';
export * from './lib/interfaces/package.config.interface';

export * from './lib/decorators/themeProvider';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ function IntroductionPageWrapper({ children }) {
</SAPContainer>;
}

/**
* Component which creates and renders the IntroductionPage component
* with given readme content for the package which is currently being viewed.
* @param readme
* @constructor
*/
export function RenderPackageIntroduction(readme: any) {
return () => <IntroductionPageWrapper>
<Markdown options={{forceBlock: true}}>{readme}</Markdown>
Expand Down
16 changes: 16 additions & 0 deletions packages/storybook/src/lib/interfaces/package.config.interface.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
/**
* Theme definition interface,
* used to define the theme and its variables
*/
export interface ThemeDefinition {
/** Theme unique identifier, in snake_case */
id: string;
/** Theme title, in sentence case, visible on selectors and etc */
name: string;
/** Theme variables, in CSS format, commonly loaded using FS reads of the CSS files */
variables: string;
}

/**
* Package configuration interface,
* used to define the package and its themes
*/
export interface PackageConfigInterface {
/** Package unique identifier, in dash-case */
value: string;
/** Package title, in sentence case */
title: string;
/** Path to the package root directory, from workspace root */
pathToPackage: string;
/** Default theme's identifier */
defaultTheme: string;
/** Package themes */
themes: ThemeDefinition[]
}
3 changes: 0 additions & 3 deletions packages/storybook/src/lib/storybook.ts

This file was deleted.

13 changes: 12 additions & 1 deletion packages/storybook/src/lib/visual-stories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import capitalize from 'lodash/capitalize';
import { StoryFn } from '@storybook/html';

const wrappedStory = (storyName: string, storyFn, direction: 'ltr' | 'rtl', compact = false) => `
<h2> ${storyName} </h2>
Expand All @@ -12,7 +13,17 @@ const wrappedStory = (storyName: string, storyFn, direction: 'ltr' | 'rtl', comp

const ignoredStoryNames = new Set(['default', 'dev', '__namedExportsOrder']);

export function visualStory(stories) {
/**
* Function, which is being called for each story file, which needs to be visualized
* for chromatic testing.
*
* idea is that it takes object of stories and returns function, which returns
* html element with all stories wrapped in divs, in both ltr and rtl directions,
* as well as compact and non-compact versions.
*
* @param stories
*/
export function visualStory(stories: Record<string, StoryFn>) {
return () => {
const storyNames = Object.keys(stories).filter(story => !ignoredStoryNames.has(story));
const allVisualStories = document.createElement('div');
Expand Down
4 changes: 2 additions & 2 deletions packages/theming-preview/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#Fundamental Library - Theming Preview
# Fundamental Library - Theming Preview

This package is mend to be used in SAP Theme Designer as Fundamental Library Components Previews.
This package is mend to be used in SAP Theme Designer as Fundamental Library Components Previews.
Original file line number Diff line number Diff line change
@@ -1,7 +1,60 @@
### Fundamental styles visual stories executor
# Fundamental styles visual stories executor

Executor generates `Visual` stories for target project's stories. It combines every story in every `*.stories.(ts|tsx|js|jsx)`
file with every theme which is passed to it from options.

You can ignore stories by providing `Regex` pattern to options property `excludedStoriesKinds` or by setting
`true` in `parameters.visualDisabled`.

## Usage

In `project.json` of the target project, add new task with a configuration like so:
```
{
// Rest of the project.json
"targets": {
// Rest of the targets
"build-visual": {
"executor": "workspace-plugins:visual-stories",
"options": {
"themes": [
// The list of the themes which will be used to generate stories
// Themes should be attached to the given project in the `{workspaceRoot}/projects.js` file
],
"excludedStoriesKinds": [
// The list of the regex patterns which will be used to exclude stories
// The passed parameters will be matched agains story titles
"^(Helpers|Dev)"
]
},
"outputs": ["path/to/output/folder/relative/to/workspaceRoot"]
}
}
}
```
after that you can run the executor with `nx run <project-name>:build-visual` command and look for the generated
stories in the `path/to/output/folder/relative/to/workspaceRoot` folder.

## How it works

The executor will look for every `/stories/**/*.stories.+(js|jsx|ts|tsx)` file inside target project's root
folder, so for example if you have a project in `{workspaceRoot}/packages/styles`, then executor will look for
stories with micromatch `{workspaceRoot}/packages/styles/stories/**/*.stories.+(js|jsx|ts|tsx)`.

Then the executor will find the themes, from the [projects.js](projects.js) file. The themes should be attached to
the target project in the `projects.js` file, otherwise executor will throw an error.

After that, executor will traverse every story, parse the story file(using babel), find the default export object and
using that, it will find what is the title of the story and also if it's excluded from the visual story generation.
Meaning if there is a `parameters.visualDisabled` property in the story object and it's set to `true`, then the story
will be excluded from the generation.

From the story title, we try and figure out what should be the name of the generated visuals file. The pattern used is
`{outputPath}/{storyOriginalPath.replace('{projectRoot}', '')/{dashCase(storyTitle)}.{themeName}.visual.ts`

The created visual stories file will import `* as stories` from the original story file and will export a new default
object, which will have a title `Visuals/{storyTitle}/{themeName}`. The stories themselves are by design written in
HTML framework of storybook, so basically they are a functions, which return a string of HTML. We use that fact and we
have a function which will traverse the `stories` object and will call every story function and generate in runtime
the HTML string, which will be used to generate the visual story. More details about that function can be found in
[visual-stories.ts](packages/storybook/src/lib/visual-stories.ts) file.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default async function (schema: VisualStoriesSchema, context: ExecutorCon
sourceType: 'module',
filename: storyFileName,
presets: ['@babel/preset-react', '@babel/preset-typescript']
});
})!;
let fullTitle = '';
let storyTitle = '';
let visualDisabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ export default async function (tree: Tree, schema: CreatePackageSchema) {
return () => {
logger.info(`
Next steps:
- Open ${workspaceRoot}/projects.js file and confirm that name is correct'
- Open '.storybook/preview.ts' file and add your package to the order of the packages. Key for new package is '${namings.fileName}'
- Commit changes
- Open ${workspaceRoot}/projects.js file and confirm that the name is correct'
- Open '.storybook/preview.ts' file and add your package to the order of the packages. The key for the new package is '${namings.fileName}'
- Commit the changes
`);
};
}

0 comments on commit b7f8078

Please sign in to comment.