theme.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. import {css} from '@emotion/react';
  2. import color from 'color';
  3. import {DATA_CATEGORY_INFO} from 'sentry/constants';
  4. import {CHART_PALETTE} from 'sentry/constants/chartPalette';
  5. import {Outcome} from 'sentry/types';
  6. /**
  7. * Exporting for use in Storybook only. Do not import this
  8. * anywhere else! Instead, use the theme prop or import useTheme.
  9. */
  10. export const lightColors = {
  11. black: '#1D1127',
  12. white: '#FFFFFF',
  13. surface100: '#F5F3F7',
  14. surface200: '#FAF9FB',
  15. surface300: '#FFFFFF',
  16. surface400: '#FFFFFF',
  17. /**
  18. * Hover color. Deprecated – use <InteractionStateLayer /> instead for interaction
  19. * (hover/press) states.
  20. * @deprecated
  21. */
  22. surface500: '#F5F3F7',
  23. gray500: '#2B2233',
  24. gray400: '#3E3446',
  25. gray300: '#80708F',
  26. gray200: '#DBD6E1',
  27. gray100: '#EBE6EF',
  28. /**
  29. * Alternative version of gray200 that's translucent.
  30. * Useful for borders on tooltips, popovers, and dialogs.
  31. */
  32. translucentGray200: 'rgba(58, 17, 95, 0.18)',
  33. translucentGray100: 'rgba(45, 0, 85, 0.1)',
  34. purple400: '#584AC0',
  35. purple300: '#6C5FC7',
  36. purple200: 'rgba(108, 95, 199, 0.5)',
  37. purple100: 'rgba(108, 95, 199, 0.08)',
  38. blue400: '#2562D4',
  39. blue300: '#3C74DD',
  40. blue200: 'rgba(60, 116, 221, 0.5)',
  41. blue100: 'rgba(60, 116, 221, 0.09)',
  42. green400: '#268D75',
  43. green300: '#2BA185',
  44. green200: 'rgba(43, 161, 133, 0.55)',
  45. green100: 'rgba(43, 161, 133, 0.13)',
  46. yellow400: '#E5A500',
  47. yellow300: '#F5B000',
  48. yellow200: 'rgba(245, 176, 0, 0.55)',
  49. yellow100: 'rgba(245, 176, 0, 0.08)',
  50. red400: '#DF3338',
  51. red300: '#F55459',
  52. red200: 'rgba(245, 84, 89, 0.5)',
  53. red100: 'rgba(245, 84, 89, 0.09)',
  54. pink400: '#E50675',
  55. pink300: '#F14499',
  56. pink200: 'rgba(249, 26, 138, 0.5)',
  57. pink100: 'rgba(249, 26, 138, 0.1)',
  58. };
  59. /**
  60. * Exporting for use in Storybook only. Do not import this
  61. * anywhere else! Instead, use the theme prop or import useTheme.
  62. */
  63. export const darkColors = {
  64. black: '#1D1127',
  65. white: '#FFFFFF',
  66. surface100: '#18121C',
  67. surface200: '#1A141F',
  68. surface300: '#241D2A',
  69. surface400: '#2C2433',
  70. /**
  71. * Hover color. Deprecated – use <InteractionStateLayer /> instead for interaction
  72. * (hover/press) states.
  73. * @deprecated
  74. */
  75. surface500: '#362E3E',
  76. gray500: '#EBE6EF',
  77. gray400: '#D6D0DC',
  78. gray300: '#998DA5',
  79. gray200: '#43384C',
  80. gray100: '#342B3B',
  81. /**
  82. * Alternative version of gray200 that's translucent.
  83. * Useful for borders on tooltips, popovers, and dialogs.
  84. */
  85. translucentGray200: 'rgba(218, 184, 245, 0.18)',
  86. translucentGray100: 'rgba(208, 168, 240, 0.1)',
  87. purple400: '#A397F7',
  88. purple300: '#7669D3',
  89. purple200: 'rgba(118, 105, 211, 0.27)',
  90. purple100: 'rgba(118, 105, 211, 0.12)',
  91. blue400: '#70A2FF',
  92. blue300: '#3070E8',
  93. blue200: 'rgba(48, 112, 232, 0.25)',
  94. blue100: 'rgba(48, 112, 232, 0.12)',
  95. green400: '#1AB792',
  96. green300: '#1D876E',
  97. green200: 'rgba(29, 135, 110, 0.3)',
  98. green100: 'rgba(29, 135, 110, 0.14)',
  99. yellow400: '#E5A500',
  100. yellow300: '#B28000',
  101. yellow200: 'rgba(178, 128, 0, 0.25)',
  102. yellow100: 'rgba(178, 128, 0, 0.1)',
  103. red400: '#F87277',
  104. red300: '#E12D33',
  105. red200: 'rgba(225, 45, 51, 0.25)',
  106. red100: 'rgba(225, 45, 51, 0.12)',
  107. pink400: '#E674AD',
  108. pink300: '#CE3B85',
  109. pink200: 'rgba(206, 59, 133, 0.25)',
  110. pink100: 'rgba(206, 59, 133, 0.1)',
  111. };
  112. const prismLight = {
  113. '--prism-base': '#332B3B',
  114. '--prism-selected': '#E9E0EB',
  115. '--prism-inline-code': '#D25F7C',
  116. '--prism-inline-code-background': '#F8F9FB',
  117. '--prism-highlight-background': '#E8ECF2',
  118. '--prism-highlight-accent': '#C7CBD1',
  119. '--prism-comment': '#72697C',
  120. '--prism-punctuation': '#70697C',
  121. '--prism-property': '#7A6229',
  122. '--prism-selector': '#3C774A',
  123. '--prism-operator': '#635D6F',
  124. '--prism-variable': '#A8491A',
  125. '--prism-function': '#106A9E',
  126. '--prism-keyword': '#A7114A',
  127. };
  128. const prismDark = {
  129. '--prism-base': '#F2EDF6',
  130. '--prism-selected': '#865891',
  131. '--prism-inline-code': '#D25F7C',
  132. '--prism-inline-code-background': '#F8F9FB',
  133. '--prism-highlight-background': '#382F5C',
  134. '--prism-highlight-accent': '#D25F7C',
  135. '--prism-comment': '#8B7A9E',
  136. '--prism-punctuation': '#B3ACC1',
  137. '--prism-property': '#EAB944',
  138. '--prism-selector': '#7EBE8E',
  139. '--prism-operator': '#A470A7',
  140. '--prism-variable': '#E58759',
  141. '--prism-function': '#6CC5F9',
  142. '--prism-keyword': '#E386AA',
  143. };
  144. const lightShadows = {
  145. dropShadowLight: '0 0 1px rgba(43, 34, 51, 0.04)',
  146. dropShadowMedium: '0 1px 2px rgba(43, 34, 51, 0.04)',
  147. dropShadowHeavy: '0 4px 24px rgba(43, 34, 51, 0.12)',
  148. };
  149. const darkShadows = {
  150. dropShadowLight: '0 0 1px rgba(10, 8, 12, 0.2)',
  151. dropShadowMedium: '0 1px 2px rgba(10, 8, 12, 0.2)',
  152. dropShadowHeavy: '0 4px 24px rgba(10, 8, 12, 0.36)',
  153. };
  154. /**
  155. * Background used in the theme-color meta tag
  156. * The colors below are an approximation of the colors used in the sidebar (sidebarGradient).
  157. * Unfortunately the exact colors cannot be used, as the theme-color tag does not support linear-gradient()
  158. */
  159. const sidebarBackground = {
  160. light: '#2f1937',
  161. dark: '#181622',
  162. };
  163. type BaseColors = typeof lightColors;
  164. const generateAliases = (colors: BaseColors) => ({
  165. /**
  166. * Heading text color
  167. */
  168. headingColor: colors.gray500,
  169. /**
  170. * Primary text color
  171. */
  172. textColor: colors.gray400,
  173. /**
  174. * Text that should not have as much emphasis
  175. */
  176. subText: colors.gray300,
  177. /**
  178. * Background for the main content area of a page?
  179. */
  180. bodyBackground: colors.surface200,
  181. /**
  182. * Primary background color
  183. */
  184. background: colors.surface300,
  185. /**
  186. * Elevated background color
  187. */
  188. backgroundElevated: colors.surface400,
  189. /**
  190. * Secondary background color used as a slight contrast against primary background
  191. */
  192. backgroundSecondary: colors.surface200,
  193. /**
  194. * Tertiary background color used as a stronger contrast against primary background
  195. */
  196. backgroundTertiary: colors.surface100,
  197. /**
  198. * Background for the header of a page
  199. */
  200. headerBackground: colors.surface300,
  201. /**
  202. * Primary border color
  203. */
  204. border: colors.gray200,
  205. translucentBorder: colors.translucentGray200,
  206. /**
  207. * Inner borders, e.g. borders inside of a grid
  208. */
  209. innerBorder: colors.gray100,
  210. translucentInnerBorder: colors.translucentGray100,
  211. /**
  212. * A color that denotes a "success", or something good
  213. */
  214. success: colors.green300,
  215. successText: colors.green400,
  216. /**
  217. * A color that denotes an error, or something that is wrong
  218. */
  219. error: colors.red300,
  220. errorText: colors.red400,
  221. /**
  222. * A color that denotes danger, for dangerous actions like deletion
  223. */
  224. danger: colors.red300,
  225. dangerText: colors.red400,
  226. /**
  227. * A color that denotes a warning
  228. */
  229. warning: colors.yellow300,
  230. warningText: colors.yellow400,
  231. /**
  232. * A color that indicates something is disabled where user can not interact or use
  233. * it in the usual manner (implies that there is an "enabled" state)
  234. */
  235. disabled: colors.gray300,
  236. disabledBorder: colors.gray200,
  237. /**
  238. * Indicates a "hover" state. Deprecated – use `InteractionStateLayer` instead for
  239. * interaction (hover/press) states.
  240. * @deprecated
  241. */
  242. hover: colors.surface500,
  243. /**
  244. * Indicates that something is "active" or "selected"
  245. */
  246. active: colors.purple300,
  247. activeHover: colors.purple400,
  248. activeText: colors.purple400,
  249. /**
  250. * Indicates that something has "focus", which is different than "active" state as it is more temporal
  251. * and should be a bit subtler than active
  252. */
  253. focus: colors.purple200,
  254. focusBorder: colors.purple300,
  255. /**
  256. * Inactive
  257. */
  258. inactive: colors.gray300,
  259. /**
  260. * Link color indicates that something is clickable
  261. */
  262. linkColor: colors.blue400,
  263. linkHoverColor: colors.blue400,
  264. linkUnderline: colors.blue200,
  265. linkFocus: colors.blue300,
  266. /**
  267. * Form placeholder text color
  268. */
  269. formPlaceholder: colors.gray300,
  270. /**
  271. * Default form text color
  272. */
  273. formText: colors.gray400,
  274. /**
  275. *
  276. */
  277. rowBackground: colors.surface400,
  278. /**
  279. * Color of lines that flow across the background of the chart to indicate axes levels
  280. * (This should only be used for yAxis)
  281. */
  282. chartLineColor: colors.gray100,
  283. /**
  284. * Color for chart label text
  285. */
  286. chartLabel: colors.gray300,
  287. /**
  288. * Color for the 'others' series in topEvent charts
  289. */
  290. chartOther: colors.gray200,
  291. /**
  292. * Default Progressbar color
  293. */
  294. progressBar: colors.purple300,
  295. /**
  296. * Default Progressbar color
  297. */
  298. progressBackground: colors.gray100,
  299. /**
  300. * Overlay for partial opacity
  301. */
  302. overlayBackgroundAlpha: color(colors.surface200).alpha(0.7).string(),
  303. /**
  304. * Tag progress bars
  305. */
  306. tagBarHover: colors.purple200,
  307. tagBar: colors.gray200,
  308. /**
  309. * Search filter "token" background
  310. */
  311. searchTokenBackground: {
  312. valid: colors.blue100,
  313. validActive: color(colors.blue100).opaquer(1.0).string(),
  314. invalid: colors.red100,
  315. invalidActive: color(colors.red100).opaquer(0.8).string(),
  316. },
  317. /**
  318. * Search filter "token" border
  319. */
  320. searchTokenBorder: {
  321. valid: colors.blue200,
  322. validActive: color(colors.blue200).opaquer(1).string(),
  323. invalid: colors.red200,
  324. invalidActive: color(colors.red200).opaquer(1).string(),
  325. },
  326. /**
  327. * Count on button when active
  328. */
  329. buttonCountActive: colors.white,
  330. /**
  331. * Count on button
  332. */
  333. buttonCount: colors.gray500,
  334. /**
  335. * Background of alert banners at the top
  336. */
  337. bannerBackground: colors.gray500,
  338. });
  339. const dataCategory = {
  340. [DATA_CATEGORY_INFO.error.plural]: CHART_PALETTE[4][3],
  341. [DATA_CATEGORY_INFO.transaction.plural]: CHART_PALETTE[4][2],
  342. [DATA_CATEGORY_INFO.attachment.plural]: CHART_PALETTE[4][1],
  343. [DATA_CATEGORY_INFO.replay.plural]: CHART_PALETTE[4][4],
  344. };
  345. /**
  346. * Default colors for data usage outcomes
  347. */
  348. const outcome = {
  349. [Outcome.ACCEPTED]: CHART_PALETTE[0][0],
  350. [Outcome.FILTERED]: CHART_PALETTE[1][1],
  351. [Outcome.DROPPED]: CHART_PALETTE[5][3],
  352. };
  353. const generateAlertTheme = (colors: BaseColors, alias: Aliases) => ({
  354. muted: {
  355. background: colors.gray200,
  356. backgroundLight: alias.backgroundSecondary,
  357. border: alias.border,
  358. borderHover: alias.border,
  359. iconColor: 'inherit',
  360. iconHoverColor: 'inherit',
  361. },
  362. info: {
  363. background: colors.blue300,
  364. backgroundLight: colors.blue100,
  365. border: colors.blue200,
  366. borderHover: colors.blue300,
  367. iconColor: colors.blue400,
  368. iconHoverColor: colors.blue400,
  369. },
  370. warning: {
  371. background: colors.yellow300,
  372. backgroundLight: colors.yellow100,
  373. border: colors.yellow200,
  374. borderHover: colors.yellow300,
  375. iconColor: colors.yellow400,
  376. iconHoverColor: colors.yellow400,
  377. },
  378. success: {
  379. background: colors.green300,
  380. backgroundLight: colors.green100,
  381. border: colors.green200,
  382. borderHover: colors.green300,
  383. iconColor: colors.green400,
  384. iconHoverColor: colors.green400,
  385. },
  386. error: {
  387. background: colors.red300,
  388. backgroundLight: colors.red100,
  389. border: colors.red200,
  390. borderHover: colors.red300,
  391. iconColor: colors.red400,
  392. iconHoverColor: colors.red400,
  393. textLight: colors.red200,
  394. },
  395. });
  396. const generateBadgeTheme = (colors: BaseColors) => ({
  397. default: {
  398. background: colors.gray100,
  399. indicatorColor: colors.gray100,
  400. color: colors.gray500,
  401. },
  402. alpha: {
  403. background: `linear-gradient(90deg, ${colors.pink300}, ${colors.yellow300})`,
  404. indicatorColor: colors.pink300,
  405. color: colors.white,
  406. },
  407. beta: {
  408. background: `linear-gradient(90deg, ${colors.purple300}, ${colors.pink300})`,
  409. indicatorColor: colors.purple300,
  410. color: colors.white,
  411. },
  412. new: {
  413. background: `linear-gradient(90deg, ${colors.blue300}, ${colors.green300})`,
  414. indicatorColor: colors.green300,
  415. color: colors.white,
  416. },
  417. experimental: {
  418. background: colors.gray100,
  419. indicatorColor: colors.gray100,
  420. color: colors.gray500,
  421. },
  422. warning: {
  423. background: colors.yellow300,
  424. indicatorColor: colors.yellow300,
  425. color: colors.gray500,
  426. },
  427. });
  428. const generateTagTheme = (colors: BaseColors) => ({
  429. default: {
  430. background: colors.surface400,
  431. border: colors.gray200,
  432. iconColor: colors.gray300,
  433. },
  434. promotion: {
  435. background: colors.pink100,
  436. border: colors.pink200,
  437. iconColor: colors.pink400,
  438. },
  439. highlight: {
  440. background: colors.purple100,
  441. border: colors.purple200,
  442. iconColor: colors.purple400,
  443. },
  444. warning: {
  445. background: colors.yellow100,
  446. border: colors.yellow200,
  447. iconColor: colors.yellow400,
  448. },
  449. success: {
  450. background: colors.green100,
  451. border: colors.green200,
  452. iconColor: colors.green400,
  453. },
  454. error: {
  455. background: colors.red100,
  456. border: colors.red200,
  457. iconColor: colors.red400,
  458. },
  459. info: {
  460. background: colors.purple100,
  461. border: colors.purple200,
  462. iconColor: colors.purple400,
  463. },
  464. white: {
  465. background: colors.white,
  466. border: colors.white,
  467. iconColor: colors.black,
  468. },
  469. black: {
  470. background: colors.black,
  471. border: colors.black,
  472. iconColor: colors.white,
  473. },
  474. });
  475. const generateLevelTheme = (colors: BaseColors) => ({
  476. sample: colors.purple300,
  477. info: colors.blue300,
  478. warning: colors.yellow300,
  479. // Hardcoded legacy color (orange400). We no longer use orange anywhere
  480. // else in the app (except for the chart palette). This needs to be harcoded
  481. // here because existing users may still associate orange with the "error" level.
  482. error: '#FF7738',
  483. fatal: colors.red300,
  484. default: colors.gray300,
  485. unknown: colors.gray200,
  486. });
  487. const generateButtonTheme = (colors: BaseColors, alias: Aliases) => ({
  488. default: {
  489. color: alias.textColor,
  490. colorActive: alias.textColor,
  491. background: alias.background,
  492. backgroundActive: alias.hover,
  493. border: alias.border,
  494. borderActive: alias.border,
  495. borderTranslucent: alias.translucentBorder,
  496. focusBorder: alias.focusBorder,
  497. focusShadow: alias.focus,
  498. },
  499. primary: {
  500. color: colors.white,
  501. colorActive: colors.white,
  502. background: colors.purple300,
  503. backgroundActive: colors.purple400,
  504. border: colors.purple300,
  505. borderActive: colors.purple300,
  506. borderTranslucent: colors.purple300,
  507. focusBorder: alias.focusBorder,
  508. focusShadow: alias.focus,
  509. },
  510. danger: {
  511. color: colors.white,
  512. colorActive: colors.white,
  513. background: colors.red300,
  514. backgroundActive: colors.red400,
  515. border: colors.red300,
  516. borderActive: colors.red300,
  517. borderTranslucent: colors.red300,
  518. focusBorder: colors.red300,
  519. focusShadow: colors.red200,
  520. },
  521. link: {
  522. color: alias.linkColor,
  523. colorActive: alias.linkHoverColor,
  524. background: 'transparent',
  525. backgroundActive: 'transparent',
  526. border: 'transparent',
  527. borderActive: 'transparent',
  528. borderTranslucent: 'transparent',
  529. focusBorder: alias.focusBorder,
  530. focusShadow: alias.focus,
  531. },
  532. disabled: {
  533. color: alias.disabled,
  534. colorActive: alias.disabled,
  535. background: alias.background,
  536. backgroundActive: alias.background,
  537. border: alias.disabledBorder,
  538. borderActive: alias.disabledBorder,
  539. borderTranslucent: alias.translucentInnerBorder,
  540. focusBorder: 'transparent',
  541. focusShadow: 'transparent',
  542. },
  543. });
  544. const generateUtils = (colors: BaseColors, aliases: Aliases) => ({
  545. tooltipUnderline: (underlineColor: ColorOrAlias = 'gray300') => ({
  546. textDecoration: `underline dotted ${
  547. colors[underlineColor] ?? aliases[underlineColor]
  548. }`,
  549. textDecorationThickness: '0.75px',
  550. textUnderlineOffset: '1.25px',
  551. }),
  552. overflowEllipsis: css({
  553. display: 'block',
  554. width: '100%',
  555. whiteSpace: 'nowrap',
  556. overflow: 'hidden',
  557. textOverflow: 'ellipsis',
  558. }),
  559. });
  560. const generatePrismVariables = (
  561. prismColors: typeof prismLight,
  562. blockBackground: string
  563. ) =>
  564. css({
  565. // block background differs based on light/dark mode
  566. '--prism-block-background': blockBackground,
  567. ...prismColors,
  568. });
  569. const iconSizes = {
  570. xs: '12px',
  571. sm: '16px',
  572. md: '20px',
  573. lg: '24px',
  574. xl: '32px',
  575. xxl: '72px',
  576. };
  577. const commonTheme = {
  578. breakpoints: {
  579. small: '800px',
  580. medium: '992px',
  581. large: '1200px',
  582. xlarge: '1440px',
  583. xxlarge: '2560px',
  584. },
  585. ...lightColors,
  586. ...lightShadows,
  587. iconSizes,
  588. iconDirections: {
  589. up: '0',
  590. right: '90',
  591. down: '180',
  592. left: '270',
  593. },
  594. // Try to keep these ordered plz
  595. zIndex: {
  596. // Generic z-index when you hope your component is isolated and
  597. // does not need to battle others for z-index priority
  598. initial: 1,
  599. truncationFullValue: 10,
  600. traceView: {
  601. spanTreeToggler: 900,
  602. dividerLine: 909,
  603. rowInfoMessage: 910,
  604. minimapContainer: 999,
  605. },
  606. header: 1000,
  607. errorMessage: 1000,
  608. dropdown: 1001,
  609. dropdownAutocomplete: {
  610. // needs to be below actor but above other page elements (e.g. pagination)
  611. // (e.g. Issue Details "seen" dots on chart is 2)
  612. // stream header is 1000
  613. menu: 1007,
  614. // needs to be above menu
  615. actor: 1008,
  616. },
  617. globalSelectionHeader: 1009,
  618. settingsSidebarNavMask: 1017,
  619. settingsSidebarNav: 1018,
  620. sidebarPanel: 1019,
  621. sidebar: 1020,
  622. orgAndUserMenu: 1030,
  623. // Sentry user feedback modal
  624. sentryErrorEmbed: 1090,
  625. // If you change modal also update shared-components.less
  626. // as the z-index for bootstrap modals lives there.
  627. modal: 10000,
  628. toast: 10001,
  629. // tooltips and hovercards can be inside modals sometimes.
  630. hovercard: 10002,
  631. tooltip: 10003,
  632. // On mobile views issue list dropdowns overlap
  633. issuesList: {
  634. stickyHeader: 1,
  635. sortOptions: 2,
  636. displayOptions: 3,
  637. },
  638. },
  639. grid: 8,
  640. borderRadius: '6px',
  641. borderRadiusBottom: '0 0 6px 6px',
  642. borderRadiusTop: '6px 6px 0 0',
  643. borderRadiusLeft: '6px 0 0 6px',
  644. borderRadiusRight: '0 6px 6px 0',
  645. panelBorderRadius: '6px',
  646. modalBorderRadius: '8px',
  647. linkBorderRadius: '2px',
  648. headerSelectorRowHeight: 44,
  649. headerSelectorLabelHeight: 28,
  650. // Relative font sizes
  651. fontSizeRelativeSmall: '0.9em',
  652. fontSizeExtraSmall: '11px',
  653. fontSizeSmall: '12px',
  654. fontSizeMedium: '14px',
  655. fontSizeLarge: '16px',
  656. fontSizeExtraLarge: '18px',
  657. codeFontSize: '13px',
  658. headerFontSize: '22px',
  659. settings: {
  660. // Max-width for settings breadcrumbs
  661. // i.e. organization, project, or team
  662. maxCrumbWidth: '240px',
  663. containerWidth: '1440px',
  664. headerHeight: '61px',
  665. sidebarWidth: '220px',
  666. },
  667. sidebar: {
  668. boxShadow: '0 3px 3px #2f2936',
  669. color: '#9586a5',
  670. divider: '#493e54',
  671. badgeSize: '22px',
  672. smallBadgeSize: '11px',
  673. collapsedWidth: '70px',
  674. expandedWidth: '220px',
  675. mobileHeight: '54px',
  676. menuSpacing: '15px',
  677. },
  678. text: {
  679. family: "'Rubik', 'Avenir Next', sans-serif",
  680. familyMono: "'Roboto Mono', Monaco, Consolas, 'Courier New', monospace",
  681. lineHeightHeading: 1.2,
  682. lineHeightBody: 1.4,
  683. pageTitle: {
  684. fontSize: '1.625rem',
  685. fontWeight: 600,
  686. letterSpacing: '-0.01em',
  687. lineHeight: 1.2,
  688. },
  689. cardTitle: {
  690. fontSize: '1rem',
  691. fontWeight: 600,
  692. lineHeight: 1.2,
  693. },
  694. },
  695. /**
  696. * Common styles for form inputs & buttons, separated by size.
  697. * Should be used to ensure consistent sizing among form elements.
  698. */
  699. form: {
  700. md: {
  701. height: 38,
  702. minHeight: 38,
  703. fontSize: '0.875rem',
  704. lineHeight: '1rem',
  705. },
  706. sm: {
  707. height: 32,
  708. minHeight: 32,
  709. fontSize: '0.875rem',
  710. lineHeight: '1rem',
  711. },
  712. xs: {
  713. height: 26,
  714. minHeight: 26,
  715. fontSize: '0.75rem',
  716. lineHeight: '0.875rem',
  717. },
  718. },
  719. /**
  720. * Padding for buttons
  721. */
  722. buttonPadding: {
  723. md: {
  724. paddingLeft: 16,
  725. paddingRight: 16,
  726. paddingTop: 10,
  727. paddingBottom: 10,
  728. },
  729. sm: {
  730. paddingLeft: 12,
  731. paddingRight: 12,
  732. paddingTop: 8,
  733. paddingBottom: 8,
  734. },
  735. xs: {
  736. paddingLeft: 8,
  737. paddingRight: 8,
  738. paddingTop: 6,
  739. paddingBottom: 6,
  740. },
  741. },
  742. /**
  743. * Padding for form inputs
  744. */
  745. formPadding: {
  746. md: {
  747. paddingLeft: 16,
  748. paddingRight: 12,
  749. paddingTop: 10,
  750. paddingBottom: 10,
  751. },
  752. sm: {
  753. paddingLeft: 12,
  754. paddingRight: 10,
  755. paddingTop: 8,
  756. paddingBottom: 8,
  757. },
  758. xs: {
  759. paddingLeft: 8,
  760. paddingRight: 6,
  761. paddingTop: 6,
  762. paddingBottom: 6,
  763. },
  764. },
  765. dataCategory,
  766. outcome,
  767. tag: generateTagTheme(lightColors),
  768. level: generateLevelTheme(lightColors),
  769. charts: {
  770. colors: CHART_PALETTE[CHART_PALETTE.length - 1],
  771. // We have an array that maps `number + 1` --> list of `number` colors
  772. getColorPalette: (length: number) =>
  773. CHART_PALETTE[Math.min(CHART_PALETTE.length - 1, length + 1)] as string[],
  774. previousPeriod: lightColors.gray200,
  775. symbolSize: 6,
  776. },
  777. diff: {
  778. removedRow: 'hsl(358deg 89% 65% / 15%)',
  779. removed: 'hsl(358deg 89% 65% / 30%)',
  780. addedRow: 'hsl(100deg 100% 87% / 18%)',
  781. added: 'hsl(166deg 58% 47% / 32%)',
  782. },
  783. // Similarity spectrum used in "Similar Issues" in group details
  784. similarity: {
  785. empty: '#e2dee6',
  786. colors: ['#ec5e44', '#f38259', '#f9a66d', '#98b480', '#57be8c'],
  787. },
  788. // used as a gradient,
  789. businessIconColors: ['#EA5BC2', '#6148CE'],
  790. demo: {
  791. headerSize: '70px',
  792. },
  793. };
  794. const lightAliases = generateAliases(lightColors);
  795. const darkAliases = generateAliases(darkColors);
  796. export const lightTheme = {
  797. ...commonTheme,
  798. ...lightColors,
  799. ...lightAliases,
  800. ...lightShadows,
  801. inverted: {
  802. ...darkColors,
  803. ...darkAliases,
  804. },
  805. ...generateUtils(lightColors, lightAliases),
  806. alert: generateAlertTheme(lightColors, lightAliases),
  807. badge: generateBadgeTheme(lightColors),
  808. button: generateButtonTheme(lightColors, lightAliases),
  809. tag: generateTagTheme(lightColors),
  810. level: generateLevelTheme(lightColors),
  811. stacktraceActiveBackground: lightColors.gray500,
  812. stacktraceActiveText: lightColors.white,
  813. prismVariables: generatePrismVariables(prismLight, lightAliases.backgroundSecondary),
  814. prismDarkVariables: generatePrismVariables(prismDark, darkAliases.backgroundElevated),
  815. sidebar: {
  816. ...commonTheme.sidebar,
  817. background: sidebarBackground.light,
  818. },
  819. sidebarGradient: `linear-gradient(294.17deg,${sidebarBackground.light} 35.57%,#452650 92.42%,#452650 92.42%)`,
  820. sidebarBorder: 'transparent',
  821. };
  822. export const darkTheme: Theme = {
  823. ...commonTheme,
  824. ...darkColors,
  825. ...darkAliases,
  826. ...darkShadows,
  827. inverted: {
  828. ...lightColors,
  829. ...lightAliases,
  830. },
  831. ...generateUtils(darkColors, lightAliases),
  832. alert: generateAlertTheme(darkColors, darkAliases),
  833. badge: generateBadgeTheme(darkColors),
  834. button: generateButtonTheme(darkColors, darkAliases),
  835. tag: generateTagTheme(darkColors),
  836. level: generateLevelTheme(darkColors),
  837. prismVariables: generatePrismVariables(prismDark, darkAliases.backgroundSecondary),
  838. prismDarkVariables: generatePrismVariables(prismDark, darkAliases.backgroundSecondary),
  839. stacktraceActiveBackground: darkColors.gray200,
  840. stacktraceActiveText: darkColors.white,
  841. sidebar: {
  842. ...commonTheme.sidebar,
  843. background: sidebarBackground.dark,
  844. },
  845. sidebarGradient: `linear-gradient(180deg, ${sidebarBackground.dark} 0%, #1B1825 100%)`,
  846. sidebarBorder: darkAliases.border,
  847. };
  848. type Theme = typeof lightTheme;
  849. export type Color = keyof typeof lightColors;
  850. export type Aliases = typeof lightAliases;
  851. export type ColorOrAlias = keyof Aliases | Color;
  852. export type IconSize = keyof typeof iconSizes;
  853. export type FormSize = keyof Theme['form'];
  854. export default commonTheme;
  855. // Be clear about what the [@emotion/React].THeme is extending
  856. type SentryTheme = Theme;
  857. /**
  858. * Configure Emotion to use our theme
  859. */
  860. declare module '@emotion/react' {
  861. // eslint-disable-next-line @typescript-eslint/no-shadow
  862. export interface Theme extends SentryTheme {}
  863. }
  864. // This should never be used directly (except in storybook)
  865. export {lightAliases as aliases};