aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/molecules/layout
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-13 19:32:56 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:14:41 +0100
commit006b15b467a5cd835a6eab1b49023100bdc8f2e6 (patch)
tree949c7295c2e206f42357f135bab4696ddf6576ec /src/components/molecules/layout
parent00f147a7a687d5772bcc538bc606cfff972178cd (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.scss305
-rw-r--r--src/components/molecules/layout/code.stories.tsx121
-rw-r--r--src/components/molecules/layout/code.test.tsx17
-rw-r--r--src/components/molecules/layout/code.tsx69
-rw-r--r--src/components/molecules/layout/index.ts1
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';