Browse Source

feat(issue-details): Update context data styles to match existing colors (#65980)

Closes https://github.com/getsentry/sentry/issues/65983

`<ContextData />` was using non-standard colors in a less file. Removed
all the styles that were only used in this file and replaced them with
styled components. Now using the same red that's used for syntax
highlighting.
Malachi Willey 1 year ago
parent
commit
0d4eb21486

+ 79 - 52
static/app/components/contextData/index.tsx

@@ -20,6 +20,18 @@ type Props = React.HTMLAttributes<HTMLPreElement> & {
   withAnnotatedText?: boolean;
 };
 
+function LinkHint({value}: {value: string}) {
+  if (!isUrl(value)) {
+    return null;
+  }
+
+  return (
+    <ExternalLink href={value} className="external-icon">
+      <StyledIconOpen size="xs" aria-label={t('Open link')} />
+    </ExternalLink>
+  );
+}
+
 function walk({
   depth,
   value = null,
@@ -41,54 +53,53 @@ function walk({
 
   if (value === null) {
     return (
-      <span className="val-null">
+      <ValueNull>
         <AnnotatedText value={jsonConsts ? 'null' : 'None'} meta={meta?.[''] ?? meta} />
-      </span>
+      </ValueNull>
     );
   }
 
   if (value === true || value === false) {
     return (
-      <span className="val-bool">
+      <ValueBoolean>
         <AnnotatedText
           value={jsonConsts ? (value ? 'true' : 'false') : value ? 'True' : 'False'}
           meta={meta?.[''] ?? meta}
         />
-      </span>
+      </ValueBoolean>
     );
   }
 
   if (typeof value === 'string') {
     const valueInfo = analyzeStringForRepr(value);
 
-    const valueToBeReturned = withAnnotatedText ? (
+    const annotatedValue = withAnnotatedText ? (
       <AnnotatedText value={valueInfo.repr} meta={meta?.[''] ?? meta} />
     ) : (
       valueInfo.repr
     );
 
-    const out = [
-      <span
-        key="value"
-        className={
-          (valueInfo.isString ? 'val-string' : '') +
-          (valueInfo.isStripped ? ' val-stripped' : '') +
-          (valueInfo.isMultiLine ? ' val-string-multiline' : '')
-        }
-      >
-        {preserveQuotes ? `"${valueToBeReturned}"` : valueToBeReturned}
-      </span>,
-    ];
-
-    if (valueInfo.isString && isUrl(value)) {
-      out.push(
-        <ExternalLink key="external" href={value} className="external-icon">
-          <StyledIconOpen size="xs" aria-label={t('Open link')} />
-        </ExternalLink>
+    const printedValue = preserveQuotes ? `"${annotatedValue}"` : annotatedValue;
+
+    if (valueInfo.isStripped) {
+      return <ValueStrippedString>{printedValue}</ValueStrippedString>;
+    }
+
+    if (valueInfo.isMultiLine) {
+      return (
+        <ValueMultiLineString>
+          {printedValue}
+          <LinkHint value={value} />
+        </ValueMultiLineString>
       );
     }
 
-    return out;
+    return (
+      <span>
+        {printedValue}
+        <LinkHint value={value} />
+      </span>
+    );
   }
 
   if (isNumber(value)) {
@@ -100,11 +111,10 @@ function walk({
       );
     return <span>{valueToBeReturned}</span>;
   }
-
   if (Array.isArray(value)) {
     for (i = 0; i < value.length; i++) {
       children.push(
-        <span className="val-array-item" key={i}>
+        <div key={i}>
           {walk({
             value: value[i],
             depth: depth + 1,
@@ -113,39 +123,31 @@ function walk({
             jsonConsts,
             meta: meta?.[i]?.[''] ?? meta?.[i] ?? meta?.[''] ?? meta,
           })}
-          {i < value.length - 1 ? <span className="val-array-sep">{', '}</span> : null}
-        </span>
+          {i < value.length - 1 ? <span>{', '}</span> : null}
+        </div>
       );
     }
     return (
-      <span className="val-array">
-        <span className="val-array-marker">{'['}</span>
-        <Toggle highUp={depth <= maxDepth} wrapClassName="val-array-items">
-          {children}
-        </Toggle>
-        <span className="val-array-marker">{']'}</span>
+      <span>
+        <span>{'['}</span>
+        <Toggle highUp={depth <= maxDepth}>{children}</Toggle>
+        <span>{']'}</span>
       </span>
     );
   }
-
   if (isValidElement(value)) {
     return value;
   }
-
   const keys = Object.keys(value);
-
   keys.sort(naturalCaseInsensitiveSort);
-
   for (i = 0; i < keys.length; i++) {
     const key = keys[i];
 
     children.push(
-      <span className="val-dict-pair" key={key}>
-        <span className="val-dict-key">
-          <span className="val-string">{preserveQuotes ? `"${key}"` : key}</span>
-        </span>
-        <span className="val-dict-col">{': '}</span>
-        <span className="val-dict-value">
+      <div key={key}>
+        <ValueObjectKey>{preserveQuotes ? `"${key}"` : key}</ValueObjectKey>
+        <span>{': '}</span>
+        <span>
           {walk({
             value: value[key],
             depth: depth + 1,
@@ -154,19 +156,17 @@ function walk({
             jsonConsts,
             meta: meta?.[key]?.[''] ?? meta?.[key] ?? meta?.[''] ?? meta,
           })}
-          {i < keys.length - 1 ? <span className="val-dict-sep">{', '}</span> : null}
+          {i < keys.length - 1 ? <span>{', '}</span> : null}
         </span>
-      </span>
+      </div>
     );
   }
 
   return (
-    <span className="val-dict">
-      <span className="val-dict-marker">{'{'}</span>
-      <Toggle highUp={depth <= maxDepth - 1} wrapClassName="val-dict-items">
-        {children}
-      </Toggle>
-      <span className="val-dict-marker">{'}'}</span>
+    <span>
+      <span>{'{'}</span>
+      <Toggle highUp={depth <= maxDepth - 1}>{children}</Toggle>
+      <span>{'}'}</span>
     </span>
   );
 }
@@ -203,3 +203,30 @@ const StyledIconOpen = styled(IconOpen)`
   position: relative;
   top: 1px;
 `;
+
+const ValueNull = styled('span')`
+  font-weight: bold;
+  color: var(--prism-property);
+`;
+
+const ValueBoolean = styled('span')`
+  font-weight: bold;
+  color: var(--prism-property);
+`;
+
+const ValueMultiLineString = styled('span')`
+  color: var(--prism-selector);
+  display: block;
+  overflow: auto;
+  border-radius: 4px;
+  padding: 2px 4px;
+`;
+
+const ValueStrippedString = styled('span')`
+  font-weight: bold;
+  color: var(--prism-keyword);
+`;
+
+const ValueObjectKey = styled('span')`
+  color: var(--prism-keyword);
+`;

+ 7 - 3
static/app/components/contextData/toggle.tsx

@@ -7,17 +7,16 @@ import {t} from 'sentry/locale';
 type Props = {
   children: React.ReactNode;
   highUp: boolean;
-  wrapClassName: string;
 };
 
-function Toggle({highUp, wrapClassName, children}: Props) {
+function Toggle({highUp, children}: Props) {
   const [isExpanded, setIsExpanded] = useState(false);
 
   if (Children.count(children) === 0) {
     return null;
   }
 
-  const wrappedChildren = <span className={wrapClassName}>{children}</span>;
+  const wrappedChildren = <ValueWrapper>{children}</ValueWrapper>;
 
   if (highUp) {
     return wrappedChildren;
@@ -69,3 +68,8 @@ const IconWrapper = styled('div')<{isExpanded: boolean}>`
           }
         `}
 `;
+
+const ValueWrapper = styled('span')`
+  display: block;
+  padding: 0 0 0 15px;
+`;

+ 0 - 42
static/less/group-detail.less

@@ -783,48 +783,6 @@ span.val {
   overflow: auto;
 }
 
-.val-stripped {
-  color: darken(@red, 10);
-  background: transparent;
-}
-
-.val-bool,
-.val-null {
-  color: darken(@blue, 10);
-  font-weight: bold;
-}
-
-.val-dict {
-  display: inline;
-
-  .val-dict-items {
-    display: block;
-    padding: 0 0 0 15px;
-
-    .val-dict-pair {
-      display: block;
-    }
-  }
-
-  .val-dict-key,
-  .val-dict-key .val-string {
-    color: darken(@red, 5);
-    background: transparent;
-    border-radius: none;
-  }
-}
-
-.val-array {
-  .val-array-items {
-    display: block;
-    padding: 0 0 0 15px;
-
-    .val-array-item {
-      display: block;
-    }
-  }
-}
-
 /**
 * Exceptions and Threads
 * ============================================================================