diff --git a/showcases/next-showcase/tsconfig.json b/showcases/next-showcase/tsconfig.json index 2e8cd0fc7f52..017b20fd23cc 100644 --- a/showcases/next-showcase/tsconfig.json +++ b/showcases/next-showcase/tsconfig.json @@ -11,7 +11,7 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "strictNullChecks": true, "downlevelIteration": true, "target": "ES2017" diff --git a/showcases/patternhub/components/icon-code-snippet/index.tsx b/showcases/patternhub/components/icon-code-snippet/index.tsx new file mode 100644 index 000000000000..ba437e256218 --- /dev/null +++ b/showcases/patternhub/components/icon-code-snippet/index.tsx @@ -0,0 +1,129 @@ +import { + DBButton, + DBDivider, + DBIcon, + DBInfotext, + DBPopover +} from '../../../../output/react/src/index'; +import CopyClipboardButton from '../copy-clipboard-button'; + +export type IconCodeSnippetProps = { + iconName: string; + weight: string; + family: string; +}; + +const IconCodeSnippet = ({ + iconName, + weight, + family +}: IconCodeSnippetProps) => { + // Generate code snippets for different configurations + const generateSnippet = ( + variant: 'before' | 'after', + withWeight: boolean, + withFamily: boolean + ) => { + const parts: string[] = []; + + if (variant === 'before') { + parts.push(`data-icon="${iconName}"`); + if (withWeight) { + parts.push(`data-icon-weight="${weight}"`); + } + + if (withFamily && family !== 'default') { + parts.push(`data-icon-variant="${family}"`); + } + } else { + parts.push(`data-icon-trailing="${iconName}"`); + if (withWeight) { + parts.push(`data-icon-weight-after="${weight}"`); + } + + if (withFamily && family !== 'default') { + parts.push(`data-icon-variant-after="${family}"`); + } + } + + return `Text`; + }; + + const snippets = [ + { + title: 'Icon Before (Basic)', + code: generateSnippet('before', false, false) + }, + { + title: `Icon Before (weight: ${weight}px)`, + code: generateSnippet('before', true, false) + }, + { + title: `Icon Before (weight: ${weight}px, family: ${family})`, + code: generateSnippet('before', true, true) + }, + { + title: 'Icon After (Basic)', + code: generateSnippet('after', false, false) + }, + { + title: `Icon After (weight: ${weight}px)`, + code: generateSnippet('after', true, false) + }, + { + title: `Icon After (weight: ${weight}px, family: ${family})`, + code: generateSnippet('after', true, true) + } + ]; + + return ( + + {iconName} + + {iconName} + + > + }> + + + + {iconName} + + + + {snippets.map((snippet, index) => ( + + + {iconName} + {snippet.title} + + + + {snippet.code} + + + Copied to clipboard + + + + ))} + + + + ); +}; + +export default IconCodeSnippet; diff --git a/showcases/patternhub/pages/foundations/icons/overview.tsx b/showcases/patternhub/pages/foundations/icons/overview.tsx index 7cc28012b1fe..2380021d60a7 100644 --- a/showcases/patternhub/pages/foundations/icons/overview.tsx +++ b/showcases/patternhub/pages/foundations/icons/overview.tsx @@ -1,13 +1,8 @@ import { ALL_ICONS } from '@db-ux/db-theme-icons'; import { useState } from 'react'; -import { - DBCard, - DBIcon, - DBInfotext, - DBInput, - DBSelect -} from '../../../../../output/react/src'; +import { DBCard, DBInput, DBSelect } from '../../../../../output/react/src'; import DefaultPage from '../../../components/default-page'; +import IconCodeSnippet from '../../../components/icon-code-snippet'; // Import root package.json for theme version import rootPackage from '../../../../../package.json'; @@ -65,7 +60,9 @@ const IconOverview = () => { setWeight(event.target.value); }}> {[16, 20, 24, 32].map((fw) => ( - {fw} + + {fw} + ))} { setFamily(event.target.value); }}> {['default', 'filled'].map((fam) => ( - {fam} + + {fam} + ))} @@ -91,12 +90,15 @@ const IconOverview = () => { }> {ALL_ICONS.filter((icon) => icon.includes(search)).map( (icon) => ( - - {/* TODO: Make this interactive to copy the icon name */} - {icon} - - {icon} - + + ) )} diff --git a/showcases/patternhub/styles/globals.scss b/showcases/patternhub/styles/globals.scss index 1e0a058e693f..272b31cfdec3 100644 --- a/showcases/patternhub/styles/globals.scss +++ b/showcases/patternhub/styles/globals.scss @@ -172,10 +172,72 @@ div[class^="ch-"] { > .db-card { justify-content: center; align-items: center; + position: relative; .db-infotext { word-break: break-word; } + + .db-button[aria-label^="Show code"] { + position: absolute; + inset-inline-end: variables.$db-spacing-fixed-xs; + inset-block-start: variables.$db-spacing-fixed-xs; + } + } +} + +// Icon code snippet popover styles +.icon-code-snippet-container { + @include display.display(flex); + flex-direction: column; + gap: variables.$db-spacing-fixed-sm; + min-inline-size: 300px; + max-inline-size: 500px; + + .icon-code-snippet-header { + @include display.display(flex); + justify-content: space-between; + align-items: center; + } + + .icon-code-snippet-content { + @include display.display(flex); + flex-direction: column; + gap: variables.$db-spacing-fixed-md; + max-block-size: 400px; + overflow-y: auto; + + .snippet-item { + @include display.display(flex); + flex-direction: column; + gap: variables.$db-spacing-fixed-xs; + + .snippet-title { + font-weight: bold; + @extend %db-overwrite-font-size-sm; + } + + .snippet-code-container { + @include display.display(flex); + align-items: flex-start; + gap: variables.$db-spacing-fixed-xs; + padding: variables.$db-spacing-fixed-sm; + background-color: colors.$db-adaptive-bg-basic-transparent-semi-default; + border-radius: variables.$db-border-radius-sm; + position: relative; + + .snippet-code { + flex: 1; + word-break: break-all; + white-space: pre-wrap; + @extend %db-overwrite-font-size-sm; + } + + .db-button { + flex-shrink: 0; + } + } + } } }
+ {snippet.code} +