mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
Create Storybook guideline and add addon-designs to embed Figma (#27310)
* Add foundations and migrations docs * Add storybook/addon-designs version 8.2.1 * Test Figma link * Refactor Modal stories * Create figmaDesignUrl * Create foundations * Create feature flags docs * Create Storybook builds docs * Add storybook/addon-designs version 8.2.1 * Test Figma link * Add an example of Story with split-tests within the Storybook guidelines (#27260) * Add FormatCurrency demo in feature-flags.mdx * Add syntax highlight to code samples * Update stories with figmaDesignUrl * Figma access token * Use OLButton * Hide control for children and footer * Add primitive colors * Use useSplitTest instead * Update cloud builds docs with `storybook-push-trigger` * Make Foundations the default story --------- Co-authored-by: Antoine Clausse <antoine.clausse@overleaf.com> GitOrigin-RevId: 0729759803f190d89cf543d087eea86265b725f1
This commit is contained in:
120
package-lock.json
generated
120
package-lock.json
generated
@@ -4912,6 +4912,30 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@figspec/components": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@figspec/components/-/components-1.0.3.tgz",
|
||||
"integrity": "sha512-fBwHzJ4ouuOUJEi+yBZIrOy+0/fAjB3AeTcIHTT1PRxLz8P63xwC7R0EsIJXhScIcc+PljGmqbbVJCjLsnaGYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lit": "^2.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@figspec/react": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@figspec/react/-/react-1.0.4.tgz",
|
||||
"integrity": "sha512-jaPvkIef4d6NjsRiw91OZabrfdPH9FtoPGYcY5mpXjYEcdUqIq1aHtLq3SkMVyVysEapTEJ6yS8amy93MyXBEQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@figspec/components": "^1.0.1",
|
||||
"@lit-labs/react": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/bigquery": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/bigquery/-/bigquery-5.10.0.tgz",
|
||||
@@ -6543,6 +6567,30 @@
|
||||
"@lezer/highlight": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit-labs/react": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/react/-/react-1.2.1.tgz",
|
||||
"integrity": "sha512-DiZdJYFU0tBbdQkfwwRSwYyI/mcWkg3sWesKRsHUd4G+NekTmmeq9fzsurvcKTNVa0comNljwtg4Hvi1ds3V+A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@lit-labs/ssr-dom-shim": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz",
|
||||
"integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
|
||||
"integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lukeed/csprng": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
|
||||
@@ -10288,6 +10336,40 @@
|
||||
"storybook": "^8.6.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-designs": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-designs/-/addon-designs-8.2.1.tgz",
|
||||
"integrity": "sha512-orwihs1D5alhh4Qu3BSJKbSgQOdSagvRX/25m5fYZQAaqVErBY0lRR4vCAU/G/STkcdv+MHwIQ5U+0kX5Tm2+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@figspec/react": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/blocks": "^8.0.0 || ^8.1.0-0 || ^8.2.0-0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0",
|
||||
"@storybook/components": "^8.0.0 || ^8.1.0-0 || ^8.2.0-0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0",
|
||||
"@storybook/theming": "^8.0.0 || ^8.1.0-0 || ^8.2.0-0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@storybook/blocks": {
|
||||
"optional": true
|
||||
},
|
||||
"@storybook/components": {
|
||||
"optional": true
|
||||
},
|
||||
"@storybook/theming": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-docs": {
|
||||
"version": "8.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.6.12.tgz",
|
||||
@@ -12605,8 +12687,7 @@
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "9.0.8",
|
||||
@@ -27787,6 +27868,40 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lit": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz",
|
||||
"integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.6.0",
|
||||
"lit-element": "^3.3.0",
|
||||
"lit-html": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-element": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz",
|
||||
"integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.1.0",
|
||||
"@lit/reactive-element": "^1.3.0",
|
||||
"lit-html": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-html": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz",
|
||||
"integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/load-script": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
|
||||
@@ -44516,6 +44631,7 @@
|
||||
"@replit/codemirror-vim": "overleaf/codemirror-vim#1bef138382d948018f3f9b8a4d7a70ab61774e4b",
|
||||
"@sentry/browser": "7.46.0",
|
||||
"@storybook/addon-a11y": "^8.6.12",
|
||||
"@storybook/addon-designs": "^8.2.1",
|
||||
"@storybook/addon-essentials": "^8.6.12",
|
||||
"@storybook/addon-interactions": "^8.6.12",
|
||||
"@storybook/addon-links": "^8.6.12",
|
||||
|
||||
@@ -19,12 +19,15 @@ const config: StorybookConfig = {
|
||||
stories: [
|
||||
path.join(rootDir, 'frontend/stories/**/*.stories.{js,jsx,ts,tsx}'),
|
||||
path.join(rootDir, 'modules/**/stories/**/*.stories.{js,jsx,ts,tsx}'),
|
||||
path.join(rootDir, 'frontend/stories/**/*.mdx'),
|
||||
path.join(rootDir, 'modules/**/stories/**/*.mdx'),
|
||||
],
|
||||
addons: [
|
||||
getAbsolutePath('@storybook/addon-links'),
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@storybook/addon-interactions'),
|
||||
getAbsolutePath('@storybook/addon-a11y'),
|
||||
getAbsolutePath('@storybook/addon-designs'),
|
||||
getAbsolutePath('@storybook/addon-webpack5-compiler-babel'),
|
||||
{
|
||||
name: getAbsolutePath('@storybook/addon-styling-webpack'),
|
||||
|
||||
@@ -131,7 +131,11 @@ const preview: Preview = {
|
||||
options: {
|
||||
storySort: {
|
||||
method: 'alphabetical',
|
||||
order: ['Shared'],
|
||||
order: [
|
||||
'Storybook Guideline',
|
||||
['Foundations', 'Storybook builds', 'Feature Flags'],
|
||||
'Shared',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
20
services/web/.storybook/utils/figma-design-url.ts
Normal file
20
services/web/.storybook/utils/figma-design-url.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/** Creates design parameters for a Storybook story conditionally.
|
||||
* Helper function to generate design parameters based on the presence of a Figma access token.
|
||||
* The benefit of the token is that it allows component inspection directly in Storybook.
|
||||
* If token is not available, it defaults to a basic Figma URL.
|
||||
* Token can be generated in your Figma account settings.
|
||||
* To copy URL: In your Figma file, click to select the specific component frame you want to display in Storybook.
|
||||
* It's important to select the outer frame of the component, not just a single layer inside it.
|
||||
*/
|
||||
|
||||
export const figmaDesignUrl = (url: string) => {
|
||||
const accessToken = process.env.STORYBOOK_FIGMA_ACCESS_TOKEN
|
||||
|
||||
const designConfig = accessToken
|
||||
? { type: 'figspec', url, accessToken }
|
||||
: { type: 'figma', url }
|
||||
|
||||
return {
|
||||
design: designConfig,
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Meta } from '@storybook/react'
|
||||
import _ from 'lodash'
|
||||
import { SplitTestContext } from '../../frontend/js/shared/context/split-test-context'
|
||||
import { SplitTestContext } from '@/shared/context/split-test-context'
|
||||
|
||||
export const splitTestsArgTypes = {
|
||||
export const defaultSplitTestsArgTypes = {
|
||||
// to be able to use this utility, you need to add the argTypes for each split test in this object
|
||||
// Check the original implementation for an example: https://github.com/overleaf/internal/pull/17809
|
||||
'editor-redesign': {
|
||||
@@ -14,10 +14,13 @@ export const splitTestsArgTypes = {
|
||||
},
|
||||
}
|
||||
|
||||
export const withSplitTests = (
|
||||
export const withSplitTests = <ArgTypes = typeof defaultSplitTestsArgTypes,>(
|
||||
story: Meta,
|
||||
splitTests: (keyof typeof splitTestsArgTypes)[] = []
|
||||
splitTests: (keyof ArgTypes)[] = [],
|
||||
/** @deprecated For demo purposes only. Add actual split tests in defaultSplitTestsArgTypes */
|
||||
_splitTestsArgTypes?: ArgTypes
|
||||
): Meta => {
|
||||
const splitTestsArgTypes = _splitTestsArgTypes ?? defaultSplitTestsArgTypes
|
||||
return {
|
||||
...story,
|
||||
argTypes: { ...story.argTypes, ..._.pick(splitTestsArgTypes, splitTests) },
|
||||
|
||||
24
services/web/frontend/stories/docs/cloud-builds.mdx
Normal file
24
services/web/frontend/stories/docs/cloud-builds.mdx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Meta } from '@storybook/blocks';
|
||||
|
||||
<Meta title="Storybook Guideline / Storybook builds" />
|
||||
|
||||
|
||||
# Cloud Builds
|
||||
|
||||
Storybook builds can be used to share your development work. They can be found at [https://storybook.dev-overleaf.com/](https://storybook.dev-overleaf.com/).
|
||||
|
||||
The naming scheme is predictable, i.e.: `https://storybook.dev-overleaf.com/<BRANCH_NAME>/`.
|
||||
|
||||
# Triggers
|
||||
|
||||
Storybook builds are automatically triggered for the main branch. For ad hoc builds of feature branches, the commits must be pushed to branches prefixed with `storybook-`.
|
||||
|
||||
For example, you may temporarily push your branch to a `storybook-` branch: `git push origin my-example-feature:storybook-my-example-feature`
|
||||
|
||||
You can delete it shortly after: `git push origin :storybook-my-example-feature`
|
||||
|
||||
Alternatively, **if you already have a branch**, but you would like to create a Storybook, you can manually trigger the `storybook-push-trigger` on your branch via [Google Cloud Build triggers](https://console.cloud.google.com/cloud-build/triggers?project=overleaf-dev).
|
||||
|
||||
Storybook builds take about 10 minutes to finish.
|
||||
|
||||
**Source:** [Storybook in the developer manual](https://manual.dev-overleaf.com/development/code/storybook/)
|
||||
40
services/web/frontend/stories/docs/feature-flags.mdx
Normal file
40
services/web/frontend/stories/docs/feature-flags.mdx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
||||
import * as FormatCurrency from './format-currency.stories'
|
||||
|
||||
<Meta title="Storybook Guideline / Feature flags" />
|
||||
|
||||
# Feature flags
|
||||
|
||||
You can wrap your story with the `withSplitTests` utility to add split test variants to your Storybook stories, so you can toggle feature flags directly in the Storybook UI. See [withSplitTests on GitHub](https://github.com/overleaf/internal/blob/main/services/web/.storybook/utils/with-split-tests.tsx).
|
||||
|
||||
1. Define your split test argTypes:
|
||||
Add your split test configurations to the `splitTestsArgTypes` object.
|
||||
|
||||
```js
|
||||
export const splitTestsArgTypes = {
|
||||
'local-ccy-format': {
|
||||
description: 'Use local currency formatting',
|
||||
control: { type: 'radio' },
|
||||
options: ['default', 'enabled'],
|
||||
},
|
||||
}
|
||||
```
|
||||
2. Wrap your story with `withSplitTests`.
|
||||
|
||||
Import `withSplitTests` and `Meta` from '@storybook/react' in your stories.
|
||||
|
||||
```js
|
||||
export default {
|
||||
...config,
|
||||
...withSplitTests(config, ['local-ccy-format']),
|
||||
}
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Resulting stories will have added controls to define the variants of the split tests.
|
||||
|
||||
<div>
|
||||
<Canvas of={FormatCurrency.Story} />
|
||||
<Controls of={FormatCurrency.Story} />
|
||||
</div>
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react'
|
||||
import { useSplitTest } from '@/shared/context/split-test-context'
|
||||
import { withSplitTests } from '../../../.storybook/utils/with-split-tests'
|
||||
|
||||
const FormatCurrency = () => {
|
||||
const { variant } = useSplitTest('local-ccy-format')
|
||||
const formatCurrency = (amount: number, narrowSymbol: boolean) => {
|
||||
return variant === 'enabled'
|
||||
? new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD',
|
||||
currencyDisplay: narrowSymbol ? 'narrowSymbol' : 'name',
|
||||
}).format(amount)
|
||||
: `USD ${amount}`
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<strong>Variant:</strong> {JSON.stringify(variant)}
|
||||
<br />
|
||||
<strong>Long:</strong> {formatCurrency(1234.56, false)}
|
||||
<br />
|
||||
<strong>Short:</strong> {formatCurrency(1234.56, true)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const config = {
|
||||
title: 'Storybook Guideline / Feature Flags', // Must match MDX title exactly
|
||||
component: FormatCurrency,
|
||||
}
|
||||
|
||||
export default {
|
||||
...config,
|
||||
...withSplitTests(config, ['local-ccy-format'], {
|
||||
'local-ccy-format': {
|
||||
description: 'Use local currency formatting',
|
||||
control: { type: 'radio' as const },
|
||||
options: ['default', 'enabled'],
|
||||
},
|
||||
}),
|
||||
tags: ['!dev'], // hides in the sidebar
|
||||
}
|
||||
|
||||
export const Story = {}
|
||||
234
services/web/frontend/stories/docs/foundations.mdx
Normal file
234
services/web/frontend/stories/docs/foundations.mdx
Normal file
@@ -0,0 +1,234 @@
|
||||
import { Meta, ColorItem, ColorPalette, Title, Typeset } from '@storybook/blocks';
|
||||
import colors from '../../stylesheets/bootstrap-5/foundations/tokens/colors.json';
|
||||
import typography from '../../stylesheets/bootstrap-5/foundations/tokens/typography.json';
|
||||
import borderRadius from '../../stylesheets/bootstrap-5/foundations/tokens/borderRadius.json';
|
||||
import spacing from '../../stylesheets/bootstrap-5/foundations/tokens/spacing.json';
|
||||
|
||||
<Meta title="Storybook Guideline / Foundations" />
|
||||
|
||||
# Foundations
|
||||
|
||||
Foundations in UX design are the basic rules and core elements, like colors, fonts, and spacing, that ensure consistency across the design.
|
||||
<p>
|
||||
These palettes are generated from our token files. The tokens were exported from Figma and split into separate files to categorise: <a href="https://github.com/overleaf/internal/tree/main/services/web/frontend/stylesheets/bootstrap-5/foundations/tokens" target="_blank" rel="noopener noreferrer">Token files on GitHub</a>
|
||||
</p>
|
||||
|
||||
**Table of Contents**
|
||||
- [Primitive colors](#primitive-colors)
|
||||
- [Background colors](#background-colors)
|
||||
- [Content colors](#content-colors)
|
||||
- [Border colors](#border-colors)
|
||||
- [Link colors](#link-colors)
|
||||
- [Special colors](#special-colors)
|
||||
- [Font weight](#font-weight)
|
||||
- [Font size](#font-size)
|
||||
- [Border radius](#border-radius)
|
||||
- [Spacing](#spacing)
|
||||
|
||||
# Colors
|
||||
<br/>
|
||||
|
||||
## Primitive colors
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors.PrimitiveColor).map(([name, color]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
colors={[color.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
## Background colors
|
||||
|
||||
Colors used for page and component backgrounds.
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors)
|
||||
.filter(([name]) => name.startsWith('bg-'))
|
||||
.map(([name, colors]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
subtitle={colors.$primitive}
|
||||
colors={[colors.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
## Content colors
|
||||
|
||||
Colors used for text and icons.
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors)
|
||||
.filter(([name]) => name.startsWith('content-'))
|
||||
.map(([name, colors]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
subtitle={colors.$primitive}
|
||||
colors={[colors.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
## Border colors
|
||||
|
||||
Colors used for borders and dividers.
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors)
|
||||
.filter(([name]) => name.startsWith('border-'))
|
||||
.map(([name, colors]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
subtitle={colors.$primitive}
|
||||
colors={[colors.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
## Link colors
|
||||
|
||||
Colors used for hyperlink states.
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors)
|
||||
.filter(([name]) => name.startsWith('link-'))
|
||||
.map(([name, colors]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
subtitle={colors.$primitive}
|
||||
colors={[colors.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
## Special colors
|
||||
|
||||
Colors used for specific UI elements like color pickers.
|
||||
|
||||
<ColorPalette>
|
||||
{Object.entries(colors)
|
||||
.filter(([name]) => name.startsWith('special-'))
|
||||
.map(([name, colors]) => (
|
||||
<ColorItem
|
||||
key={name}
|
||||
title={name}
|
||||
subtitle={colors.$primitive}
|
||||
colors={[colors.$value]}
|
||||
/>
|
||||
))}
|
||||
</ColorPalette>
|
||||
|
||||
# Typography
|
||||
<br/>
|
||||
|
||||
## Font weight
|
||||
<br/>
|
||||
|
||||
{Object.entries(typography.Fontweight).map(([name, typography]) => (
|
||||
<div key={name}>
|
||||
<strong>{name}</strong>
|
||||
<Typeset
|
||||
fontSizes={[14]}
|
||||
fontWeight={typography.$value}
|
||||
sampleText="The quick brown fox jumps over the lazy dog"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
## Font size
|
||||
<br/>
|
||||
|
||||
{Object.entries(typography['Fontsize']).map(([name, typography]) => {
|
||||
const mixins = typography.$mixin ? [].concat(typography.$mixin) : [];
|
||||
|
||||
return (
|
||||
<div key={name} style={{ marginBottom: '2rem' }}>
|
||||
<strong>
|
||||
{name}
|
||||
{mixins.map(mixin => (
|
||||
<span key={mixin}> / @mixin {mixin}</span>
|
||||
))}
|
||||
</strong>
|
||||
<Typeset
|
||||
fontSizes={[`${typography.$value}px`]}
|
||||
fontWeight={500}
|
||||
sampleText="The quick brown fox jumps over the lazy dog"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
## Border radius
|
||||
<br/>
|
||||
|
||||
<table style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Variable name</th>
|
||||
<th>Value</th>
|
||||
<th style={{ textAlign: 'center' }}>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.entries(borderRadius['BorderRadius']).map(([name, borderRadius]) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<strong>{name}</strong>
|
||||
</td>
|
||||
<td style={{ textAlign: 'center' }}>{borderRadius.$value}px</td>
|
||||
<td style={{ textAlign: 'center', padding: '0.5rem' }}>
|
||||
<div
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
borderRadius: `${borderRadius.$value}px`,
|
||||
backgroundColor: '#098842',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Spacing
|
||||
<br/>
|
||||
|
||||
<table style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
<th>Value</th>
|
||||
<th style={{ textAlign: 'left', paddingLeft: '1rem' }}>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.entries(spacing.Spacing)
|
||||
.filter(([, spacing]) => spacing.$value > 0)
|
||||
.map(([name, spacing]) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<strong>{name}</strong>
|
||||
</td>
|
||||
<td style={{ textAlign: 'center' }}>{spacing.$value}px</td>
|
||||
<td style={{ padding: '0.5rem 1rem', verticalAlign: 'middle' }}>
|
||||
<div
|
||||
style={{
|
||||
height: `${spacing.$value}px`,
|
||||
width: '100%',
|
||||
backgroundColor: '#098842',
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -1,140 +1,80 @@
|
||||
import Button from '@/shared/components/button/button'
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import { figmaDesignUrl } from './../../../.storybook/utils/figma-design-url'
|
||||
import OLModal, {
|
||||
OLModalHeader,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalTitle,
|
||||
} from '@/shared/components/ol/ol-modal'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
|
||||
type Story = StoryObj<typeof OLModal>
|
||||
|
||||
export const Default: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Heading</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>
|
||||
Lorem ipsum dolor sit lorem a amet, consectetur adipiscing elit, sed
|
||||
do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
||||
enim ad minim veniam.
|
||||
</p>
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<Button variant="secondary">Cancel</Button>
|
||||
<Button variant="primary">Primary</Button>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
args: {
|
||||
title: 'Heading',
|
||||
children: (
|
||||
<p>
|
||||
Always use the modal actions in the footer and use descriptive words for
|
||||
them.
|
||||
</p>
|
||||
),
|
||||
footer: (
|
||||
<>
|
||||
<OLButton variant="secondary">Cancel</OLButton>
|
||||
<OLButton variant="primary">Primary</OLButton>
|
||||
</>
|
||||
),
|
||||
},
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?m=auto&node-id=3488-82657&m=dev'
|
||||
),
|
||||
}
|
||||
|
||||
export const Informative: Story = {
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?m=auto&node-id=3488-86576&m=dev'
|
||||
),
|
||||
args: {
|
||||
title: 'Informative',
|
||||
children: (
|
||||
<p>
|
||||
Presents information for the user to be aware of and doesn’t require any
|
||||
action.
|
||||
</p>
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
export const ModalWithAcknowledgment: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Acknowledgment</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>
|
||||
System requires an acknowledgment from the user. Usually contains
|
||||
only one primary button.
|
||||
</p>
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<Button variant="primary">Accept</Button>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
export const Acknowledgment: Story = {
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?m=auto&node-id=3488-86581&m=dev'
|
||||
),
|
||||
args: {
|
||||
title: 'Acknowledgment',
|
||||
children: (
|
||||
<p>
|
||||
System requires an acknowledgment from the user. Usually contains only
|
||||
one primary button.
|
||||
</p>
|
||||
),
|
||||
footer: <OLButton variant="primary">Accept</OLButton>,
|
||||
},
|
||||
}
|
||||
|
||||
export const ModalWithSecondary: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Heading</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>
|
||||
Lorem ipsum dolor sit lorem a amet, consectetur adipiscing elit, sed
|
||||
do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
||||
enim ad minim veniam.
|
||||
</p>
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<Button variant="secondary">Cancel</Button>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const ModalWithTertiary: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Heading</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>Used for destructive or irreversible actions.</p>
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<Button variant="secondary">Third</Button>
|
||||
<Button variant="secondary" className="ms-auto">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary">Primary</Button>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const ModalInformative: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Informative</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>
|
||||
Presents information for the user to be aware of and doesn’t require
|
||||
any action.
|
||||
</p>
|
||||
</OLModalBody>
|
||||
</OLModal>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const ModalDanger: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<OLModal show {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>Danger</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
<p>
|
||||
Lorem ipsum dolor sit lorem a amet, consectetur adipiscing elit, sed
|
||||
do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
||||
enim ad minim veniam.
|
||||
</p>
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<Button variant="secondary">Cancel</Button>
|
||||
<Button variant="danger">Delete</Button>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
export const Danger: Story = {
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?m=auto&node-id=3488-86586&m=dev'
|
||||
),
|
||||
args: {
|
||||
title: 'Danger',
|
||||
children: <p>Used for destructive or irreversible actions.</p>,
|
||||
footer: (
|
||||
<>
|
||||
<OLButton variant="secondary">Cancel</OLButton>
|
||||
<OLButton variant="danger">Delete</OLButton>
|
||||
</>
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -146,7 +86,24 @@ const meta: Meta<typeof OLModal> = {
|
||||
control: 'radio',
|
||||
options: ['lg', 'md', 'sm'],
|
||||
},
|
||||
title: { control: 'text' },
|
||||
children: { control: false },
|
||||
footer: { control: false },
|
||||
},
|
||||
args: {
|
||||
show: true,
|
||||
size: 'sm',
|
||||
onHide: () => {},
|
||||
},
|
||||
render: ({ title, children, footer, ...args }) => (
|
||||
<OLModal {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>{children}</OLModalBody>
|
||||
{footer && <OLModalFooter>{footer}</OLModalFooter>}
|
||||
</OLModal>
|
||||
),
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Badge from '@/shared/components/badge/badge'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import classnames from 'classnames'
|
||||
import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
|
||||
import Badge from '@/shared/components/badge/badge'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
const meta: Meta<typeof Badge> = {
|
||||
title: 'Shared / Components / Badge',
|
||||
@@ -31,20 +32,27 @@ export default meta
|
||||
type Story = StoryObj<typeof Badge>
|
||||
|
||||
export const BadgeDefault: Story = {
|
||||
render: args => {
|
||||
return (
|
||||
<Badge
|
||||
className={classnames({ 'text-dark': args.bg === 'light' })}
|
||||
{...args}
|
||||
/>
|
||||
)
|
||||
args: {
|
||||
bg: meta.argTypes!.bg!.options![0],
|
||||
},
|
||||
}
|
||||
BadgeDefault.args = {
|
||||
bg: meta.argTypes!.bg!.options![0],
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?node-id=3458-9502&m=dev'
|
||||
),
|
||||
render: args => (
|
||||
<Badge
|
||||
className={classnames({ 'text-dark': args.bg === 'light' })}
|
||||
{...args}
|
||||
/>
|
||||
),
|
||||
}
|
||||
|
||||
export const BadgePrepend: Story = {
|
||||
args: {
|
||||
bg: meta.argTypes!.bg!.options![0],
|
||||
},
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?node-id=3458-11319&m=dev'
|
||||
),
|
||||
render: args => {
|
||||
return (
|
||||
<Badge
|
||||
@@ -55,6 +63,3 @@ export const BadgePrepend: Story = {
|
||||
)
|
||||
},
|
||||
}
|
||||
BadgePrepend.args = {
|
||||
bg: meta.argTypes!.bg!.options![0],
|
||||
}
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import Button from '@/shared/components/button/button'
|
||||
import { Meta } from '@storybook/react'
|
||||
import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
|
||||
type Args = React.ComponentProps<typeof Button>
|
||||
type Args = React.ComponentProps<typeof OLButton>
|
||||
|
||||
export const NewButton = (args: Args) => {
|
||||
return <Button {...args} />
|
||||
return <OLButton {...args} />
|
||||
}
|
||||
|
||||
export const ButtonWithLeadingIcon = (args: Args) => {
|
||||
return <Button leadingIcon="add" {...args} />
|
||||
return <OLButton leadingIcon="add" {...args} />
|
||||
}
|
||||
|
||||
export const ButtonWithTrailingIcon = (args: Args) => {
|
||||
return <Button trailingIcon="add" {...args} />
|
||||
return <OLButton trailingIcon="add" {...args} />
|
||||
}
|
||||
|
||||
export const ButtonWithIcons = (args: Args) => {
|
||||
return <Button trailingIcon="add" leadingIcon="add" {...args} />
|
||||
return <OLButton trailingIcon="add" leadingIcon="add" {...args} />
|
||||
}
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
const meta: Meta<typeof OLButton> = {
|
||||
title: 'Shared / Components / Button',
|
||||
component: Button,
|
||||
component: OLButton,
|
||||
args: {
|
||||
children: 'A Button',
|
||||
disabled: false,
|
||||
@@ -30,7 +31,7 @@ const meta: Meta<typeof Button> = {
|
||||
argTypes: {
|
||||
size: {
|
||||
control: 'radio',
|
||||
options: ['small', 'default', 'large'],
|
||||
options: ['lg', 'md', 'sm'],
|
||||
},
|
||||
variant: {
|
||||
control: 'radio',
|
||||
@@ -42,9 +43,13 @@ const meta: Meta<typeof Button> = {
|
||||
'danger-ghost',
|
||||
'premium',
|
||||
'premium-secondary',
|
||||
'link',
|
||||
],
|
||||
},
|
||||
},
|
||||
parameters: figmaDesignUrl(
|
||||
'https://www.figma.com/design/V7Ogph1Ocs4ux2A4WMNAh7/Overleaf---Components?node-id=3458-22412&m=dev'
|
||||
),
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"BorderRadius": {
|
||||
"border-radius-none": {
|
||||
"$type": "number",
|
||||
"$value": 0
|
||||
},
|
||||
"border-radius-base": {
|
||||
"$type": "number",
|
||||
"$value": 4
|
||||
},
|
||||
"border-radius-medium": {
|
||||
"$type": "number",
|
||||
"$value": 8
|
||||
},
|
||||
"border-radius-large": {
|
||||
"$type": "number",
|
||||
"$value": 16
|
||||
},
|
||||
"border-radius-full": {
|
||||
"$type": "number",
|
||||
"$value": 9999
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
{
|
||||
"PrimitiveColor": {
|
||||
"white": {
|
||||
"$type": "color",
|
||||
"$value": "#fff",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-10": {
|
||||
"$type": "color",
|
||||
"$value": "#f4f5f6",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-20": {
|
||||
"$type": "color",
|
||||
"$value": "#e7e9ee",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-30": {
|
||||
"$type": "color",
|
||||
"$value": "#d0d5dd",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-40": {
|
||||
"$type": "color",
|
||||
"$value": "#afb5c0",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-50": {
|
||||
"$type": "color",
|
||||
"$value": "#8d96a5",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-60": {
|
||||
"$type": "color",
|
||||
"$value": "#677283",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-70": {
|
||||
"$type": "color",
|
||||
"$value": "#495365",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-80": {
|
||||
"$type": "color",
|
||||
"$value": "#2f3a4c",
|
||||
"$primitive": null
|
||||
},
|
||||
"neutral-90": {
|
||||
"$type": "color",
|
||||
"$value": "#1b222c",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-10": {
|
||||
"$type": "color",
|
||||
"$value": "#eaf6ef",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-20": {
|
||||
"$type": "color",
|
||||
"$value": "#b8dbc8",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-30": {
|
||||
"$type": "color",
|
||||
"$value": "#86caa5",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-40": {
|
||||
"$type": "color",
|
||||
"$value": "#53b57f",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-50": {
|
||||
"$type": "color",
|
||||
"$value": "#098842",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-60": {
|
||||
"$type": "color",
|
||||
"$value": "#1e6b41",
|
||||
"$primitive": null
|
||||
},
|
||||
"green-70": {
|
||||
"$type": "color",
|
||||
"$value": "#195936",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-10": {
|
||||
"$type": "color",
|
||||
"$value": "#f1f4f9",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-20": {
|
||||
"$type": "color",
|
||||
"$value": "#c3d0e3",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-30": {
|
||||
"$type": "color",
|
||||
"$value": "#97b6e5",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-40": {
|
||||
"$type": "color",
|
||||
"$value": "#6597e0",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-50": {
|
||||
"$type": "color",
|
||||
"$value": "#366cbf",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-60": {
|
||||
"$type": "color",
|
||||
"$value": "#28518f",
|
||||
"$primitive": null
|
||||
},
|
||||
"blue-70": {
|
||||
"$type": "color",
|
||||
"$value": "#214475",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-10": {
|
||||
"$type": "color",
|
||||
"$value": "#f9f1f1",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-20": {
|
||||
"$type": "color",
|
||||
"$value": "#f5beba",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-30": {
|
||||
"$type": "color",
|
||||
"$value": "#e59d9a",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-40": {
|
||||
"$type": "color",
|
||||
"$value": "#e36d66",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-50": {
|
||||
"$type": "color",
|
||||
"$value": "#b83a33",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-60": {
|
||||
"$type": "color",
|
||||
"$value": "#942f2a",
|
||||
"$primitive": null
|
||||
},
|
||||
"red-70": {
|
||||
"$type": "color",
|
||||
"$value": "#782722",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-10": {
|
||||
"$type": "color",
|
||||
"$value": "#fcf1e3",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-20": {
|
||||
"$type": "color",
|
||||
"$value": "#fcc483",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-30": {
|
||||
"$type": "color",
|
||||
"$value": "#f7a445",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-40": {
|
||||
"$type": "color",
|
||||
"$value": "#de8014",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-50": {
|
||||
"$type": "color",
|
||||
"$value": "#8f5514",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-60": {
|
||||
"$type": "color",
|
||||
"$value": "#7a4304",
|
||||
"$primitive": null
|
||||
},
|
||||
"yellow-70": {
|
||||
"$type": "color",
|
||||
"$value": "#633a0b",
|
||||
"$primitive": null
|
||||
}
|
||||
},
|
||||
"special-neutral": {
|
||||
"$type": "color",
|
||||
"$value": "#a7b1c2",
|
||||
"$primitive": "Neutral"
|
||||
},
|
||||
"special-red": {
|
||||
"$type": "color",
|
||||
"$value": "#f04343",
|
||||
"$primitive": "Red"
|
||||
},
|
||||
"special-orange": {
|
||||
"$type": "color",
|
||||
"$value": "#dd8a3e",
|
||||
"$primitive": "Orange"
|
||||
},
|
||||
"special-yellow": {
|
||||
"$type": "color",
|
||||
"$value": "#e4ca3e",
|
||||
"$primitive": "Yellow"
|
||||
},
|
||||
"special-green": {
|
||||
"$type": "color",
|
||||
"$value": "#33cf67",
|
||||
"$primitive": "Green"
|
||||
},
|
||||
"special-lightblue": {
|
||||
"$type": "color",
|
||||
"$value": "#43a7f0",
|
||||
"$primitive": "LightBlue"
|
||||
},
|
||||
"special-blue": {
|
||||
"$type": "color",
|
||||
"$value": "#434af0",
|
||||
"$primitive": "Blue"
|
||||
},
|
||||
"special-violet": {
|
||||
"$type": "color",
|
||||
"$value": "#b943f0",
|
||||
"$primitive": "Violet"
|
||||
},
|
||||
"special-pink": {
|
||||
"$type": "color",
|
||||
"$value": "#ff4bcd",
|
||||
"$primitive": "Pink"
|
||||
},
|
||||
"bg-light-primary": {
|
||||
"$type": "color",
|
||||
"$value": "#ffffff",
|
||||
"$primitive": "white"
|
||||
},
|
||||
"bg-light-secondary": {
|
||||
"$type": "color",
|
||||
"$value": "#f4f5f6",
|
||||
"$primitive": "neutral-10"
|
||||
},
|
||||
"bg-light-tertiary": {
|
||||
"$type": "color",
|
||||
"$value": "#e7e9ee",
|
||||
"$primitive": "neutral-20"
|
||||
},
|
||||
"bg-light-disabled": {
|
||||
"$type": "color",
|
||||
"$value": "#e7e9ee",
|
||||
"$primitive": "neutral-20"
|
||||
},
|
||||
"bg-dark-primary": {
|
||||
"$type": "color",
|
||||
"$value": "#1b222c",
|
||||
"$primitive": "neutral-90"
|
||||
},
|
||||
"bg-dark-secondary": {
|
||||
"$type": "color",
|
||||
"$value": "#2f3a4c",
|
||||
"$primitive": "neutral-80"
|
||||
},
|
||||
"bg-dark-tertiary": {
|
||||
"$type": "color",
|
||||
"$value": "#495365",
|
||||
"$primitive": "neutral-70"
|
||||
},
|
||||
"bg-dark-disabled": {
|
||||
"$type": "color",
|
||||
"$value": "#495365",
|
||||
"$primitive": "neutral-70"
|
||||
},
|
||||
"bg-accent-01": {
|
||||
"$type": "color",
|
||||
"$value": "#098842",
|
||||
"$primitive": "green-50"
|
||||
},
|
||||
"bg-accent-02": {
|
||||
"$type": "color",
|
||||
"$value": "#1e6b41",
|
||||
"$primitive": "green-60"
|
||||
},
|
||||
"bg-accent-03": {
|
||||
"$type": "color",
|
||||
"$value": "#eaf6ef",
|
||||
"$primitive": "green-10"
|
||||
},
|
||||
"bg-danger-01": {
|
||||
"$type": "color",
|
||||
"$value": "#b83a33",
|
||||
"$primitive": "red-50"
|
||||
},
|
||||
"bg-danger-02": {
|
||||
"$type": "color",
|
||||
"$value": "#942f2a",
|
||||
"$primitive": "red-60"
|
||||
},
|
||||
"bg-danger-03": {
|
||||
"$type": "color",
|
||||
"$value": "#f9f1f1",
|
||||
"$primitive": "red-10"
|
||||
},
|
||||
"bg-warning-01": {
|
||||
"$type": "color",
|
||||
"$value": "#8f5514",
|
||||
"$primitive": "yellow-50"
|
||||
},
|
||||
"bg-warning-02": {
|
||||
"$type": "color",
|
||||
"$value": "#7a4304",
|
||||
"$primitive": "yellow-60"
|
||||
},
|
||||
"bg-warning-03": {
|
||||
"$type": "color",
|
||||
"$value": "#fcf1e3",
|
||||
"$primitive": "yellow-10"
|
||||
},
|
||||
"bg-info-01": {
|
||||
"$type": "color",
|
||||
"$value": "#366cbf",
|
||||
"$primitive": "blue-50"
|
||||
},
|
||||
"bg-info-02": {
|
||||
"$type": "color",
|
||||
"$value": "#28518f",
|
||||
"$primitive": "blue-60"
|
||||
},
|
||||
"bg-info-03": {
|
||||
"$type": "color",
|
||||
"$value": "#f1f4f9",
|
||||
"$primitive": "blue-10"
|
||||
},
|
||||
"content-primary": {
|
||||
"$type": "color",
|
||||
"$value": "#1b222c",
|
||||
"$primitive": "neutral-90"
|
||||
},
|
||||
"content-secondary": {
|
||||
"$type": "color",
|
||||
"$value": "#495365",
|
||||
"$primitive": "neutral-70"
|
||||
},
|
||||
"content-disabled": {
|
||||
"$type": "color",
|
||||
"$value": "#afb5c0",
|
||||
"$primitive": "neutral-40"
|
||||
},
|
||||
"content-placeholder": {
|
||||
"$type": "color",
|
||||
"$value": "#677283",
|
||||
"$primitive": "neutral-60"
|
||||
},
|
||||
"content-danger": {
|
||||
"$type": "color",
|
||||
"$value": "#b83a33",
|
||||
"$primitive": "red-50"
|
||||
},
|
||||
"content-warning": {
|
||||
"$type": "color",
|
||||
"$value": "#8f5514",
|
||||
"$primitive": "yellow-50"
|
||||
},
|
||||
"content-positive": {
|
||||
"$type": "color",
|
||||
"$value": "#098842",
|
||||
"$primitive": "green-50"
|
||||
},
|
||||
"content-info": {
|
||||
"$type": "color",
|
||||
"$value": "#366cbf",
|
||||
"$primitive": "blue-50"
|
||||
},
|
||||
"border-primary": {
|
||||
"$type": "color",
|
||||
"$value": "#677283",
|
||||
"$primitive": "neutral-60"
|
||||
},
|
||||
"border-hover": {
|
||||
"$type": "color",
|
||||
"$value": "#495365",
|
||||
"$primitive": "neutral-70"
|
||||
},
|
||||
"border-disabled": {
|
||||
"$type": "color",
|
||||
"$value": "#e7e9ee",
|
||||
"$primitive": "neutral-20"
|
||||
},
|
||||
"border-danger": {
|
||||
"$type": "color",
|
||||
"$value": "#b83a33",
|
||||
"$primitive": "red-50"
|
||||
},
|
||||
"border-divider": {
|
||||
"$type": "color",
|
||||
"$value": "#e7e9ee",
|
||||
"$primitive": "neutral-20"
|
||||
},
|
||||
"border-active": {
|
||||
"$type": "color",
|
||||
"$value": "#366cbf",
|
||||
"$primitive": "blue-50"
|
||||
},
|
||||
"link-web": {
|
||||
"$type": "color",
|
||||
"$value": "#1e6b41",
|
||||
"$primitive": "green-60"
|
||||
},
|
||||
"link-web-hover": {
|
||||
"$type": "color",
|
||||
"$value": "#195936",
|
||||
"$primitive": "green-70"
|
||||
},
|
||||
"link-web-visited": {
|
||||
"$type": "color",
|
||||
"$value": "#1e6b41",
|
||||
"$primitive": "green-60"
|
||||
},
|
||||
"link-ui": {
|
||||
"$type": "color",
|
||||
"$value": "#366cbf",
|
||||
"$primitive": "blue-50"
|
||||
},
|
||||
"link-ui-hover": {
|
||||
"$type": "color",
|
||||
"$value": "#28518f",
|
||||
"$primitive": "blue-60"
|
||||
},
|
||||
"link-ui-visited": {
|
||||
"$type": "color",
|
||||
"$value": "#28518f",
|
||||
"$primitive": "blue-60"
|
||||
},
|
||||
"hover-interaction": {
|
||||
"$type": "color",
|
||||
"$value": "rgba(27, 34, 44, 0.0800)",
|
||||
"$primitive": null
|
||||
},
|
||||
"overlay": {
|
||||
"$type": "color",
|
||||
"$value": "rgba(27, 34, 44, 0.8000)",
|
||||
"$primitive": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"Spacing": {
|
||||
"spacing-00": {
|
||||
"$type": "number",
|
||||
"$value": 0
|
||||
},
|
||||
"spacing-01": {
|
||||
"$type": "number",
|
||||
"$value": 2
|
||||
},
|
||||
"spacing-02": {
|
||||
"$type": "number",
|
||||
"$value": 4
|
||||
},
|
||||
"spacing-03": {
|
||||
"$type": "number",
|
||||
"$value": 6
|
||||
},
|
||||
"spacing-04": {
|
||||
"$type": "number",
|
||||
"$value": 8
|
||||
},
|
||||
"spacing-05": {
|
||||
"$type": "number",
|
||||
"$value": 12
|
||||
},
|
||||
"spacing-06": {
|
||||
"$type": "number",
|
||||
"$value": 16
|
||||
},
|
||||
"spacing-07": {
|
||||
"$type": "number",
|
||||
"$value": 20
|
||||
},
|
||||
"spacing-08": {
|
||||
"$type": "number",
|
||||
"$value": 24
|
||||
},
|
||||
"spacing-09": {
|
||||
"$type": "number",
|
||||
"$value": 32
|
||||
},
|
||||
"spacing-10": {
|
||||
"$type": "number",
|
||||
"$value": 40
|
||||
},
|
||||
"spacing-11": {
|
||||
"$type": "number",
|
||||
"$value": 48
|
||||
},
|
||||
"spacing-12": {
|
||||
"$type": "number",
|
||||
"$value": 56
|
||||
},
|
||||
"spacing-13": {
|
||||
"$type": "number",
|
||||
"$value": 64
|
||||
},
|
||||
"spacing-14": {
|
||||
"$type": "number",
|
||||
"$value": 72
|
||||
},
|
||||
"spacing-15": {
|
||||
"$type": "number",
|
||||
"$value": 80
|
||||
},
|
||||
"spacing-16": {
|
||||
"$type": "number",
|
||||
"$value": 96
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"Fontweight": {
|
||||
"font-weight-regular": {
|
||||
"$type": "number",
|
||||
"$value": 400
|
||||
},
|
||||
"font-weight-medium": {
|
||||
"$type": "number",
|
||||
"$value": 500
|
||||
},
|
||||
"font-weight-semibold": {
|
||||
"$type": "number",
|
||||
"$value": 600
|
||||
}
|
||||
},
|
||||
"Fontsize": {
|
||||
"font-size-01": {
|
||||
"$type": "number",
|
||||
"$value": 12,
|
||||
"$mixin": "body-xs"
|
||||
},
|
||||
"font-size-02": {
|
||||
"$type": "number",
|
||||
"$value": 14,
|
||||
"$mixin": "body-sm"
|
||||
},
|
||||
"font-size-03": {
|
||||
"$type": "number",
|
||||
"$value": 16,
|
||||
"$mixin": "body-base"
|
||||
},
|
||||
"font-size-04": {
|
||||
"$type": "number",
|
||||
"$value": 18,
|
||||
"$mixin": ["body-lg", "heading-xs"]
|
||||
},
|
||||
"font-size-05": {
|
||||
"$type": "number",
|
||||
"$value": 20,
|
||||
"$mixin": "heading-sm"
|
||||
},
|
||||
"font-size-06": {
|
||||
"$type": "number",
|
||||
"$value": 24,
|
||||
"$mixin": "heading-md"
|
||||
},
|
||||
"font-size-07": {
|
||||
"$type": "number",
|
||||
"$value": 30,
|
||||
"$mixin": "heading-lg"
|
||||
},
|
||||
"font-size-08": {
|
||||
"$type": "number",
|
||||
"$value": 36,
|
||||
"$mixin": "heading-xl"
|
||||
},
|
||||
"font-size-09": {
|
||||
"$type": "number",
|
||||
"$value": 48,
|
||||
"$mixin": "heading-2xl"
|
||||
},
|
||||
"font-size-10": {
|
||||
"$type": "number",
|
||||
"$value": 52,
|
||||
"$mixin": "display-xs"
|
||||
},
|
||||
"font-size-11": {
|
||||
"$type": "number",
|
||||
"$value": 60,
|
||||
"$mixin": "display-sm"
|
||||
},
|
||||
"font-size-12": {
|
||||
"$type": "number",
|
||||
"$value": 72,
|
||||
"$mixin": "display-md"
|
||||
},
|
||||
"font-size-13": {
|
||||
"$type": "number",
|
||||
"$value": 96,
|
||||
"$mixin": "display-lg"
|
||||
}
|
||||
},
|
||||
"Lineheight": {
|
||||
"line-height-01": {
|
||||
"$type": "number",
|
||||
"$value": 16
|
||||
},
|
||||
"line-height-02": {
|
||||
"$type": "number",
|
||||
"$value": 20
|
||||
},
|
||||
"line-height-03": {
|
||||
"$type": "number",
|
||||
"$value": 24
|
||||
},
|
||||
"line-height-04": {
|
||||
"$type": "number",
|
||||
"$value": 28
|
||||
},
|
||||
"line-height-05": {
|
||||
"$type": "number",
|
||||
"$value": 32
|
||||
},
|
||||
"line-height-06": {
|
||||
"$type": "number",
|
||||
"$value": 40
|
||||
},
|
||||
"line-height-07": {
|
||||
"$type": "number",
|
||||
"$value": 48
|
||||
},
|
||||
"line-height-08": {
|
||||
"$type": "number",
|
||||
"$value": 64
|
||||
},
|
||||
"line-height-09": {
|
||||
"$type": "number",
|
||||
"$value": 68
|
||||
},
|
||||
"line-height-10": {
|
||||
"$type": "number",
|
||||
"$value": 80
|
||||
},
|
||||
"line-height-11": {
|
||||
"$type": "number",
|
||||
"$value": 96
|
||||
},
|
||||
"line-height-12": {
|
||||
"$type": "number",
|
||||
"$value": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +218,7 @@
|
||||
"@replit/codemirror-vim": "overleaf/codemirror-vim#1bef138382d948018f3f9b8a4d7a70ab61774e4b",
|
||||
"@sentry/browser": "7.46.0",
|
||||
"@storybook/addon-a11y": "^8.6.12",
|
||||
"@storybook/addon-designs": "^8.2.1",
|
||||
"@storybook/addon-essentials": "^8.6.12",
|
||||
"@storybook/addon-interactions": "^8.6.12",
|
||||
"@storybook/addon-links": "^8.6.12",
|
||||
|
||||
Reference in New Issue
Block a user