shared: codemod shared/symbols shared/notifications shared/extensions shared/components/ResultContainer components to CSS modules (#27488)

Co-authored-by: gitstart-sourcegraph <gitstart@users.noreply.github.com>
This commit is contained in:
GitStart-SourceGraph 2021-11-29 10:29:13 +01:00 committed by GitHub
parent 6c934669d6
commit c673f98b2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 218 additions and 199 deletions

View File

@ -1,12 +1,16 @@
.file-locations {
overflow-y: auto;
// adding this temporarily and should be addressed in next css module tickets
:global(.result-container) {
.result-container {
margin-bottom: 0;
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
border-radius: 0;
// ResultContainer Module has this style,
// but the specificity is lesser when it's inside FileLocation
&:not(:last-of-type) {
margin-bottom: 0.5rem;
}
}
}

View File

@ -186,6 +186,7 @@ export class FileLocations extends React.PureComponent<Props, State> {
showAllMatches={true}
fetchHighlightedFileLineRanges={this.props.fetchHighlightedFileLineRanges}
settingsCascade={this.props.settingsCascade}
containerClassName={styles.resultContainer}
/>
)
}

View File

@ -15,13 +15,13 @@ exports[`<HierarchicalLocationsView /> displays a single location when complete
>
<div>
<div
class="test-search-result result-container"
class="test-search-result resultContainer resultContainer"
data-result-type="content"
data-testid="result-container"
role="none"
>
<div
class="result-container__header"
class="header"
>
<svg
class="mdi-icon icon-inline flex-shrink-0"
@ -35,10 +35,10 @@ exports[`<HierarchicalLocationsView /> displays a single location when complete
/>
</svg>
<div
class="result-container__header-divider mx-1"
class="mx-1 headerDivider"
/>
<div
class="result-container__header-title test-search-result-label"
class="headerTitle test-search-result-label"
data-testid="result-container-header"
>
<span
@ -74,7 +74,7 @@ exports[`<HierarchicalLocationsView /> displays a single location when complete
</a>
</div>
<span
class="result-container__header-description ml-2"
class="ml-2 headerDescription"
/>
</div>
<small>
@ -237,13 +237,13 @@ exports[`<HierarchicalLocationsView /> displays multiple locations grouped by fi
>
<div>
<div
class="test-search-result result-container"
class="test-search-result resultContainer resultContainer"
data-result-type="content"
data-testid="result-container"
role="none"
>
<div
class="result-container__header"
class="header"
>
<svg
class="mdi-icon icon-inline flex-shrink-0"
@ -257,10 +257,10 @@ exports[`<HierarchicalLocationsView /> displays multiple locations grouped by fi
/>
</svg>
<div
class="result-container__header-divider mx-1"
class="mx-1 headerDivider"
/>
<div
class="result-container__header-title test-search-result-label"
class="headerTitle test-search-result-label"
data-testid="result-container-header"
>
<span
@ -298,7 +298,7 @@ exports[`<HierarchicalLocationsView /> displays multiple locations grouped by fi
</a>
</div>
<span
class="result-container__header-description ml-2"
class="ml-2 headerDescription"
/>
</div>
<small>
@ -414,13 +414,13 @@ exports[`<HierarchicalLocationsView /> displays partial locations before complet
>
<div>
<div
class="test-search-result result-container"
class="test-search-result resultContainer resultContainer"
data-result-type="content"
data-testid="result-container"
role="none"
>
<div
class="result-container__header"
class="header"
>
<svg
class="mdi-icon icon-inline flex-shrink-0"
@ -434,10 +434,10 @@ exports[`<HierarchicalLocationsView /> displays partial locations before complet
/>
</svg>
<div
class="result-container__header-divider mx-1"
class="mx-1 headerDivider"
/>
<div
class="result-container__header-title test-search-result-label"
class="headerTitle test-search-result-label"
data-testid="result-container-header"
>
<span
@ -473,7 +473,7 @@ exports[`<HierarchicalLocationsView /> displays partial locations before complet
</a>
</div>
<span
class="result-container__header-description ml-2"
class="ml-2 headerDescription"
/>
</div>
<small>

View File

@ -5,10 +5,6 @@
// box that renders the tooltip on GitHub is pure white.
$body-bg-color-light: #ffffff;
@import '../../shared/src/extensions/devtools';
@import '../../shared/src/notifications/NotificationItem';
@import '../../shared/src/notifications/Notifications';
:root {
--body-bg: #ffffff;
--text-muted: #888888;

View File

@ -67,6 +67,11 @@ interface Props extends SettingsCascadeProps, TelemetryProps {
allExpanded?: boolean
fetchHighlightedFileLineRanges: (parameters: FetchFileParameters, force?: boolean) => Observable<string[][]>
/**
* CSS class name to be applied to the ResultContainer Component
*/
containerClassName?: string
}
const sumHighlightRanges = (count: number, item: MatchItem): number => count + item.highlightRanges.length
@ -222,6 +227,7 @@ export const FileMatch: React.FunctionComponent<Props> = props => {
repoStars: result.repoStars,
repoLastFetched: result.repoLastFetched,
onResultClicked: props.onSelect,
className: props.containerClassName,
resultType: result.type,
}
} else {
@ -241,6 +247,7 @@ export const FileMatch: React.FunctionComponent<Props> = props => {
repoStars: result.repoStars,
repoLastFetched: result.repoLastFetched,
onResultClicked: props.onSelect,
className: props.containerClassName,
resultType: result.type,
}
}
@ -257,6 +264,7 @@ export const FileMatch: React.FunctionComponent<Props> = props => {
repoStars: result.repoStars,
repoLastFetched: result.repoLastFetched,
onResultClicked: props.onSelect,
className: props.containerClassName,
resultType: result.type,
}
} else {
@ -276,6 +284,7 @@ export const FileMatch: React.FunctionComponent<Props> = props => {
repoStars: result.repoStars,
repoLastFetched: result.repoLastFetched,
onResultClicked: props.onSelect,
className: props.containerClassName,
resultType: result.type,
}
}

View File

@ -0,0 +1,48 @@
.result-container {
margin-right: 1rem;
&:last-child {
border-bottom-width: 1px;
}
&:not(:last-of-type) {
margin-bottom: 0.5rem;
}
}
.header {
padding: 0.5rem 0.5rem 0.5rem 0;
background-color: transparent;
display: flex;
align-items: center;
white-space: nowrap;
&-title {
flex: 1 1 auto;
overflow: hidden;
display: flex;
}
&-divider {
border-right: 1px solid var(--border-color-2);
height: 1rem;
}
p {
margin-bottom: 0;
}
&:not(:only-of-type) {
border-bottom: none;
}
&-description {
line-height: (14/11);
}
}
.toggle-matches-container {
display: flex;
flex-shrink: 0;
padding: 0;
}

View File

@ -1,47 +0,0 @@
.result-container {
margin-right: 1rem;
&:last-child {
border-bottom-width: 1px;
}
&:not(:last-of-type) {
/* Added important flag here to prevent overide. To be worked on during module migraton. */
margin-bottom: 0.5rem !important;
}
&__header {
padding: 0.5rem 0.5rem 0.5rem 0;
background-color: transparent;
display: flex;
align-items: center;
white-space: nowrap;
&-title {
flex: 1 1 auto;
overflow: hidden;
display: flex;
}
&-divider {
border-right: 1px solid var(--border-color-2);
height: 1rem;
}
p {
margin-bottom: 0;
}
&:not(:only-of-type) {
border-bottom: none;
}
&-description {
line-height: (14/11);
}
}
&__toggle-matches-container {
display: flex;
flex-shrink: 0;
padding: 0;
}
}

View File

@ -166,7 +166,7 @@ describe('ResultContainer', () => {
// 1 is the value of subsetMatches
expect(expandedItems.length).toBe(1)
const button = container.querySelector('.result-container__toggle-matches-container')
const button = container.querySelector('[data-testid="toggle-matches-container"]')
expect(button).toBeVisible()
fireEvent.click(button!)
@ -185,7 +185,7 @@ describe('ResultContainer', () => {
it('displays the collapse label when expanded', () => {
const { container } = render(<ResultContainer {...defaultProps} />)
const button = container.querySelector('.result-container__toggle-matches-container')
const button = container.querySelector('[data-testid="toggle-matches-container"]')
expect(button).toBeVisible()
fireEvent.click(button!)
@ -206,7 +206,7 @@ describe('ResultContainer', () => {
let expandedItems = container.querySelectorAll('[data-testid="file-match-children-item"]')
expect(expandedItems.length).toBe(5)
const button = container.querySelector('.result-container__toggle-matches-container')
const button = container.querySelector('[data-testid="toggle-matches-container"]')
expect(button).toBeVisible()
fireEvent.click(button!)

View File

@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react'
import { formatRepositoryStarCount } from '@sourcegraph/shared/src/util/stars'
import styles from './ResultContainer.module.scss'
import { SearchResultStar } from './SearchResultStar'
export interface Props {
@ -95,6 +96,11 @@ export interface Props {
* Click event for when the result is clicked
*/
onResultClicked?: () => void
/**
* CSS class name to be applied to the component
*/
className?: string
}
/**
@ -115,6 +121,7 @@ export const ResultContainer: React.FunctionComponent<Props> = ({
matchCountLabel,
repoStars,
onResultClicked,
className,
resultType,
}) => {
const [expanded, setExpanded] = useState(allExpanded || defaultExpanded)
@ -136,33 +143,31 @@ export const ResultContainer: React.FunctionComponent<Props> = ({
const Icon = icon
return (
<div
className="test-search-result result-container"
className={classNames('test-search-result', styles.resultContainer, className)}
data-testid="result-container"
data-result-type={resultType}
data-expanded={allExpanded}
onClick={trackReferencePanelClick}
role="none"
>
<div className="result-container__header">
<div className={styles.header}>
<Icon className="icon-inline flex-shrink-0" />
<div className="result-container__header-divider mx-1" />
<div
className={classNames('result-container__header-title', titleClassName)}
data-testid="result-container-header"
>
<div className={classNames('mx-1', styles.headerDivider)} />
<div className={classNames(styles.headerTitle, titleClassName)} data-testid="result-container-header">
{title}
{description && <span className="result-container__header-description ml-2">{description}</span>}
{description && <span className={classNames('ml-2', styles.headerDescription)}>{description}</span>}
</div>
{matchCountLabel && (
<>
<small>{matchCountLabel}</small>
{collapsible && <div className="result-container__header-divider mx-2" />}
{collapsible && <div className={classNames('mx-2', styles.headerDivider)} />}
</>
)}
{collapsible && (
<button
type="button"
className="result-container__toggle-matches-container btn btn-sm btn-link py-0"
data-testid="toggle-matches-container"
className={classNames('btn btn-sm btn-link py-0', styles.toggleMatchesContainer)}
onClick={toggle}
>
{expanded ? (
@ -181,7 +186,7 @@ export const ResultContainer: React.FunctionComponent<Props> = ({
</button>
)}
{matchCountLabel && formattedRepositoryStarCount && (
<div className="result-container__header-divider mx-2" />
<div className={classNames('mx-2', styles.headerDivider)} />
)}
{formattedRepositoryStarCount && (
<>

View File

@ -2,6 +2,6 @@
min-width: 24vw;
max-width: 50vw;
min-height: 27rem; // avoid jitter when only loading indicator is shown
min-height: 27rem; /* avoid jitter when only loading indicator is shown */
max-height: 70vh;
}

View File

@ -1,4 +1,5 @@
import { Tab, TabList, TabPanel, TabPanels, Tabs } from '@reach/tabs'
import classNames from 'classnames'
import MenuUpIcon from 'mdi-react/MenuUpIcon'
import React, { useCallback } from 'react'
import { UncontrolledPopover } from 'reactstrap'
@ -8,6 +9,7 @@ import { useLocalStorage } from '../../util/useLocalStorage'
import { ExtensionsControllerProps } from '../controller'
import { ActiveExtensionsPanel } from './ActiveExtensionsPanel'
import styles from './index.module.scss'
export interface ExtensionsDevelopmentToolsProps
extends ExtensionsControllerProps,
@ -34,7 +36,11 @@ const ExtensionDevelopmentTools: React.FunctionComponent<ExtensionsDevelopmentTo
const handleTabsChange = useCallback((index: number) => setTabIndex(index), [setTabIndex])
return (
<Tabs defaultIndex={tabIndex} className="extension-status card border-0 rounded-0" onChange={handleTabsChange}>
<Tabs
defaultIndex={tabIndex}
className={classNames('card border-0 rounded-0', styles.extensionStatus)}
onChange={handleTabsChange}
>
<div className="tablist-wrapper w-100 align-items-center">
<TabList>
{TABS.map(({ label, id }) => (

View File

@ -1,5 +0,0 @@
@import './components/ResultContainer';
@import './extensions/devtools';
@import './notifications/NotificationItem';
@import './notifications/Notifications';
@import './symbols/SymbolIcon';

View File

@ -0,0 +1,55 @@
.sourcegraph-notification-item {
display: block;
transition: all 300ms ease-in;
}
.progress {
// important is required to override the sibling class
background: transparent !important;
border-radius: 0;
}
.progressbar {
height: 0.25rem;
transition: width 0.6s ease;
}
.body-container {
display: flex;
align-items: flex-start;
}
.body {
flex: 1;
padding: 0.5rem;
overflow: hidden;
pre,
code {
overflow-x: auto;
}
}
.content > :last-child,
.title > :last-child {
margin-bottom: 0;
}
.close {
cursor: pointer;
flex: 0 0;
/* stylelint-disable-next-line declaration-property-unit-whitelist */
font-size: 1.25rem;
line-height: 1;
background-color: transparent;
border-width: 0;
outline: 0 !important;
color: inherit;
opacity: 0.7;
padding: 0.5rem;
&:hover,
&:focus {
opacity: 1;
}
}

View File

@ -1,52 +0,0 @@
.sourcegraph-notification-item {
display: block;
transition: all 300ms ease-in;
&__progress {
background: transparent;
border-radius: 0;
}
&__progressbar {
height: 0.25rem;
transition: width 0.6s ease;
}
&__body-container {
display: flex;
align-items: flex-start;
}
&__body {
flex: 1;
padding: 0.5rem;
overflow: hidden;
pre,
code {
overflow-x: auto;
}
}
&__content > :last-child,
&__title > :last-child {
margin-bottom: 0;
}
&__close {
cursor: pointer;
flex: 0 0;
// stylelint-disable-next-line declaration-property-unit-whitelist
font-size: 1.25rem;
line-height: 1;
background-color: transparent;
border-width: 0;
outline: 0 !important;
color: inherit;
opacity: 0.7;
padding: 0.5rem;
&:hover,
&:focus {
opacity: 1;
}
}
}

View File

@ -9,7 +9,6 @@ import { NotificationType } from '@sourcegraph/extension-api-classes'
import webStyles from '@sourcegraph/web/src/SourcegraphWebApp.scss'
import { NotificationItem } from './NotificationItem'
import notificationItemStyles from './NotificationItem.scss'
const notificationClassNames = {
[NotificationType.Log]: 'alert alert-secondary',
@ -24,7 +23,6 @@ const onDismiss = action('onDismiss')
const decorator: DecoratorFn = story => (
<>
<style>{webStyles}</style>
<style>{notificationItemStyles}</style>
<div style={{ maxWidth: '20rem', margin: '2rem' }}>{story()}</div>
</>
)

View File

@ -7,6 +7,7 @@ import * as sourcegraph from 'sourcegraph'
import { renderMarkdown } from '../util/markdown'
import { Notification } from './notification'
import styles from './NotificationItem.module.scss'
export interface NotificationClassNameProps {
notificationClassNames: Record<sourcegraph.NotificationType, string>
@ -77,15 +78,15 @@ export class NotificationItem extends React.PureComponent<Props, State> {
return (
<div
className={classNames(
'sourcegraph-notification-item',
styles.sourcegraphNotificationItem,
this.props.className,
this.props.notificationClassNames[this.props.notification.type]
)}
>
<div className="sourcegraph-notification-item__body-container">
<div className="sourcegraph-notification-item__body">
<div className={styles.bodyContainer}>
<div className={styles.body}>
<div
className="sourcegraph-notification-item__title"
className={styles.title}
dangerouslySetInnerHTML={{
__html: renderMarkdown(this.props.notification.message || '', {
allowDataUriLinksAndDownloads: true,
@ -94,7 +95,7 @@ export class NotificationItem extends React.PureComponent<Props, State> {
/>
{this.state.progress && (
<div
className="sourcegraph-notification-item__content"
className={styles.content}
dangerouslySetInnerHTML={{
__html: renderMarkdown(this.state.progress.message),
}}
@ -104,7 +105,7 @@ export class NotificationItem extends React.PureComponent<Props, State> {
{(!this.props.notification.progress || !this.state.progress) && (
<button
type="button"
className="sourcegraph-notification-item__close close"
className={classNames('close', styles.close)}
onClick={this.onDismiss}
aria-label="Close"
>
@ -113,9 +114,9 @@ export class NotificationItem extends React.PureComponent<Props, State> {
)}
</div>
{this.props.notification.progress && this.state.progress && (
<div className="sourcegraph-notification-item__progress progress">
<div className={classNames('progress', styles.progress)}>
<div
className="sourcegraph-notification-item__progressbar progress-bar"
className={classNames('progress-bar', styles.progressbar)}
// eslint-disable-next-line react/forbid-dom-props
style={{ width: `${this.state.progress.percentage}%` }}
/>

View File

@ -10,6 +10,7 @@ import { asError } from '../util/errors'
import { Notification } from './notification'
import { NotificationItem, NotificationClassNameProps } from './NotificationItem'
import styles from './Notifications.module.scss'
interface Props extends ExtensionsControllerProps, NotificationClassNameProps {}
@ -129,7 +130,7 @@ export class Notifications extends React.PureComponent<Props, State> {
public render(): JSX.Element | null {
return (
<div className="sourcegraph-notifications">
<div className={styles.sourcegraphNotifications}>
{this.state.notifications.slice(0, Notifications.MAX_RETAIN).map(notification => (
<NotificationItem
key={notification.id}

View File

@ -0,0 +1,40 @@
.symbol-icon {
$oc-level: 5;
$symbol-kinds: (
'array': 'red',
'boolean': 'red',
'class': 'orange',
'constant': 'indigo',
'constructor': 'violet',
'enum': 'blue',
'enummember': 'blue',
'event': 'red',
'field': 'blue',
'file': 'gray',
'function': 'violet',
'interface': 'green',
'key': 'yellow',
'method': 'violet',
'module': 'grape',
'namespace': 'grape',
'null': 'red',
'number': 'violet',
'object': 'orange',
'operator': 'gray',
'package': 'yellow',
'property': 'gray',
'string': 'orange',
'struct': 'orange',
'typeparameter': 'blue',
'variable': 'blue',
);
// Default for unknown symbols
color: var(--oc-gray-#{$oc-level});
@each $kind, $oc-color in $symbol-kinds {
&--kind-#{$kind} {
color: var(--oc-#{$oc-color}-#{$oc-level});
}
}
}

View File

@ -1,39 +0,0 @@
.symbol-icon {
$symbol-kinds: (
'array': $oc-red-list,
'boolean': $oc-red-list,
'class': $oc-orange-list,
'constant': $oc-indigo-list,
'constructor': $oc-violet-list,
'enum': $oc-blue-list,
'enummember': $oc-blue-list,
'event': $oc-red-list,
'field': $oc-blue-list,
'file': $oc-gray-list,
'function': $oc-violet-list,
'interface': $oc-green-list,
'key': $oc-yellow-list,
'method': $oc-violet-list,
'module': $oc-grape-list,
'namespace': $oc-grape-list,
'null': $oc-red-list,
'number': $oc-violet-list,
'object': $oc-orange-list,
'operator': $oc-gray-list,
'package': $oc-yellow-list,
'property': $oc-gray-list,
'string': $oc-orange-list,
'struct': $oc-orange-list,
'typeparameter': $oc-blue-list,
'variable': $oc-blue-list,
);
// Default for unknown symbols
color: $oc-gray-5;
@each $kind, $color-list in $symbol-kinds {
&--kind-#{$kind} {
color: map-get($color-list, '5');
}
}
}

View File

@ -1,5 +1,5 @@
import classNames from 'classnames'
import { kebabCase } from 'lodash'
import { upperFirst } from 'lodash'
import { MdiReactIconComponentType } from 'mdi-react'
import CodeArrayIcon from 'mdi-react/CodeArrayIcon'
import CodeBracesIcon from 'mdi-react/CodeBracesIcon'
@ -29,6 +29,7 @@ import * as React from 'react'
import { SymbolKind } from '../graphql-operations'
import styles from './SymbolIcon.module.scss'
/**
* Returns the icon component for a given symbol kind
*/
@ -96,16 +97,14 @@ interface SymbolIconProps {
kind: SymbolKind
className?: string
}
function getSymbolIconClassName(kind: SymbolKind): string | undefined {
return (styles as Record<string, string>)[`symbolIconKind${upperFirst(kind.toLowerCase())}`]
}
/**
* Renders an Icon for a given symbol kind
*/
export const SymbolIcon: React.FunctionComponent<SymbolIconProps> = ({ kind, className = '' }) => {
const Icon = getSymbolIconComponent(kind)
return (
<Icon
className={classNames(`symbol-icon symbol-icon--kind-${kebabCase(kind)}`, className)}
data-tooltip={kind.toLowerCase()}
/>
)
return <Icon className={classNames(getSymbolIconClassName(kind), className)} data-tooltip={kind.toLowerCase()} />
}

View File

@ -83,7 +83,6 @@ body,
@import './repo/RepoContainer';
@import './components/Dialog';
@import './user/settings/UserSettingsArea';
@import '../../shared/src/index';
:root {
// Skip Reach UI styles. See https://reacttraining.com/reach-ui/styling/.