Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .husky/post-checkout
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node webapp/scripts/updateBranchInfo.mjs
node webapp/scripts/updateBranchInfo.js
2 changes: 1 addition & 1 deletion .husky/post-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node webapp/scripts/updateBranchInfo.mjs
node webapp/scripts/updateBranchInfo.js
3 changes: 3 additions & 0 deletions library/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# copy file to .env.local and fill in the API key to enable Tolgee in Storybook
VITE_APP_TOLGEE_API_URL=https://app.tolgee.io
VITE_APP_TOLGEE_API_KEY=
6 changes: 6 additions & 0 deletions library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/
node_modules/
*.local

*storybook.log
storybook-static/
2 changes: 2 additions & 0 deletions library/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/dist/
/src/i18n/*.json
19 changes: 19 additions & 0 deletions library/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { StorybookConfig } from '@storybook/react-vite';

export default {
stories: ['../src/**/stories.@(js|jsx|ts|tsx)', '../src/**/*.@(md|mdx)'],
addons: [
'@storybook/addon-docs',
'@storybook/addon-a11y',
'@storybook/addon-themes',
'@tolgee/storybook-addon',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
typescript: {
check: true,
reactDocgen: 'react-docgen-typescript',
},
} satisfies StorybookConfig;
51 changes: 51 additions & 0 deletions library/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { CssBaseline, ThemeProvider } from '@mui/material';
import type { Preview } from '@storybook/react-vite';
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
import { withTolgeeProvider } from '@tolgee/storybook-addon';
import { MuiLocalizationProvider } from 'lib.components/MuiLocalizationProvider';
import { locales } from 'lib.constants/locales';

import { getTheme } from '../../webapp/src/ThemeProvider'; // TODO migrate https://github.com/tolgee/tolgee-platform/issues/3326
import { branchName } from '../../webapp/src/branch.json';

const language = 'en';
const featureTag = `draft: ${branchName.split('/').pop()}`;

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [
withTolgeeProvider({
messageFormat: 'icu',
locales,
LocalizationProvider: MuiLocalizationProvider,
tolgee: {
language,
fallbackLanguage: language,
apiUrl: import.meta.env.VITE_APP_TOLGEE_API_URL,
apiKey: import.meta.env.VITE_APP_TOLGEE_API_KEY,
staticData: Object.fromEntries(
Object.entries(locales).map(([k, v]) => [k, v.translations]),
),
tagNewKeys: [featureTag],
},
}),
withThemeFromJSXProvider({
GlobalStyles: CssBaseline,
Provider: ThemeProvider,
themes: {
Light: getTheme('light'),
Dark: getTheme('dark'),
},
defaultTheme: 'Light',
}),
],
} satisfies Preview;

export default preview;
59 changes: 59 additions & 0 deletions library/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Component/Hook/... Library

