diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-10-13 19:32:56 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:14:41 +0100 |
| commit | 006b15b467a5cd835a6eab1b49023100bdc8f2e6 (patch) | |
| tree | 949c7295c2e206f42357f135bab4696ddf6576ec /src/components/molecules/layout | |
| parent | 00f147a7a687d5772bcc538bc606cfff972178cd (diff) | |
refactor(components): rewrite Code component and usePrism hook
* move Prism styles to Sass placeholders to avoid repeats
* let usePrism consumer define its plugins (remove default ones)
* remove `plugins` prop from Code component
* add new props to Code component to let consumer configure plugins
(and handle plugin list from the given options)
However there are some problems with Prism plugins: line-highlight and
treeview does not seems to be loaded. I don't want to use Babel instead
of SWC so I have no solution for now.
Diffstat (limited to 'src/components/molecules/layout')
| -rw-r--r-- | src/components/molecules/layout/code.module.scss | 305 | ||||
| -rw-r--r-- | src/components/molecules/layout/code.stories.tsx | 121 | ||||
| -rw-r--r-- | src/components/molecules/layout/code.test.tsx | 17 | ||||
| -rw-r--r-- | src/components/molecules/layout/code.tsx | 69 | ||||
| -rw-r--r-- | src/components/molecules/layout/index.ts | 1 |
5 files changed, 0 insertions, 513 deletions
diff --git a/src/components/molecules/layout/code.module.scss b/src/components/molecules/layout/code.module.scss deleted file mode 100644 index 2eaf9a2..0000000 --- a/src/components/molecules/layout/code.module.scss +++ /dev/null @@ -1,305 +0,0 @@ -@use "../../../styles/abstracts/functions" as fun; -@use "../../../styles/abstracts/mixins" as mix; - -.wrapper { - :global { - .code-toolbar { - --toolbar-height: #{fun.convert-px(100)}; - - position: relative; - margin-top: calc(var(--toolbar-height) + var(--spacing-sm)); - - @include mix.media("screen") { - @include mix.dimensions("2xs") { - --toolbar-height: #{fun.convert-px(60)}; - } - } - - .toolbar { - display: flex; - flex-flow: row wrap; - justify-content: center; - width: 100%; - height: var(--toolbar-height); - position: absolute; - top: calc(var(--toolbar-height) * -1); - left: 0; - right: 0; - background: var(--color-bg-tertiary); - border: fun.convert-px(1) solid var(--color-border); - } - - .toolbar-item { - display: flex; - align-items: center; - margin: 0 var(--spacing-2xs); - } - - .toolbar-item:nth-child(1) { - flex: 0 0 100%; - justify-content: center; - margin: 0 auto 0 0; - padding: 0 var(--spacing-sm); - background: var(--color-bg-code); - border-bottom: fun.convert-px(1) solid var(--color-border); - color: var(--color-primary-darker); - font-size: var(--font-size-sm); - font-weight: 600; - - @include mix.media("screen") { - @include mix.dimensions("2xs") { - flex: 0 0 auto; - justify-content: left; - border-bottom: none; - border-right: fun.convert-px(1) solid var(--color-border); - } - } - } - } - - .copy-to-clipboard-button, - .prism-color-scheme-button { - display: block; - padding: fun.convert-px(3) var(--spacing-xs); - background: var(--color-bg); - border: 0.4ex solid var(--color-primary); - border-radius: fun.convert-px(30); - box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1) - var(--color-shadow), - fun.convert-px(1) fun.convert-px(2) fun.convert-px(2) fun.convert-px(-2) - var(--color-shadow), - fun.convert-px(3) fun.convert-px(4) fun.convert-px(5) fun.convert-px(-4) - var(--color-shadow); - color: var(--color-primary); - font-size: var(--font-size-sm); - font-weight: 600; - transition: all 0.35s ease-in-out 0s; - - &:hover, - &:focus { - transform: translateX(#{fun.convert-px(-2)}) - translateY(#{fun.convert-px(-2)}); - box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1) - var(--color-shadow-light), - fun.convert-px(1) fun.convert-px(2) fun.convert-px(2) - fun.convert-px(-2) var(--color-shadow-light), - fun.convert-px(3) fun.convert-px(4) fun.convert-px(5) - fun.convert-px(-4) var(--color-shadow-light), - fun.convert-px(4) fun.convert-px(7) fun.convert-px(8) - fun.convert-px(-3) var(--color-shadow-light); - } - - &:focus { - text-decoration: underline var(--color-primary) fun.convert-px(3); - } - - &:active { - text-decoration: none; - transform: translateY(#{fun.convert-px(2)}); - box-shadow: 0 0 0 0 var(--color-shadow); - } - } - - pre[class*="language-"] { - --gutter-size-with-spacing: calc(var(--gutter-size) + var(--spacing-xs)); - - position: relative; - overflow: auto; - background: var(--color-bg-secondary); - border: fun.convert-px(1) solid var(--color-border-light); - color: var(--color-fg); - hyphens: none; - tab-size: 4; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - - &.command-line { - --gutter-size: 19ch; - padding-left: var(--gutter-size-with-spacing); - } - - &.line-numbers { - --gutter-size: 6ch; - - counter-reset: lineNumber; - padding-left: var(--gutter-size-with-spacing); - } - - code { - display: block; - padding: var(--spacing-xs) 0; - position: relative; - } - - .line-numbers-rows, - .command-line-prompt { - display: block; - width: var(--gutter-size); - padding: var(--spacing-xs) 0; - position: absolute; - top: 0; - left: calc(var(--gutter-size-with-spacing) * -1); - background: var(--color-bg); - border-right: fun.convert-px(1) solid var(--color-border); - font-size: 100%; - letter-spacing: -1px; - text-align: right; - pointer-events: none; - user-select: none; - - > span { - &::before { - display: block; - padding-right: var(--spacing-xs); - color: var(--color-fg-light); - } - } - } - - .command-line-prompt { - > span { - &::before { - content: " "; - } - - &[data-user]::before { - content: "[" attr(data-user) "@" attr(data-host) "] $"; - } - - &[data-user="root"]::before { - content: "[" attr(data-user) "@" attr(data-host) "] #"; - } - - &[data-prompt]::before { - content: attr(data-prompt); - } - - &[data-continuation-prompt]::before { - content: attr(data-continuation-prompt); - } - } - } - - .line-numbers-rows { - > span { - counter-increment: lineNumber; - - &::before { - content: counter(lineNumber); - } - } - } - - .token { - &.comment, - &.doc-comment { - color: var(--color-fg-light); - } - - &.punctuation { - color: var(--color-fg); - } - - &.attr-name, - &.hexcode, - &.inserted, - &.string { - color: var(--color-token-green); - } - - &.class, - &.coord, - &.id, - &.function { - color: var(--color-token-purple); - } - - &.builtin, - &.builtin.class-name, - &.property-access, - &.regex, - &.scope { - color: var(--color-token-magenta); - } - - &.class-name, - &.constant, - &.global, - &.interpolation, - &.key, - &.package, - &.this, - &.title, - &.variable { - color: var(--color-token-blue); - } - - &.combinator, - &.keyword, - &.operator, - &.pseudo-class, - &.pseudo-element, - &.rule, - &.selector, - &.unit { - color: var(--color-token-orange); - } - - &.attr-value, - &.boolean, - &.number { - color: var(--color-token-yellow); - } - - &.delimiter, - &.doctype, - &.parameter, - &.parent, - &.property, - &.shebang, - &.tag { - color: var(--color-token-cyan); - } - - &.deleted { - color: var(--color-token-red); - } - - &.punctuation.brace-hover, - &.punctuation.brace-selected { - background: var(--color-bg); - outline: solid fun.convert-px(1) var(--color-primary-light); - } - } - - span.inline-color-wrapper { - background: url(fun.encode-svg( - '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="gray" d="M0 0h2v2H0z"/><path fill="white" d="M0 0h1v1H0zM1 1h1v1H1z"/></svg>' - )); - - // Prevent repeating pattern to be seen. - background-position: center; - background-size: 110%; - - display: inline-block; - height: 1.1ch; - width: 1.1ch; - margin: 0 0.5ch 0 0; - border: fun.convert-px(1) solid var(--color-bg); - outline: fun.convert-px(1) solid var(--color-border-dark); - overflow: hidden; - } - - span.inline-color { - display: block; - - /* To prevent visual glitches again */ - height: 120%; - width: 120%; - } - } - } -} diff --git a/src/components/molecules/layout/code.stories.tsx b/src/components/molecules/layout/code.stories.tsx deleted file mode 100644 index d20cdbe..0000000 --- a/src/components/molecules/layout/code.stories.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { Code } from './code'; - -/** - * Code - Storybook Meta - */ -export default { - title: 'Molecules/Layout/Code', - component: Code, - args: { - filterOutput: false, - outputPattern: '#output#', - }, - argTypes: { - 'aria-label': { - control: { - type: 'text', - }, - description: 'An accessible name for the code sample.', - table: { - category: 'Accessibility', - }, - type: { - name: 'string', - required: false, - }, - }, - children: { - control: { - type: 'text', - }, - description: 'The code sample.', - type: { - name: 'string', - required: true, - }, - }, - filterOutput: { - control: { - type: 'boolean', - }, - description: 'Filter the command line output.', - table: { - category: 'Options', - defaultValue: { summary: false }, - }, - type: { - name: 'boolean', - required: false, - }, - }, - language: { - control: { - type: 'text', - }, - description: 'The code sample language.', - type: { - name: 'string', - required: true, - }, - }, - plugins: { - description: 'An array of Prism plugins to activate.', - type: { - name: 'object', - required: false, - value: {}, - }, - }, - outputPattern: { - control: { - type: 'text', - }, - description: 'The command line output pattern.', - table: { - category: 'Options', - defaultValue: { summary: '#output#' }, - }, - type: { - name: 'string', - required: false, - }, - }, - }, -} as ComponentMeta<typeof Code>; - -const Template: ComponentStory<typeof Code> = (args) => <Code {...args} />; - -const javascriptCodeSample = ` -const foo = () => { - return 'bar'; -} -`; - -/** - * Code Stories - Code sample - */ -export const CodeSample = Template.bind({}); -CodeSample.args = { - children: javascriptCodeSample, - language: 'javascript', - plugins: ['line-numbers'], -}; - -const commandLineCode = ` -ls -lah -#output#drwxr-x---+ 42 armand armand 4,0K 17 avril 11:15 . -#output#drwxr-xr-x 4 root root 4,0K 30 mai 2021 .. -#output#-rw-r--r-- 1 armand armand 2,0K 21 juil. 2021 .xinitrc -`; - -/** - * Code Stories - Command Line - */ -export const CommandLine = Template.bind({}); -CommandLine.args = { - children: commandLineCode, - filterOutput: true, - language: 'bash', - plugins: ['command-line'], -}; diff --git a/src/components/molecules/layout/code.test.tsx b/src/components/molecules/layout/code.test.tsx deleted file mode 100644 index a0e4143..0000000 --- a/src/components/molecules/layout/code.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { describe, expect, it } from '@jest/globals'; -import { render } from '../../../../tests/utils'; -import { Code } from './code'; - -const code = ` -function foo() { - return 'bar'; -} -`; - -const language = 'javascript'; - -describe('Code', () => { - it('renders a code block', () => { - render(<Code language={language}>{code}</Code>); - }); -}); diff --git a/src/components/molecules/layout/code.tsx b/src/components/molecules/layout/code.tsx deleted file mode 100644 index a1aadd8..0000000 --- a/src/components/molecules/layout/code.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { FC, useRef } from 'react'; -import { - type OptionalPrismPlugin, - type PrismLanguage, - usePrism, -} from '../../../utils/hooks'; -import styles from './code.module.scss'; - -export type CodeProps = { - /** - * An accessible name. - */ - 'aria-label'?: string; - /** - * The code to highlight. - */ - children: string; - /** - * Filter command line output. Default: false. - */ - filterOutput?: boolean; - /** - * The code language. - */ - language: PrismLanguage; - /** - * The optional Prism plugins. - */ - plugins?: OptionalPrismPlugin[]; - /** - * Filter command line output using the given string. Default: #output# - */ - outputPattern?: string; -}; - -/** - * Code component - * - * Render a code block with syntax highlighting. - */ -export const Code: FC<CodeProps> = ({ - children, - filterOutput = false, - language, - plugins = [], - outputPattern = '#output#', - ...props -}) => { - const wrapperRef = useRef<HTMLDivElement>(null); - const { attributes, className } = usePrism({ language, plugins }); - - const outputAttribute = filterOutput - ? { 'data-filter-output': outputPattern } - : {}; - - return ( - <div className={styles.wrapper} ref={wrapperRef}> - <pre - {...props} - {...attributes} - {...outputAttribute} - className={className} - tabIndex={0} - > - <code className={`language-${language}`}>{children}</code> - </pre> - </div> - ); -}; diff --git a/src/components/molecules/layout/index.ts b/src/components/molecules/layout/index.ts index 58d5442..80db10a 100644 --- a/src/components/molecules/layout/index.ts +++ b/src/components/molecules/layout/index.ts @@ -1,5 +1,4 @@ export * from './card'; -export * from './code'; export * from './columns'; export * from './page-footer'; export * from './page-header'; |
