diff --git a/.sauce/config1Dimension.yml b/.sauce/config1Dimension.yml index f6eeb61ef0..48bd751dd2 100644 --- a/.sauce/config1Dimension.yml +++ b/.sauce/config1Dimension.yml @@ -4,7 +4,8 @@ showConsoleLog: true sauce: region: us-west-1 concurrency: 1 # Controls how many suites are executed at the same time. - retries: 3 + # todo fix and enable retries + retries: 0 metadata: tags: - e2e @@ -23,16 +24,13 @@ suites: - "Tests/IntegrationTests/Fixtures/1Dimension/*.e2e.js" platformName: "Windows 10" screenResolution: "1280x1024" - smartRetry: - failedOnly: true - name: "One dimensional Tests in Firefox on MacOS" + # todo use chrome here and fix ci https://github.com/neos/neos-ui/issues/3591 browserName: "firefox" src: - "Tests/IntegrationTests/Fixtures/1Dimension/*.e2e.js" platformName: "macOS 13" screenResolution: "1440x900" - smartRetry: - failedOnly: true npm: dependencies: - testcafe-react-selectors diff --git a/.sauce/config2Dimension.yml b/.sauce/config2Dimension.yml index 30bc6a38c2..80ebb74ad7 100644 --- a/.sauce/config2Dimension.yml +++ b/.sauce/config2Dimension.yml @@ -3,7 +3,7 @@ kind: testcafe sauce: region: us-west-1 concurrency: 1 # Controls how many suites are executed at the same time. - retries: 3 + retries: 0 metadata: tags: - e2e @@ -22,16 +22,12 @@ suites: - "Tests/IntegrationTests/Fixtures/2Dimension/*.e2e.js" platformName: "Windows 10" screenResolution: "1280x1024" - smartRetry: - failedOnly: true - - name: "Two dimensional Tests in Firefox on MacOS" - browserName: "firefox" + - name: "Two dimensional Tests in Chrome on MacOS" + browserName: "chrome" src: - "Tests/IntegrationTests/Fixtures/2Dimension/*.e2e.js" platformName: "macOS 13" screenResolution: "1440x900" - smartRetry: - failedOnly: true npm: dependencies: - testcafe-react-selectors diff --git a/Build/Jenkins/update-neos-ui-compiled.sh b/Build/Jenkins/update-neos-ui-compiled.sh index dab3d0a836..c92057c3cf 100755 --- a/Build/Jenkins/update-neos-ui-compiled.sh +++ b/Build/Jenkins/update-neos-ui-compiled.sh @@ -35,7 +35,7 @@ export NODE_OPTIONS="--max-old-space-size=4096" nvm install && nvm use make clean && make setup -NEOS_UI_VERSION="${GIT_TAG:-${GIT_BRANCH}-dev}" make build-production +NEOS_UI_VERSION="${GIT_TAG:-${GIT_BRANCH#*/}-dev}" make build-production rm -Rf tmp_compiled_pkg git clone git@github.com:neos/neos-ui-compiled.git tmp_compiled_pkg diff --git a/Classes/Aspects/AugmentationAspect.php b/Classes/Aspects/AugmentationAspect.php index 281e812d1f..1138d150de 100644 --- a/Classes/Aspects/AugmentationAspect.php +++ b/Classes/Aspects/AugmentationAspect.php @@ -114,7 +114,15 @@ public function contentElementAugmentation(JoinPointInterface $joinPoint) $attributes['data-__neos-node-contextpath'] = $node->getContextPath(); $attributes['data-__neos-fusion-path'] = $fusionPath; - return $this->htmlAugmenter->addAttributes($content, $attributes); + // Define all attribute names as exclusive via the `exclusiveAttributes` parameter, to prevent the data of + // two different nodes to be concatenated into the attributes of a single html node. + // This way an outer div is added, if the wrapped content already has node related data-attributes set. + return $this->htmlAugmenter->addAttributes( + $content, + $attributes, + 'div', + array_keys($attributes) + ); } /** diff --git a/Makefile b/Makefile index 8c943de2f8..b42c73ec6c 100644 --- a/Makefile +++ b/Makefile @@ -108,11 +108,11 @@ test: ## Executes integration tests on saucelabs. test-e2e-saucelabs: - bash Tests/IntegrationTests/e2e-saucelabs.sh + bash Tests/IntegrationTests/e2e.sh --saucelabs ## Executes integration tests locally. test-e2e: - bash Tests/IntegrationTests/e2e.sh chrome:--disable-search-engine-choice-screen + bash Tests/IntegrationTests/e2e.sh --browser chrome:--disable-search-engine-choice-screen ## Executes integration tests locally in a docker-compose setup. test-e2e-docker: build-e2e-testing diff --git a/README.md b/README.md index a13b2f38e8..85f6f4fab3 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ To speed up the e2e-test workflow/feedback loop you can start the system under t * The neos dev instance is available at `localhost:8081` * To enter the container run `docker compose -f Tests/IntegrationTests/docker-compose.neos-dev-instance.yaml exec php bash` * `yarn run testcafe ` - * for example, this runs all tests in chrome: (NOTE starting with Chrome 127, --disable-search-engine-choice-screen is needed) + * for example, this runs all tests in chrome: (NOTE starting with Chrome 127, --disable-search-engine-choice-screen is needed until https://github.com/DevExpress/testcafe/pull/8248 is released) `yarn run testcafe chrome:--disable-search-engine-choice-screen Tests/IntegrationTests/Fixtures/1Dimension` * some helpful optional flags are * `-T 'sidebars'` - grep tests by pattern and only execute those diff --git a/Tests/IntegrationTests/Fixtures/1Dimension/selectBoxes.e2e.js b/Tests/IntegrationTests/Fixtures/1Dimension/selectBoxes.e2e.js index ae67757496..0391dce32b 100644 --- a/Tests/IntegrationTests/Fixtures/1Dimension/selectBoxes.e2e.js +++ b/Tests/IntegrationTests/Fixtures/1Dimension/selectBoxes.e2e.js @@ -23,7 +23,6 @@ test('SelectBox opens below and breaks out of the creation dialog if there\'s en test('SelectBox opens above in creation dialog if there\'s not enough space below.', async t => { await t - .resizeWindow(1200, 768) .click(Selector('#neos-PageTree-AddNode')) .click(ReactSelector('NodeTypeItem').withExactText('SelectBox opens above')) .click(ReactSelector('NodeCreationDialog SelectBox')); diff --git a/Tests/IntegrationTests/SharedNodeTypesPackage/NodeTypes/Document/SelectBoxTestPage/OpensAboveInInspector.yaml b/Tests/IntegrationTests/SharedNodeTypesPackage/NodeTypes/Document/SelectBoxTestPage/OpensAboveInInspector.yaml index 5365e250e1..f89d08f1c3 100644 --- a/Tests/IntegrationTests/SharedNodeTypesPackage/NodeTypes/Document/SelectBoxTestPage/OpensAboveInInspector.yaml +++ b/Tests/IntegrationTests/SharedNodeTypesPackage/NodeTypes/Document/SelectBoxTestPage/OpensAboveInInspector.yaml @@ -10,6 +10,9 @@ groups: test: label: Test + # move it before the general document meta-data so there is + # also space below when opening it in the e2e tests + position: start properties: TextField: type: string diff --git a/Tests/IntegrationTests/e2e-saucelabs.sh b/Tests/IntegrationTests/e2e-saucelabs.sh deleted file mode 100755 index 5f70a9af10..0000000000 --- a/Tests/IntegrationTests/e2e-saucelabs.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -# Check if saucectl is installed -if ! command -v saucectl &> /dev/null; then - echo "saucectl is not installed. Installing saucectl..." - # Install saucectl via npm (assuming npm is installed) - npm install -g saucectl -fi - -# Check if SAUCE_USERNAME and SAUCE_ACCESS_KEY are set -if [[ -n "$SAUCE_USERNAME" && -n "$SAUCE_ACCESS_KEY" ]]; then - echo "SAUCE_USERNAME and SAUCE_ACCESS_KEY are set. Configuring saucectl..." - #saucectl configure -else - echo "SAUCE_USERNAME or SAUCE_ACCESS_KEY is not set. Skipping saucectl configuration." - exit 1 -fi - -cd ../../.. - -rm -rf DummyDistributionPackages || true -mv DistributionPackages DummyDistributionPackages -mkdir DistributionPackages - -ln -s "../Packages/Application/Neos.Neos.Ui/Tests/IntegrationTests/SharedNodeTypesPackage" DistributionPackages/Neos.TestNodeTypes - -for fixture in Packages/Application/Neos.Neos.Ui/Tests/IntegrationTests/Fixtures/*/; do - echo "$fixture" - dimension=$(basename "$fixture") - echo "$dimension" - - ln -s "../${fixture}SitePackage" DistributionPackages/Neos.TestSite - - # TODO: optimize this - composer reinstall neos/test-nodetypes - composer reinstall neos/test-site - # make sure neos is installed even if patching led to the removal (bug) - composer update neos/neos-development-collection - ./flow flow:cache:flush --force - ./flow flow:cache:warmup - ./flow configuration:show --path Neos.ContentRepository.contentDimensions - - if ./flow site:list | grep -q 'Node name'; then - ./flow site:prune '*' - fi - ./flow site:import --package-key=Neos.TestSite - ./flow resource:publish - - cd Packages/Application/Neos.Neos.Ui - saucectl run --config .sauce/config${dimension}.yml - cd ../../.. - rm -f DistributionPackages/Neos.TestSite - -done - -rm -rf DistributionPackages -mv DummyDistributionPackages DistributionPackages diff --git a/Tests/IntegrationTests/e2e.sh b/Tests/IntegrationTests/e2e.sh index 2dd372e10c..4b5c3c9bec 100755 --- a/Tests/IntegrationTests/e2e.sh +++ b/Tests/IntegrationTests/e2e.sh @@ -2,45 +2,148 @@ set -ex -if [ -z "$1" ]; then - echo "No testcafe browser supplied, e.g. 'chrome:headless'" -fi +# Global variables +BROWSER="" +USE_SAUCELABS=false -cd ../../.. +# Function to parse arguments and save values to global variables +parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + print_usage_information + exit 0 + ;; + -s|--saucelabs) + USE_SAUCELABS=true + ;; + -b|--browser) + BROWSER="$2" + shift + ;; + *) + echo "Unknown option: $1" + print_usage_information + exit 1 + ;; + esac + shift + done +} -rm -rf DummyDistributionPackages || true -mv DistributionPackages DummyDistributionPackages -mkdir DistributionPackages +print_usage_information() { + cat < /dev/null; then + echo "saucectl is not installed. Installing saucectl..." + # Install saucectl via npm (assuming npm is installed) + npm install -g saucectl fi - ./flow site:import --package-key=Neos.TestSite - ./flow resource:publish +} + +# parse dimension from fixture file name +function get_dimension() { + dimension=$(basename "$1") + echo "$dimension" +} + +# Function that gets a fixture as parameter. With the fixture we +# load the related site package and import the site. +function initialize_neos_site() { + local fixture=$1 - cd Packages/Application/Neos.Neos.Ui - yarn run testcafe "$1" "../../../${fixture}*.e2e.js" \ - --selector-timeout=10000 --assertion-timeout=30000 + ln -s "../${fixture}SitePackage" DistributionPackages/Neos.TestSite + + composer reinstall neos/test-nodetypes + composer reinstall neos/test-site + # make sure neos is installed even if patching led to the removal (bug) + composer update neos/neos-development-collection + ./flow flow:cache:flush --force + ./flow flow:cache:warmup + ./flow configuration:show --path Neos.ContentRepository.contentDimensions + + if ./flow site:list | grep -q 'Node name'; then + ./flow site:prune '*' + fi + ./flow site:import --package-key=Neos.TestSite + ./flow resource:publish +} + +function run_tests() { cd ../../.. - rm -f DistributionPackages/Neos.TestSite -done + rm -rf DummyDistributionPackages || true + mv DistributionPackages DummyDistributionPackages + mkdir DistributionPackages + + ln -s "../Packages/Application/Neos.Neos.Ui/Tests/IntegrationTests/SharedNodeTypesPackage" DistributionPackages/Neos.TestNodeTypes + + for fixture in Packages/Application/Neos.Neos.Ui/Tests/IntegrationTests/Fixtures/*/; do + dimension=$(get_dimension "$fixture") + initialize_neos_site "$fixture" + + # go tp the Neos.Neos.Ui package and run the tests + cd Packages/Application/Neos.Neos.Ui + + if [[ $BROWSER ]]; then + yarn run testcafe "$BROWSER" "../../../${fixture}*.e2e.js" --selector-timeout=10000 --assertion-timeout=30000 || hasFailure=1 + fi + + if [[ $USE_SAUCELABS ]]; then + saucectl run --config .sauce/config${dimension}.yml || hasFailure=1 + fi + + # cd back to the root directory and clean up + cd ../../.. + rm -f DistributionPackages/Neos.TestSite + done + + rm -rf DistributionPackages + mv DummyDistributionPackages DistributionPackages + + if [[ $hasFailure -eq 1 ]] ; then + exit 1 + fi +} + +parse_arguments "$@" + +# check if incoming parameters are correct +check_testcafe_browser +check_saucelabs_setup -rm -rf DistributionPackages -mv DummyDistributionPackages DistributionPackages +run_tests diff --git a/esbuild.js b/esbuild.js index 5a77b17f00..b6f4cf0c83 100644 --- a/esbuild.js +++ b/esbuild.js @@ -32,7 +32,8 @@ const options = { legalComments: "linked", loader: { '.js': 'tsx', - '.svg': 'dataurl', + '.dataurl.svg': 'dataurl', + '.svg': 'text', '.vanilla-css': 'css', '.woff2': 'file' }, @@ -53,13 +54,6 @@ const options = { } }) - // load ckeditor icons as plain text and not via `.svg: dataurl` - // (currently neccessary for the table select handle icon) - onLoad({filter: /node_modules\/@ckeditor\/.*\.svg$/}, async ({path}) => ({ - contents: (await require('fs/promises').readFile(path)).toString(), - loader: 'text' - })) - // prefix Fontawesome with "neos-" to prevent clashes with customer Fontawesome onLoad({filter: /@fortawesome\/fontawesome-svg-core\/styles\.css$/}, async ({path}) => { const contents = (await require('fs/promises').readFile(path)).toString(); diff --git a/packages/neos-ui-ckeditor5-bindings/src/ckEditorApi.js b/packages/neos-ui-ckeditor5-bindings/src/ckEditorApi.js index 979a2ab5f5..7579373ac1 100644 --- a/packages/neos-ui-ckeditor5-bindings/src/ckEditorApi.js +++ b/packages/neos-ui-ckeditor5-bindings/src/ckEditorApi.js @@ -57,9 +57,12 @@ export const createEditor = store => async options => { return NeosEditor .create(propertyDomNode, ckEditorConfig) .then(editor => { + const debouncedOnChange = debounce(() => onChange(cleanupContentBeforeCommit(editor.getData())), 1500, {maxWait: 5000}); + editor.model.document.on('change:data', debouncedOnChange); editor.ui.focusTracker.on('change:isFocused', event => { if (!event.source.isFocused) { - onChange(cleanupContentBeforeCommit(editor.getData())) + // when another editor is focused commit all possible pending changes + debouncedOnChange.flush(); return } @@ -74,7 +77,6 @@ export const createEditor = store => async options => { }); editor.model.document.on('change', () => handleUserInteractionCallback()); - editor.model.document.on('change:data', debounce(() => onChange(cleanupContentBeforeCommit(editor.getData())), 1500, {maxWait: 5000})); return editor; }).catch(e => { if (e instanceof TypeError && e.message.match(/Class constructor .* cannot be invoked without 'new'/)) { diff --git a/packages/neos-ui-containers/src/InsertModeSelector/index.js b/packages/neos-ui-containers/src/InsertModeSelector/index.js index 70de7bce8d..a4df6b9148 100644 --- a/packages/neos-ui-containers/src/InsertModeSelector/index.js +++ b/packages/neos-ui-containers/src/InsertModeSelector/index.js @@ -1,12 +1,16 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; -import {ButtonGroup, Button, Icon} from '@neos-project/react-ui-components'; +import {ButtonGroup, Button, ResourceIcon} from '@neos-project/react-ui-components'; import {neos} from '@neos-project/neos-ui-decorators'; import I18n from '@neos-project/neos-ui-i18n'; import style from './style.module.css'; +import createAboveIcon from './resources/create-above.svg'; +import createBelowIcon from './resources/create-below.svg'; +import createInsideIcon from './resources/create-inside.svg'; + const MODE_AFTER = 'after'; const MODE_BEFORE = 'before'; const MODE_INTO = 'into'; @@ -98,7 +102,7 @@ export default class InsertModeSelector extends PureComponent { size="small" title={`${i18nRegistry.translate('Neos.Neos:Main:insert')} ${i18nRegistry.translate('above')}`} > - + diff --git a/Resources/Public/Icons/create-above.svg b/packages/neos-ui-containers/src/InsertModeSelector/resources/create-above.svg similarity index 100% rename from Resources/Public/Icons/create-above.svg rename to packages/neos-ui-containers/src/InsertModeSelector/resources/create-above.svg diff --git a/Resources/Public/Icons/create-below.svg b/packages/neos-ui-containers/src/InsertModeSelector/resources/create-below.svg similarity index 100% rename from Resources/Public/Icons/create-below.svg rename to packages/neos-ui-containers/src/InsertModeSelector/resources/create-below.svg diff --git a/Resources/Public/Icons/create-inside.svg b/packages/neos-ui-containers/src/InsertModeSelector/resources/create-inside.svg similarity index 100% rename from Resources/Public/Icons/create-inside.svg rename to packages/neos-ui-containers/src/InsertModeSelector/resources/create-inside.svg diff --git a/packages/neos-ui-editors/src/Editors/Image/Components/PreviewScreen/index.js b/packages/neos-ui-editors/src/Editors/Image/Components/PreviewScreen/index.js index ee77293da9..40980a39b2 100644 --- a/packages/neos-ui-editors/src/Editors/Image/Components/PreviewScreen/index.js +++ b/packages/neos-ui-editors/src/Editors/Image/Components/PreviewScreen/index.js @@ -5,6 +5,7 @@ import {AssetUpload} from '../../../../Library/index'; import {Thumbnail} from '../../Utils/index'; import {Icon} from '@neos-project/react-ui-components'; +import dummyImage from '../../resource/dummy-image.dataurl.svg'; import style from './style.module.css'; export default class PreviewScreen extends PureComponent { @@ -52,7 +53,7 @@ export default class PreviewScreen extends PureComponent { {propertyName} diff --git a/packages/neos-ui-editors/src/Editors/Image/resource/dummy-image.dataurl.svg b/packages/neos-ui-editors/src/Editors/Image/resource/dummy-image.dataurl.svg new file mode 100644 index 0000000000..26bd783040 --- /dev/null +++ b/packages/neos-ui-editors/src/Editors/Image/resource/dummy-image.dataurl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/neos-ui-editors/src/SecondaryEditors/ImageCropper/index.js b/packages/neos-ui-editors/src/SecondaryEditors/ImageCropper/index.js index 5e7a1660e6..4c98dc63ca 100644 --- a/packages/neos-ui-editors/src/SecondaryEditors/ImageCropper/index.js +++ b/packages/neos-ui-editors/src/SecondaryEditors/ImageCropper/index.js @@ -8,6 +8,7 @@ import {$get} from 'plow-js'; import AspectRatioDropDown from './AspectRatioDropDown/index'; import CropConfiguration, {CustomAspectRatioOption, LockedAspectRatioStrategy} from './model.js'; +import dummyImage from '../../Editors/Image/resource/dummy-image.dataurl.svg'; import style from './style.module.css'; import './react_crop.vanilla-css'; @@ -182,7 +183,7 @@ export default class ImageCropper extends PureComponent { const aspectRatioLocked = cropConfiguration.aspectRatioStrategy instanceof LockedAspectRatioStrategy; const allowCustomRatios = cropConfiguration.aspectRatioOptions.some(option => option instanceof CustomAspectRatioOption); const {sourceImage, i18nRegistry} = this.props; - const src = sourceImage.previewUri || '/_Resources/Static/Packages/Neos.Neos/Images/dummy-image.svg'; + const src = sourceImage.previewUri || dummyImage; const toolbarRef = el => { this.toolbarNode = el; diff --git a/packages/neos-ui-guest-frame/src/initializePropertyDomNode.js b/packages/neos-ui-guest-frame/src/initializePropertyDomNode.js index b5bd02f549..94d527b5bb 100644 --- a/packages/neos-ui-guest-frame/src/initializePropertyDomNode.js +++ b/packages/neos-ui-guest-frame/src/initializePropertyDomNode.js @@ -1,6 +1,6 @@ import {$get, $contains} from 'plow-js'; -import {actions, selectors} from '@neos-project/neos-ui-redux-store'; +import {actions} from '@neos-project/neos-ui-redux-store'; import {validateElement} from '@neos-project/neos-ui-validators'; import {getGuestFrameWindow, closestContextPathInGuestFrame} from './dom'; @@ -74,14 +74,6 @@ export default ({store, globalRegistry, nodeTypesRegistry, inlineEditorRegistry, actions.Changes.persistChanges([change]) ), onChange: value => { - const node = selectors.CR.Nodes.byContextPathSelector(contextPath)(store.getState()); - if (node) { - const oldValue = node.properties[propertyName]; - if (oldValue === value) { - return; - } - } - const validationResult = validateElement(value, $get(['properties', propertyName], nodeType), globalRegistry.get('validators')); // Update inline validation errors store.dispatch( diff --git a/packages/neos-ui-guest-frame/src/style.module.css b/packages/neos-ui-guest-frame/src/style.module.css index 2c6fed4f8b..cb7ef380d4 100644 --- a/packages/neos-ui-guest-frame/src/style.module.css +++ b/packages/neos-ui-guest-frame/src/style.module.css @@ -22,11 +22,11 @@ outline-color: var(--colors-Warn); } -:global(.neos-inline-editable:focus) { +:global([data-__neos-property][contenteditable]) { outline: none; } -:global([data-neos-inline-editor-is-initialized]:hover) { +:global([data-__neos-property][contenteditable]:hover) { outline-offset: 5px; outline: 2px dashed var(--colors-PrimaryBlue); } diff --git a/packages/react-ui-components/esbuild.js b/packages/react-ui-components/esbuild.js index 4f4a1468ac..e23adc49ad 100644 --- a/packages/react-ui-components/esbuild.js +++ b/packages/react-ui-components/esbuild.js @@ -71,7 +71,7 @@ async function main() { metafile: true, loader: { '.js': 'tsx', - '.svg': 'dataurl', + '.svg': 'text', '.css': 'copy' }, plugins: [ diff --git a/packages/react-ui-components/src/Icon/resourceIcon.tsx b/packages/react-ui-components/src/Icon/resourceIcon.tsx index d67566d7f1..0970c0c74e 100644 --- a/packages/react-ui-components/src/Icon/resourceIcon.tsx +++ b/packages/react-ui-components/src/Icon/resourceIcon.tsx @@ -13,6 +13,11 @@ export interface ResourceIconProps extends Omit { readonly theme?: ResourceIconTheme; } +/** + * @deprecated please refrain from using resource paths + * use the new react-ui-components/ResourceIcon instead. + * See also https://github.com/neos/neos-ui/issues/2092 + */ class ResourceIcon extends PureComponent { public static readonly defaultProps = defaultProps; diff --git a/packages/react-ui-components/src/Logo/index.js b/packages/react-ui-components/src/Logo/index.js index 2b66f8a85b..6c2501bd4d 100644 --- a/packages/react-ui-components/src/Logo/index.js +++ b/packages/react-ui-components/src/Logo/index.js @@ -1,14 +1,11 @@ import React, {PureComponent} from 'react'; +import {ResourceIcon} from '../ResourceIcon'; -import logo from './logo.svg'; +import logoSvg from './resource/logo.svg'; import style from './style.module.css'; export default class Logo extends PureComponent { render() { - return ( -
- Neos -
- ); + return ; } } diff --git a/packages/react-ui-components/src/Logo/logo.svg b/packages/react-ui-components/src/Logo/logo.svg deleted file mode 100755 index bfcafa2669..0000000000 --- a/packages/react-ui-components/src/Logo/logo.svg +++ /dev/null @@ -1 +0,0 @@ -neos_negative_dark \ No newline at end of file diff --git a/packages/react-ui-components/src/Logo/resource/logo.svg b/packages/react-ui-components/src/Logo/resource/logo.svg new file mode 100755 index 0000000000..1b91ad9eed --- /dev/null +++ b/packages/react-ui-components/src/Logo/resource/logo.svg @@ -0,0 +1,5 @@ + diff --git a/packages/react-ui-components/src/Logo/style.module.css b/packages/react-ui-components/src/Logo/style.module.css index 4e6e5a7a55..93f7fd844b 100644 --- a/packages/react-ui-components/src/Logo/style.module.css +++ b/packages/react-ui-components/src/Logo/style.module.css @@ -1,4 +1,3 @@ -.logo { +.logo > svg { height: 24px; - width: auto; } diff --git a/packages/react-ui-components/src/ResourceIcon/index.tsx b/packages/react-ui-components/src/ResourceIcon/index.tsx new file mode 100644 index 0000000000..f8d0fdd6fd --- /dev/null +++ b/packages/react-ui-components/src/ResourceIcon/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import mergeClassNames from 'classnames'; +import style from './style.module.css'; + +type ResourceIconProps = { + source?: string; + className?: string; + label?: string; +} + +export function ResourceIcon(props: ResourceIconProps) { + const {source, className, label} = props; + + if (!source) { + return null; + } + + const classNames = mergeClassNames( + className, + { + [style['resource-icon']]: true + } + ); + + return ; +} diff --git a/packages/react-ui-components/src/ResourceIcon/style.module.css b/packages/react-ui-components/src/ResourceIcon/style.module.css new file mode 100644 index 0000000000..f759d7b28b --- /dev/null +++ b/packages/react-ui-components/src/ResourceIcon/style.module.css @@ -0,0 +1,16 @@ +.resource-icon { + composes: reset from '../reset.module.css'; + font: normal normal normal FontAwesome; + font-size: 14px/1; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + display: inline-flex; + width: 100%; + justify-content: center; +} + +.resource-icon > svg { + fill: none; +} diff --git a/packages/react-ui-components/src/index.ts b/packages/react-ui-components/src/index.ts index d8a4677430..a4b4df2619 100644 --- a/packages/react-ui-components/src/index.ts +++ b/packages/react-ui-components/src/index.ts @@ -11,6 +11,7 @@ export {default as DropDown} from './DropDown'; export {default as Frame} from './Frame'; export {default as Headline} from './Headline'; export {default as Icon} from './Icon'; +export {ResourceIcon} from './ResourceIcon'; export {default as IconButton} from './IconButton'; export {default as IconButtonDropDown} from './IconButtonDropDown'; export {default as Label} from './Label';