This project is a library of components/hooks/... which are reused across other
Tolgee applications. This is not an application by itself, but there is a
[Storybook](https://storybook.js.org/) instance integrated to display and let
you try the components individually or in preset combinations.

## Storybook

Install Storybook and library dependencies:

```shell
cd library
npm run install
```

Duplicate [.env](./.env) as [.env.local](./.env.local) and configure your Tolgee API KEY.

Addon for Tolgee is preset, but its dependencies have to be also installed:

```shell
cd ../storybook-tolgee-addon
npm run install
```

Run Storybook:

```shell
cd ../library
npm run storybook
```

Storybook should open in your browser, otherwise open <http://localhost:6006/>.

## Component Migration

- Apply the boy scout rule – improve names, aliases, subpaths, dependencies...
- Move the component/hook/... from `webapp/src/component/` directory under `library/src/components/` (note the plural – we are unifying it to plurals everywhere). If the component/hook/... is placed under a subpath, persist it.
- Keep one component per file. Constants reused elsewhere can be placed under `constants.ts`. Helper functions under `utils.ts`.
- Up until now, each component was a single file (e.g. `MfaBadge.tsx`), this is changing (not for hooks/...). Please create a directory named like the component (i.e. `MfaBadge`), move the component inside and name it `index.tsx`. This way the component can still be referenced the same path (omit `index.tsx` in the path).
- Remove the original component/hook/...
- Update dependencies. Within `webapp` use `@tginternal/library/` prefix (e.g. `@tginternal/library/hooks/useCurrentLanguage`). Within `library` use `lib.` prefix (e.g. `lib.hooks/useCurrentLanguage`). Referencing `webapp` from `library` might not be safe. At the moment, only a few prefixes are predefined in `library`'s [tsconfig.json](./tsconfig.json), [package.json](./package.json) and [vite.config.ts](./vite.config.ts), add more as you need them.
- Remember the boy scout rule.

## Component Documentation

- Read [writing stories](https://storybook.js.org/docs/writing-stories) Storybook docs.
- CSF docs:
- In the component directory, create `stories.tsx` file.
- The component (object of `Meta` type) and its stories (objects of `Story` type) are declared and exported here.
- Many properties can be set here, but Storybook can derive a lot by itself, so check the defaults at first. Storybook inspects the component's code for prop names, comments... so rather spend time on the component than on the stories (TSDoc comments will bring the value also elsewhere).
- Many properties can be set on the component level for all stories or on the individual story level.
- For inspiration have a look on [MfaBadge/stories.tsx](./src/components/MfaBadge/stories.tsx).
- For details have a look on [CSF docs](https://storybook.js.org/docs/api/csf).
- MDX docs:
- If the autogenerated CSF documentation is not enough (e.g. additional formatted texts are needed), create `stories.mdx` file next to `stories.tsx`.
- You have a free hand in writing arbitrary Markdown texts here and inserting stories from `stories.tsx` to them. Please follow CSF structure and other MDX files.
- For inspiration have a look on [FlagImage/stories.mdx](./src/components/languages/FlagImage/stories.mdx).
- For details have a look on [MDX docs](https://storybook.js.org/docs/writing-docs/mdx).
27 changes: 27 additions & 0 deletions library/cspell.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { defineConfig } from 'cspell';

export default defineConfig({
version: '0.2',
readonly: true,
language: 'en', // === en-US
minWordLength: 3,
caseSensitive: true,
words: ['CSF', 'subpaths', 'Tolgee', 'tsc', 'Vite'],
flagWords: [],
ignoreWords: [
'autodocs',
'Čeština',
'Dansk',
'Deutsch',
'env',
'esnext',
'Español',
'Français',
'fns',
'gfm',
'Português',
'tginternal',
'tolgee',
],
ignorePaths: ['/dist/', '/src/i18n/*.json', '/storybook-static/'],
});
18 changes: 18 additions & 0 deletions library/custom.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// <reference types="storybook/test" />

// ^ Load Storybook types (play, queries...)

// Enable type checking for import.meta.env.VITE_APP_TOLGEE_API_URL/VITE_APP_TOLGEE_API_KEY

interface ViteTypeOptions {
strictImportMetaEnv: unknown;
}

interface ImportMetaEnv {
readonly VITE_APP_TOLGEE_API_URL: string;
readonly VITE_APP_TOLGEE_API_KEY: string;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}
81 changes: 81 additions & 0 deletions library/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import jsPlugin from '@eslint/js';
import jsonPlugin from '@eslint/json';
import markdownPlugin from '@eslint/markdown';
import reactPlugin from 'eslint-plugin-react';
import reactHooksPlugin from 'eslint-plugin-react-hooks';
import reactRefreshPlugin from 'eslint-plugin-react-refresh';
import tsPlugin from 'typescript-eslint';
import compatPlugin from 'eslint-plugin-compat';
import prettierConfig from 'eslint-config-prettier/flat';

/**
* @type {import('eslint').Linter.Config[]}
*/
export default defineConfig([
{
settings: {
react: {
version: 'detect',
},
},
},
{
languageOptions: {
globals: {
...globals.browser,
},
parserOptions: {
tsconfigRootDir: import.meta.dirname,
ecmaFeatures: {
jsx: true,
},
},
sourceType: 'module',
},
},
{
ignores: ['dist/*', 'storybook-static/*'],
},
{
files: ['**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx'],
extends: [
jsPlugin.configs.recommended,
tsPlugin.configs.recommended,
reactPlugin.configs.flat.recommended,
reactPlugin.configs.flat['jsx-runtime'],
],
},
{
files: ['**/*.jsx', '**/*.tsx'],
extends: [
reactHooksPlugin.configs.flat.recommended,
reactRefreshPlugin.configs.vite,
],
},
{
files: ['src/**/stories.jsx', 'src/**/stories.tsx'],
rules: {
'react-refresh/only-export-components': [
'error',
{ allowExportNames: ['meta'] },
],
},
},
{
files: ['**/*.json'],
ignores: ['package-lock.json'],
language: 'json/json',
plugins: { jsonPlugin },
extends: [jsonPlugin.configs.recommended],
},
{
files: ['**/*.md'], // MDX support awaits implementation https://github.com/eslint/markdown/issues/316
language: 'markdown/gfm',
plugins: { markdownPlugin },
extends: [markdownPlugin.configs.recommended],
},
compatPlugin.configs['flat/recommended'],
prettierConfig,
]);
Loading
Loading