diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3e5e83..f0e8256f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- `` + - visualize the usage of tabulator chars by background color and arrow symbol + - new `tabIntentSize`, `tabIntentStyle`, `tabForceSpaceForModes` properties to give better control over tabulator usage + +### Fixed + +- `` + - images representing SVG without `width` property on their root element are displayed with a minimal forced dimension to prevent that they are hidden in some browsers + ## [23.4.1] - 2024-02-08 ### Fixed diff --git a/package.json b/package.json index aae5603f..13dd327b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@eccenca/gui-elements", "description": "GUI elements based on other libraries, usable in React application, written in Typescript.", - "version": "23.4.1", + "version": "23.5.0-rc.0", "license": "Apache-2.0", "homepage": "https://github.com/eccenca/gui-elements", "bugs": "https://github.com/eccenca/gui-elements/issues", diff --git a/src/components/Depiction/depiction.scss b/src/components/Depiction/depiction.scss index 024dce33..f991fbd8 100644 --- a/src/components/Depiction/depiction.scss +++ b/src/components/Depiction/depiction.scss @@ -3,16 +3,14 @@ $eccgui-size-depiction-height-small: mini-units(6) !default; $eccgui-size-depiction-height-medium: mini-units(12) !default; $eccgui-size-depiction-height-large: mini-units(24) !default; $eccgui-size-depiction-height-xlarge: mini-units(48) !default; - $eccgui-color-depiction-background: $eccgui-color-workspace-text !default; $eccgui-color-depiction-text: $eccgui-color-workspace-background !default; $eccgui-size-depiction-border-radius: $pt-border-radius !default; - .#{$eccgui}-depiction { - max-width: 100%; - display: inline-flex; position: relative; + display: inline-flex; + max-width: 100%; .#{$eccgui}-overviewitem__item > & { flex-grow: 0; @@ -26,12 +24,13 @@ $eccgui-size-depiction-border-radius: $pt-border-radius !default; } .#{$eccgui}-depiction__image { - overflow: hidden; max-width: 100%; max-height: 100%; + overflow: hidden; border-radius: $eccgui-size-depiction-border-radius; - img, svg { + img, + svg { width: 100%; height: 100%; } @@ -57,10 +56,22 @@ $eccgui-size-depiction-border-radius: $pt-border-radius !default; .#{$eccgui}-depiction__image--ratio-source { aspect-ratio: auto; - img, svg { + img, + svg { max-width: 100%; max-height: 100%; } + + /** + * SVG images without width property on their SVG root are not (specific: using a width of 0px) displayed by some browsers (e.g. Firefox or Brave). + * This might be technically correct but to the user it looks like a bug and is not expected by them. + * We workaround this "problem" by adding minimal dimensions to images with an SVG source. + */ + img[src^="data:image/svg"], + img[src*=".svg"] { + min-width: $eccgui-size-depiction-height-tiny; + min-height: $eccgui-size-depiction-height-tiny; + } } .#{$eccgui}-depiction__image--ratio-1to1 { @@ -68,19 +79,22 @@ $eccgui-size-depiction-border-radius: $pt-border-radius !default; } .#{$eccgui}-depiction__image--contain-sizing { - img, svg { + img, + svg { object-fit: contain; } } .#{$eccgui}-depiction__image--cover-sizing { - img, svg { + img, + svg { object-fit: cover; } } .#{$eccgui}-depiction__image--stretch-sizing { - img, svg { + img, + svg { object-fit: fill; } } @@ -153,8 +167,8 @@ $eccgui-size-depiction-border-radius: $pt-border-radius !default; --#{$eccgui}-depiction-color: #{$eccgui-color-depiction-background}; } .#{$eccgui}-depiction__image--color-config { - background: var(--#{$eccgui}-depiction-background); color: var(--#{$eccgui}-depiction-color); + background: var(--#{$eccgui}-depiction-background); /* Lead to more problems, even with our Carbon icons, that it "heals" unknown SVGs @@ -166,11 +180,11 @@ $eccgui-size-depiction-border-radius: $pt-border-radius !default; } .#{$eccgui}-depiction__image--hasborder { - border: 1px solid currentColor; + border: 1px solid currentcolor; } .#{$eccgui}-depiction__caption--none, - .#{$eccgui}-depiction__caption--tooltip { +.#{$eccgui}-depiction__caption--tooltip { position: fixed; left: -5000rem; } diff --git a/src/components/Depiction/stories/Depiction.stories.tsx b/src/components/Depiction/stories/Depiction.stories.tsx index 257e1b72..bc5d13aa 100644 --- a/src/components/Depiction/stories/Depiction.stories.tsx +++ b/src/components/Depiction/stories/Depiction.stories.tsx @@ -1,19 +1,25 @@ import React from "react"; -import { ComponentStory, ComponentMeta } from "@storybook/react"; import { LogoReact } from "@carbon/icons-react"; +import { Meta, StoryFn } from "@storybook/react"; + import { Badge, Depiction, Icon, TestIcon } from "../../../index"; + import canonicalIcons from "./../../Icon/canonicalIconNames"; -import png16to9 from "./test-16to9.png"; +import { Svg9to16 } from "./test-9to16"; import png9to16 from "./test-9to16.png"; -import svg16to9 from "./test-16to9.svg"; import svg9to16 from "./test-9to16.svg"; -import svg16to9base64 from "./test-16to9.tobase64.svg"; import svg9to16base64 from "./test-9to16.tobase64.svg"; import { Svg16to9 } from "./test-16to9"; -import { Svg9to16 } from "./test-9to16"; +import png16to9 from "./test-16to9.png"; +import svg16to9 from "./test-16to9.svg"; +import svg16to9base64 from "./test-16to9.tobase64.svg"; +import svgDimensionless from "./test-dimensionless.svg"; +import svgDimensionlessBase64 from "./test-dimensionless.tobase64.svg"; const allIcons = new Map([ - ...Object.keys(canonicalIcons).map((keyId) => { return [`Icon: ${keyId}`, ] }) + ...Object.keys(canonicalIcons).map((keyId) => { + return [`Icon: ${keyId}`, ]; + }), ]); const exampleImages = { @@ -25,18 +31,28 @@ const exampleImages = { "SVG 9:16 as Base64": , "SVG 16:9 as React element": , "SVG 9:16 as React element": , - // "PNG 16:9 as Base64": , - // "SVG 16:9 as Base64": , + "SVG without known width/height dimensions": , + "SVG without known width/height as Base64": , "Test icon": , ...Object.fromEntries(allIcons), }; const exampleBadges = { "No badge": undefined, - "Text badge (small, danger, bottom-right)": Problem occured!, - "Icon badge (accent, inline, bottom-right)": , - "Number badge (large, info, top-right)": , -} + "Text badge (small, danger, bottom-right)": ( + + Problem occured! + + ), + "Icon badge (accent, inline, bottom-right)": ( + + + + ), + "Number badge (large, info, top-right)": ( + + ), +}; export default { title: "Components/Depiction", @@ -56,14 +72,12 @@ export default { mapping: exampleBadges, }, }, -} as ComponentMeta; +} as Meta; -const TemplateFull: ComponentStory = (args) => ( - -); +const TemplateFull: StoryFn = (args) => ; export const FullExample = TemplateFull.bind({}); FullExample.args = { image: , - caption: "This is a test description for the image." + caption: "This is a test description for the image.", }; diff --git a/src/components/Depiction/stories/test-dimensionless.svg b/src/components/Depiction/stories/test-dimensionless.svg new file mode 100644 index 00000000..74f51ec9 --- /dev/null +++ b/src/components/Depiction/stories/test-dimensionless.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + dimensionless + + diff --git a/src/components/Depiction/stories/test-dimensionless.tobase64.svg b/src/components/Depiction/stories/test-dimensionless.tobase64.svg new file mode 100644 index 00000000..74f51ec9 --- /dev/null +++ b/src/components/Depiction/stories/test-dimensionless.tobase64.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + dimensionless + + diff --git a/src/extensions/codemirror/CodeMirror.tsx b/src/extensions/codemirror/CodeMirror.tsx index 19ec2f55..222e5c52 100644 --- a/src/extensions/codemirror/CodeMirror.tsx +++ b/src/extensions/codemirror/CodeMirror.tsx @@ -66,6 +66,22 @@ export interface CodeEditorProps { wrapLines?: boolean; outerDivAttributes?: Partial>; + + /** + * Size in spaces that is used for a tabulator key. + */ + tabIntentSize?: number; + + /** + * Set the char type that is used for the tabulator key. + * If set to `space` the a number of `tabIntentSize` spaces is used instead of a tab. + */ + tabIntentStyle?: "tab" | "space"; + + /** + * For some modes an indent style with `space` can be forced, even if `tabIntentStyle="tab"` is set. + */ + tabForceSpaceForModes?: SupportedCodeEditorModes[]; } /** @@ -82,6 +98,9 @@ export const CodeEditor = ({ height, wrapLines = false, outerDivAttributes, + tabIntentSize = 2, + tabIntentStyle = "tab", + tabForceSpaceForModes = ["python", "yaml"], }: CodeEditorProps) => { const domRef = useRef(null); @@ -90,9 +109,16 @@ export const CodeEditor = ({ mode: convertMode(mode), lineWrapping: wrapLines, lineNumbers: !preventLineNumbers, - tabSize: 2, + tabSize: tabIntentSize, + indentUnit: tabIntentSize, + indentWithTabs: tabIntentStyle === "tab" && !(tabForceSpaceForModes ?? []).includes(mode), theme: "xq-light", readOnly: readOnly, + extraKeys: { + Tab: function (cm) { + cm.execCommand(cm.getOption("indentWithTabs") ? "insertTab" : "insertSoftTab"); + }, + }, }); editorInstance.on("change", (api) => { diff --git a/src/extensions/codemirror/_codemirror.scss b/src/extensions/codemirror/_codemirror.scss index 704e34eb..36c3d60a 100644 --- a/src/extensions/codemirror/_codemirror.scss +++ b/src/extensions/codemirror/_codemirror.scss @@ -7,9 +7,9 @@ max-width: 100%; .CodeMirror { + height: 290px; clip-path: unset !important; // we may check later why they set inset(0) now border-radius: $pt-border-radius; - height: 290px; // get them a "border" like input boxes from blueprintjs box-shadow: input-transition-shadow($input-shadow-color-focus), $pt-input-box-shadow; @@ -54,6 +54,20 @@ .CodeMirror-sizer { border-right-width: $eccgui-size-inline-whitespace !important; } + + .cm-tab { + position: relative; + + // mark tabulator chars + background-color: $eccgui-color-info-background; + + &::after { + position: absolute; + left: 10%; + color: rgba($eccgui-color-workspace-text, $eccgui-opacity-muted); + content: "⇥"; + } + } } }