Projects STRLCPY gradejs Commits f160dec8
🤬
  • wip: components and styling update to mostly static SearchResults page

  • Loading...
  • Dmitry Shakun committed 2 years ago
    f160dec8
    1 parent 6a377a9c
  • packages/web/src/assets/icons/sprite/check.svg
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/layouts/HomeNew/HomeNew.tsx
    skipped 11 lines
    12 12  };
    13 13   
    14 14  export default function HomeNew({ suggestions }: Props) {
     15 + // TODO: mock date, remove later
    15 16   const popularCards: CardProps[] = [
    16 17   {
    17 18   id: 'uExBVGuF',
    skipped 24 lines
    42 43   },
    43 44   ];
    44 45   
     46 + // TODO: mock date, remove later
    45 47   const popularPackages: CardProps[] = [
    46 48   {
    47 49   id: 'FPsBcl8R',
    skipped 67 lines
    115 117   },
    116 118   ];
    117 119   
     120 + // TODO: mock date, remove later
    118 121   const vulnerablePackages: CardProps[] = [
    119 122   {
    120 123   id: 'LnO9Xynn',
    skipped 54 lines
  • ■ ■ ■ ■ ■
    packages/web/src/components/layouts/SearchResults/SearchResults.module.scss
    skipped 6 lines
    7 7   grid-template-rows: min-content 1fr;
    8 8   grid-column-gap: 80px;
    9 9   margin-top: 44px;
    10  - margin-bottom: 100px;
     10 + padding-bottom: 108px;
     11 + border-bottom: 1px solid $gray-border;
     12 + margin-bottom: 80px;
     13 + 
     14 + @include lg {
     15 + grid-template-columns: 232px minmax(0, 1fr);
     16 + grid-column-gap: 56px;
     17 + padding-bottom: 86px;
     18 + }
    11 19   
    12 20   @include mobile-and-tablet {
    13 21   margin-top: 24px;
    14 22   grid-template-columns: minmax(0, 1fr);
    15 23   grid-template-rows: none;
    16 24   grid-gap: 24px;
     25 + padding-bottom: 64px;
     26 + margin-bottom: 56px;
     27 + }
     28 + 
     29 + @include mobile {
     30 + padding-bottom: 64px;
    17 31   }
    18 32  }
    19 33   
    skipped 7 lines
    27 41   }
    28 42  }
    29 43   
    30  -.searchedPackage {
    31  - grid-column: 2 / -1;
    32  - display: flex;
    33  - align-items: flex-start;
    34  - margin-bottom: 36px;
    35  - 
    36  - @include mobile-and-tablet {
    37  - flex-direction: column;
    38  - grid-column: 1;
    39  - margin-bottom: 0;
    40  - }
    41  -}
    42  - 
    43  -.searchedPackageImageWrapper {
    44  - display: flex;
    45  - flex-shrink: 0;
    46  - margin-right: 24px;
    47  - max-width: 52px;
    48  - 
    49  - @include mobile-and-tablet {
    50  - max-width: 44px;
    51  - margin-right: 0;
    52  - margin-bottom: 24px;
    53  - }
    54  -}
    55  - 
    56  -.searchedPackageImage {
    57  - width: 100%;
    58  - object-fit: cover;
    59  -}
    60  - 
    61  -.searchedPackageContent {
    62  - display: flex;
    63  - flex-direction: column;
    64  -}
    65  - 
    66  -.searchedPackageTitle {
    67  - margin-bottom: 12px;
    68  - 
    69  - @include mobile-and-tablet {
    70  - margin-bottom: 8px;
    71  - }
    72  -}
    73  - 
    74  -.searchedPackageHighlight {
    75  - color: $gray-text;
    76  -}
    77  - 
    78  -.searchedPackageSubtitle {
    79  - color: $gray-text;
    80  -}
    81  - 
    82 44  .sidebar {
    83 45   grid-column: 1 / 2;
    84 46   grid-row: 1 / 3;
    skipped 27 lines
    112 74   line-height: 26px;
    113 75  }
    114 76   
     77 +.sidebarItemCounter {
     78 + margin-left: 8px;
     79 +}
     80 + 
    115 81  .sidebarItemAction {
    116 82   display: flex;
    117 83  }
    skipped 36 lines
    154 120   cursor: pointer;
    155 121   font-weight: 500;
    156 122   color: $blue-accent;
     123 + transition: opacity $transition-duration $transition-timing-function;
     124 + 
     125 + &:hover {
     126 + opacity: 0.6;
     127 + }
    157 128  }
    158 129   
    159 130  .checkboxGroup {
    skipped 1 lines
    161 132   grid-gap: 18px;
    162 133  }
    163 134   
    164  -.checkbox {
    165  - cursor: pointer;
    166  - display: inline-block;
    167  - position: relative;
    168  - padding-left: 36px;
    169  - 
    170  - @include lg {
    171  - line-height: 24px;
    172  - }
    173  -}
    174  - 
    175  -.checkboxInput {
    176  - position: absolute;
    177  - top: 0;
    178  - left: 0;
    179  - margin: 0;
    180  - padding: 0;
    181  - opacity: 0;
    182  - 
    183  - &:checked ~ .checkboxName {
    184  - &::before {
    185  - background: $black;
    186  - }
    187  - 
    188  - &::after {
    189  - opacity: 1;
    190  - }
    191  - }
    192  -}
    193  - 
    194  -.checkboxName {
    195  - display: inline-block;
    196  - 
    197  - &::before {
    198  - content: '';
    199  - position: absolute;
    200  - top: 0;
    201  - left: 0;
    202  - width: 24px;
    203  - height: 24px;
    204  - border: 2px solid transparent;
    205  - border-radius: 5px;
    206  - background: $gray-border;
    207  - transition: background 0.2s ease-out;
    208  - }
    209  - 
    210  - &::after {
    211  - content: '';
    212  - position: absolute;
    213  - top: 7px;
    214  - left: 6px;
    215  - width: 12px;
    216  - height: 10px;
    217  - opacity: 0;
    218  - transition: opacity 0.2s ease-out;
    219  - background: url('~assets/checkbox-check.svg') 50% no-repeat;
    220  - }
    221  -}
    222  - 
    223 135  .authors {
    224 136   display: flex;
    225 137   flex-wrap: wrap;
    226 138  }
    227 139   
    228  -.author {
    229  - display: flex;
    230  - align-items: center;
    231  - margin-bottom: 10px;
    232  - 
    233  - &:not(:last-child) {
    234  - margin-right: 16px;
    235  - }
    236  -}
    237  - 
    238  -.authorImageWrapper {
    239  - display: flex;
    240  - flex-shrink: 0;
    241  - margin-right: 6px;
    242  - max-width: 36px;
    243  -}
    244  - 
    245  -.authorImage {
    246  - width: 100%;
    247  - object-fit: cover;
    248  - border-radius: 50%;
    249  -}
    250  - 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/layouts/SearchResults/SearchResults.tsx
    skipped 6 lines
    7 7  import ChipGroup from '../../ui/ChipGroup/ChipGroup';
    8 8  import PackagePreview from '../../ui/PackagePreview/PackagePreview';
    9 9  import SearchBar from '../../ui/SearchBar/SearchBar';
     10 +import Badge from '../../ui/Badge/Badge';
     11 +import Person from 'components/ui/Person/Person';
     12 +import Checkbox from '../../ui/Checkbox/Checkbox';
     13 +import SearchedResource from '../../ui/SearchedResource/SearchedResource';
     14 +import { CardProps } from '../../ui/Card/Card';
     15 +import CardGroup from '../../ui/CardGroup/CardGroup';
     16 +import CardList from '../../ui/CardList/CardList';
     17 +import CardGroups from 'components/ui/CardGroups/CardGroups';
    10 18   
    11  -type Props = {};
     19 +export default function SearchResults() {
     20 + // TODO: mock date, remove later
     21 + const similarCards: CardProps[] = [
     22 + {
     23 + id: 'uExBVGuF',
     24 + title: 'github.com',
     25 + icon: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     26 + packageTags: {
     27 + featuredPackages: ['mdast-util-from-markdown', 'react', 'react-dom'],
     28 + restPackages: 45,
     29 + },
     30 + },
     31 + {
     32 + id: '1EkL1u5g',
     33 + title: 'fingerprint.com',
     34 + icon: 'https://avatars.githubusercontent.com/u/67208791?s=200&v=4',
     35 + packageTags: {
     36 + featuredPackages: ['mdast-util-from-markdown', 'react', 'react-dom'],
     37 + restPackages: 45,
     38 + },
     39 + },
     40 + {
     41 + id: 'mhwO2bPM',
     42 + title: 'facebook.com',
     43 + icon: 'https://avatars.githubusercontent.com/u/69631?s=200&v=4',
     44 + packageTags: {
     45 + featuredPackages: ['react'],
     46 + restPackages: 45,
     47 + },
     48 + },
     49 + ];
     50 + 
     51 + // TODO: mock date, remove later
     52 + const popularPackages: CardProps[] = [
     53 + {
     54 + id: 'FPsBcl8R',
     55 + title: '@team-griffin/react-heading-section',
     56 + description: "This package's job is to automatically determine...",
     57 + featuredSites: {
     58 + iconList: [
     59 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     60 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     61 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     62 + ],
     63 + numberOfUses: 5265,
     64 + },
     65 + },
     66 + {
     67 + id: 'emtYcsUh',
     68 + title: 'unist-util-generated',
     69 + description: 'unist utility to check if a node is generated',
     70 + featuredSites: {
     71 + iconList: [
     72 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     73 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     74 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     75 + ],
     76 + numberOfUses: 5265,
     77 + },
     78 + },
     79 + {
     80 + id: 'TYIwvAfy',
     81 + title: 'react-smooth',
     82 + description: 'is a animation library work on React',
     83 + featuredSites: {
     84 + iconList: [
     85 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     86 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     87 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     88 + ],
     89 + numberOfUses: 5265,
     90 + },
     91 + },
     92 + {
     93 + id: 'Lq1pEEX7',
     94 + title: 'unist-util-position',
     95 + description: 'unist utility to get the positional info of nodes',
     96 + featuredSites: {
     97 + iconList: [
     98 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     99 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     100 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     101 + ],
     102 + numberOfUses: 5265,
     103 + },
     104 + },
     105 + {
     106 + id: 'cWOgIbmp',
     107 + title: 'vfile-message',
     108 + description: 'Create vfile messages',
     109 + featuredSites: {
     110 + iconList: [
     111 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     112 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     113 + 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     114 + ],
     115 + numberOfUses: 5265,
     116 + },
     117 + },
     118 + {
     119 + id: 'UT97Vpoi',
     120 + title: 'Go to all Popular packages',
     121 + variant: 'toAll',
     122 + },
     123 + ];
    12 124   
    13  -export default function SearchResults(props: Props) {
    14 125   return (
    15 126   <>
    16 127   <Header>
    skipped 2 lines
    19 130   
    20 131   <Container>
    21 132   <div className={styles.searchResults}>
    22  - <div className={styles.searchedPackage}>
    23  - <div className={styles.searchedPackageImageWrapper}>
    24  - <img
    25  - className={styles.searchedPackageImage}
    26  - src='https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg'
    27  - alt=''
    28  - />
    29  - </div>
    30  - <div className={styles.searchedPackageContent}>
    31  - <h3 className={styles.searchedPackageTitle}>
    32  - pinterest.com <span className={styles.searchedPackageHighlight}>6 packages</span>
    33  - </h3>
    34  - <div className={styles.searchedPackageSubtitle}>Last scanning 21 feb in 21:30</div>
    35  - </div>
    36  - </div>
     133 + <SearchedResource
     134 + image='https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg'
     135 + name='pinterest.com'
     136 + totalPackages={6}
     137 + lastScanDate='21 feb in 21:30'
     138 + />
    37 139   
    38 140   <aside className={styles.sidebar}>
    39 141   <div className={styles.sidebarItem}>
    skipped 47 lines
    87 189   
    88 190   <div className={styles.sidebarItem}>
    89 191   <div className={styles.sidebarItemTop}>
    90  - <div className={styles.sidebarItemTitle}>Problem</div>
     192 + <div className={styles.sidebarItemTitle}>
     193 + Problem
     194 + <span className={styles.sidebarItemCounter}>
     195 + <Badge content={1} />
     196 + </span>
     197 + </div>
    91 198   </div>
    92 199   
    93 200   <div className={styles.checkboxGroup}>
    94  - <label className={styles.checkbox}>
    95  - <input type='checkbox' className={styles.checkboxInput} />
    96  - <span className={styles.checkboxName}>Vulnerabilities</span>
    97  - </label>
    98  - <label className={styles.checkbox}>
    99  - <input type='checkbox' className={styles.checkboxInput} />
    100  - <span className={styles.checkboxName}>Outdated</span>
    101  - </label>
    102  - <label className={styles.checkbox}>
    103  - <input type='checkbox' className={styles.checkboxInput} />
    104  - <span className={styles.checkboxName}>Duplicate</span>
    105  - </label>
     201 + <Checkbox label='Vulnerabilities' checked />
     202 + <Checkbox label='Outdated' />
     203 + <Checkbox label='Duplicate' />
    106 204   </div>
    107 205   </div>
    108 206   
    skipped 6 lines
    115 213   </div>
    116 214   
    117 215   <div className={styles.authors}>
    118  - <div className={styles.author}>
    119  - <div className={styles.authorImageWrapper}>
    120  - <img
    121  - className={styles.authorImage}
    122  - src='https://via.placeholder.com/36'
    123  - alt=''
    124  - />
    125  - </div>
    126  - <div className={styles.authorName}>acdlite</div>
    127  - </div>
    128  - 
    129  - <div className={styles.author}>
    130  - <div className={styles.authorImageWrapper}>
    131  - <img
    132  - className={styles.authorImage}
    133  - src='https://via.placeholder.com/36'
    134  - alt=''
    135  - />
    136  - </div>
    137  - <div className={styles.authorName}>gaearon</div>
    138  - </div>
    139  - 
    140  - <div className={styles.author}>
    141  - <div className={styles.authorImageWrapper}>
    142  - <img
    143  - className={styles.authorImage}
    144  - src='https://via.placeholder.com/36'
    145  - alt=''
    146  - />
    147  - </div>
    148  - <div className={styles.authorName}>sophiebits</div>
    149  - </div>
    150  - 
    151  - <div className={styles.author}>
    152  - <div className={styles.authorImageWrapper}>
    153  - <img
    154  - className={styles.authorImage}
    155  - src='https://via.placeholder.com/36'
    156  - alt=''
    157  - />
    158  - </div>
    159  - <div className={styles.authorName}>trueadm</div>
    160  - </div>
     216 + <Person image='https://via.placeholder.com/36' name='acdlite' checked />
     217 + <Person image='https://via.placeholder.com/36' name='gaearon' />
     218 + <Person image='https://via.placeholder.com/36' name='sophiebits' />
     219 + <Person image='https://via.placeholder.com/36' name='trueadm' />
    161 220   </div>
    162 221   
    163 222   <span role='button' className={styles.viewAll}>
    skipped 9 lines
    173 232   />
    174 233   </div>
    175 234   </div>
     235 + 
     236 + <CardGroups>
     237 + <CardGroup title='Similar sites'>
     238 + <CardList cards={similarCards} />
     239 + </CardGroup>
     240 + 
     241 + <CardGroup title='Popular packages'>
     242 + <CardList cards={popularPackages} />
     243 + </CardGroup>
     244 + </CardGroups>
    176 245   </Container>
    177 246   
    178 247   <Footer />
    skipped 4 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Badge/Badge.module.scss
     1 +@import '~styles/_vars.scss';
     2 + 
     3 +.badge {
     4 + display: inline-flex;
     5 + align-items: center;
     6 + padding: 0 8px;
     7 + font-weight: 500;
     8 + font-size: 14px;
     9 + line-height: 22px;
     10 + min-width: 22px;
     11 + height: 22px;
     12 + border-radius: 11px;
     13 + background: $black;
     14 + color: $white;
     15 +}
     16 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Badge/Badge.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import Badge from './Badge';
     4 + 
     5 +export default {
     6 + title: 'Interface / Badge',
     7 + component: Badge,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof Badge>;
     12 + 
     13 +const Template: ComponentStory<typeof Badge> = (args) => <Badge {...args} />;
     14 + 
     15 +export const OneDigit = Template.bind({});
     16 +OneDigit.args = {
     17 + content: 4,
     18 +};
     19 + 
     20 +export const TwoDigits = Template.bind({});
     21 +TwoDigits.args = {
     22 + content: 42,
     23 +};
     24 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Badge/Badge.tsx
     1 +import React from 'react';
     2 +import styles from './Badge.module.scss';
     3 + 
     4 +type Props = {
     5 + content: string | number;
     6 +};
     7 + 
     8 +export default function Badge({ content }: Props) {
     9 + return <span className={styles.badge}>{content}</span>;
     10 +}
     11 + 
  • ■ ■ ■ ■
    packages/web/src/components/ui/CardGroups/CardGroups.module.scss
    skipped 4 lines
    5 5   
    6 6   @include mobile-and-tablet {
    7 7   margin-top: 56px;
    8  - margin-bottom: 32px;
     8 + margin-bottom: 8px;
    9 9   }
    10 10   
    11 11   & > * + * {
    skipped 8 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Checkbox/Checkbox.module.scss
     1 +@import '~styles/_vars.scss';
     2 +@import '~styles/responsive.scss';
     3 + 
     4 +.checkbox {
     5 + cursor: pointer;
     6 + display: inline-block;
     7 + position: relative;
     8 + padding-left: 36px;
     9 + 
     10 + @include lg {
     11 + line-height: 24px;
     12 + }
     13 +}
     14 + 
     15 +.checkboxInput {
     16 + position: absolute;
     17 + top: 0;
     18 + left: 0;
     19 + margin: 0;
     20 + padding: 0;
     21 + opacity: 0;
     22 + 
     23 + &:checked ~ .checkboxName {
     24 + font-weight: 500;
     25 + 
     26 + &::before {
     27 + background: $black;
     28 + }
     29 + 
     30 + &::after {
     31 + opacity: 1;
     32 + }
     33 + }
     34 +}
     35 + 
     36 +.checkboxName {
     37 + display: inline-block;
     38 + 
     39 + &::before {
     40 + content: '';
     41 + position: absolute;
     42 + top: 0;
     43 + left: 0;
     44 + width: 24px;
     45 + height: 24px;
     46 + border: 2px solid transparent;
     47 + border-radius: 5px;
     48 + background: $gray-border;
     49 + transition: background 0.2s ease-out;
     50 + }
     51 + 
     52 + &::after {
     53 + content: '';
     54 + position: absolute;
     55 + top: 7px;
     56 + left: 6px;
     57 + width: 12px;
     58 + height: 10px;
     59 + opacity: 0;
     60 + transition: opacity 0.2s ease-out;
     61 + background: url('~assets/checkbox-check.svg') 50% no-repeat;
     62 + }
     63 +}
     64 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Checkbox/Checkbox.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import Checkbox from './Checkbox';
     4 + 
     5 +export default {
     6 + title: 'Interface / Checkbox',
     7 + component: Checkbox,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof Checkbox>;
     12 + 
     13 +const Template: ComponentStory<typeof Checkbox> = (args) => <Checkbox {...args} />;
     14 + 
     15 +export const Default = Template.bind({});
     16 +Default.args = {
     17 + label: 'Checkbox',
     18 +};
     19 + 
     20 +export const Checked = Template.bind({});
     21 +Checked.args = {
     22 + label: 'Checkbox',
     23 + checked: true,
     24 +};
     25 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Checkbox/Checkbox.tsx
     1 +import React from 'react';
     2 +import styles from './Checkbox.module.scss';
     3 + 
     4 +type Props = {
     5 + checked?: boolean;
     6 + label: string;
     7 +};
     8 + 
     9 +export default function Checkbox({ checked, label }: Props) {
     10 + return (
     11 + <label className={styles.checkbox}>
     12 + <input type='checkbox' className={styles.checkboxInput} checked={checked} />
     13 + <span className={styles.checkboxName}>{label}</span>
     14 + </label>
     15 + );
     16 +}
     17 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Chip/Chip.module.scss
    skipped 1 lines
    2 2  @import '~styles/responsive.scss';
    3 3   
    4 4  .chip {
     5 + cursor: pointer;
    5 6   display: inline-flex;
    6 7   align-items: center;
    7 8   justify-content: center;
    8  - background-color: $gray-surface;
    9 9   border-radius: 31px;
    10 10   line-height: 1.25;
    11 11   border: 1px solid transparent;
    12 12   white-space: nowrap;
     13 + transition: all $transition-duration $transition-timing-function;
    13 14   
    14 15   @include mobile-and-tablet {
    15 16   font-size: 14px;
    skipped 6 lines
    22 23   margin-right: 2px;
    23 24  }
    24 25   
     26 +.primary {
     27 + background-color: $gray-surface;
     28 + 
     29 + &:hover {
     30 + background-color: $gray-border;
     31 + }
     32 +}
     33 + 
    25 34  .secondary {
    26 35   color: $gray-text;
     36 + background-color: $gray-surface;
     37 + 
     38 + &:hover {
     39 + background-color: $gray-border;
     40 + }
    27 41  }
    28 42   
    29 43  .outlined {
    skipped 85 lines
  • ■ ■ ■ ■ ■
    packages/web/src/components/ui/Container/Container.module.scss
    skipped 7 lines
    8 8   margin-left: auto;
    9 9   margin-right: auto;
    10 10   
    11  - @include xl {
     11 + @include lg {
     12 + padding-left: 36px;
     13 + padding-right: 36px;
     14 + }
     15 + 
     16 + @include mobile-and-tablet {
    12 17   padding-left: 20px;
    13 18   padding-right: 20px;
    14 19   }
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Header/Header.stories.tsx packages/web/src/components/ui/Header/HeaderHomePage.stories.tsx
    skipped 2 lines
    3 3  import Header from './Header';
    4 4   
    5 5  export default {
    6  - title: 'Interface / Header',
     6 + title: 'Interface / Header Homepage',
    7 7   component: Header,
    8 8   parameters: {
    9 9   layout: 'fullscreen',
    skipped 3 lines
    13 13   },
    14 14  } as ComponentMeta<typeof Header>;
    15 15   
    16  -const Template: ComponentStory<typeof Header> = (args) => <Header {...args} />;
    17  - 
    18  -export const HomePage = Template.bind({});
     16 +export const HomePage: ComponentStory<typeof Header> = () => <Header variant='homepage' />;
    19 17   
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Header/HeaderInner.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentMeta, ComponentStory } from '@storybook/react';
     3 +import Header from './Header';
     4 +import SearchBar from '../SearchBar/SearchBar';
     5 + 
     6 +export default {
     7 + title: 'Interface / Header Inner page',
     8 + component: Header,
     9 + parameters: {
     10 + layout: 'fullscreen',
     11 + },
     12 +} as ComponentMeta<typeof Header>;
     13 + 
     14 +export const InnerPage: ComponentStory<typeof Header> = () => (
     15 + <Header>
     16 + <SearchBar value='pinterest.com/blog/%D0%92%D092%D092%D092%/dFD092fg092%D092%/dFD092/blog/%D0%92%D092%D092%D092%/dFD092fg092%D092%/dFD092f' />
     17 + </Header>
     18 +);
     19 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Icon/Icon.tsx
    skipped 21 lines
    22 22  import dependency from '../../../assets/icons/sprite/dependency.svg';
    23 23  import graph from '../../../assets/icons/sprite/graph.svg';
    24 24  import ratingArrow from '../../../assets/icons/sprite/rating-arrow.svg';
     25 +import check from '../../../assets/icons/sprite/check.svg';
    25 26   
    26 27  const icons = {
    27 28   githubLogo,
    skipped 19 lines
    47 48   dependency,
    48 49   graph,
    49 50   ratingArrow,
     51 + check,
    50 52  };
    51 53   
    52 54  export type IconProps = {
    skipped 35 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/PackagePreview/PackagePreview.module.scss
    skipped 103 lines
    104 104   color: $gray-text;
    105 105  }
    106 106   
    107  -.footer {
    108  - display: flex;
    109  - align-items: center;
    110  - justify-content: space-between;
    111  - border-top: 1px solid $gray-border;
    112  - padding-top: 24px;
    113  - 
    114  - @include mobile-and-tablet {
    115  - padding-top: 20px;
    116  - }
    117  -}
    118  - 
    119  -.tags {
    120  - display: flex;
    121  - align-items: center;
    122  - 
    123  - & > * + * {
    124  - margin-left: 24px;
    125  - }
    126  -}
    127  - 
    128  -.tag {
    129  - font-weight: 500;
    130  - 
    131  - @include mobile-and-tablet {
    132  - &:nth-child(n + 3) {
    133  - display: none;
    134  - }
    135  - }
    136  -}
    137  - 
    138  -.author {
    139  - display: flex;
    140  - align-items: center;
    141  - color: $gray-text;
    142  -}
    143  - 
    144  -.authorImage {
    145  - flex-shrink: 0;
    146  - width: 36px;
    147  - height: 36px;
    148  - border-radius: 50%;
    149  - margin-left: 16px;
    150  - 
    151  - @include mobile-and-tablet {
    152  - width: 32px;
    153  - height: 32px;
    154  - }
    155  -}
    156  - 
    157  -.authorName {
    158  - @include mobile-and-tablet {
    159  - display: none;
    160  - }
    161  -}
    162  - 
    163 107  .content {
    164 108   max-height: 0;
    165 109   overflow: hidden;
    skipped 42 lines
    208 152   line-height: 20px;
    209 153   color: $blue-accent;
    210 154   font-weight: 500;
     155 + transition: opacity $transition-duration $transition-timing-function;
     156 + 
     157 + &:hover {
     158 + opacity: 0.6;
     159 + }
    211 160  }
    212 161   
    213 162  .statTitle {
    skipped 45 lines
    259 208   justify-content: space-between;
    260 209   padding-right: 60px;
    261 210   
     211 + @include lg {
     212 + padding-right: 0;
     213 + }
     214 + 
    262 215   @include mobile-and-tablet {
    263 216   flex-wrap: wrap;
    264 217   padding-right: 0;
    skipped 3 lines
    268 221  .statListItemSmall {
    269 222   flex: 0 0 auto;
    270 223   width: 25%;
     224 + 
     225 + @include lg {
     226 + width: auto;
     227 + padding-right: 20px;
     228 + }
    271 229   
    272 230   @include mobile-and-tablet {
    273 231   width: 50%;
    skipped 14 lines
    288 246   display: grid;
    289 247   grid-template-columns: repeat(6, 1fr);
    290 248   grid-gap: 11px;
    291  - 
    292 249   overflow-x: auto;
    293 250   
    294 251   &::-webkit-scrollbar {
    skipped 54 lines
    349 306   margin-left: 8px;
    350 307  }
    351 308   
     309 +.usedOnList {
     310 + margin: 0 -36px;
     311 + padding: 0 36px;
     312 + 
     313 + @include mobile-and-tablet {
     314 + margin: 0 -20px;
     315 + padding: 0 20px;
     316 + }
     317 +}
     318 + 
    352 319  .actions {
     320 + margin-top: 56px;
    353 321   display: flex;
    354 322   align-items: center;
    355 323   justify-content: space-between;
    356 324   
    357 325   @include mobile-and-tablet {
     326 + margin-top: 44px;
     327 + }
     328 + 
     329 + @include sm {
     330 + margin-top: 32px;
    358 331   flex-direction: column-reverse;
    359 332   justify-content: flex-start;
    360  - align-items: flex-start;
     333 + align-items: flex-end;
    361 334   }
    362 335  }
    363 336   
    skipped 1 lines
    365 338   display: flex;
    366 339   align-items: center;
    367 340   
    368  - @include mobile-and-tablet {
     341 + @include sm {
     342 + margin-top: 24px;
    369 343   justify-content: space-between;
    370 344   width: 100%;
    371 345   }
    skipped 2 lines
    374 348   margin-left: 62px;
    375 349   
    376 350   @include mobile-and-tablet {
     351 + margin-left: 40px;
     352 + }
     353 + 
     354 + @include sm {
    377 355   margin-left: 0;
    378 356   }
    379 357   }
    skipped 14 lines
    394 372   display: block;
    395 373  }
    396 374   
     375 +.footer {
     376 + display: flex;
     377 + align-items: center;
     378 + justify-content: space-between;
     379 + border-top: 1px solid $gray-border;
     380 + padding-top: 24px;
     381 + 
     382 + @include mobile-and-tablet {
     383 + padding-top: 20px;
     384 + }
     385 +}
     386 + 
     387 +.tags {
     388 + display: flex;
     389 + align-items: center;
     390 + 
     391 + & > * + * {
     392 + margin-left: 24px;
     393 + }
     394 +}
     395 + 
     396 +.tag {
     397 + font-weight: 500;
     398 + transition: opacity $transition-duration $transition-timing-function;
     399 + 
     400 + &:hover {
     401 + opacity: 0.6;
     402 + }
     403 + 
     404 + @include lg {
     405 + &:nth-child(n + 5) {
     406 + display: none;
     407 + }
     408 + }
     409 + 
     410 + @include sm {
     411 + &:nth-child(n + 4) {
     412 + display: none;
     413 + }
     414 + }
     415 +}
     416 + 
     417 +.author {
     418 + display: flex;
     419 + align-items: center;
     420 + color: $gray-text;
     421 +}
     422 + 
     423 +.authorImage {
     424 + flex-shrink: 0;
     425 + width: 36px;
     426 + height: 36px;
     427 + border-radius: 50%;
     428 + margin-left: 16px;
     429 + 
     430 + @include mobile-and-tablet {
     431 + width: 32px;
     432 + height: 32px;
     433 + }
     434 +}
     435 + 
     436 +.authorName {
     437 + @include mobile-and-tablet {
     438 + display: none;
     439 + }
     440 +}
     441 + 
  • ■ ■ ■ ■ ■
    packages/web/src/components/ui/PackagePreview/PackagePreview.tsx
    skipped 10 lines
    11 11  type Props = {
    12 12   name: string;
    13 13   version: string;
     14 + opened?: boolean;
    14 15  };
    15 16   
    16  -export default function PackagePreview({ name, version }: Props) {
    17  - const [open, setOpen] = useState<boolean>(true);
     17 +export default function PackagePreview({ name, version, opened }: Props) {
     18 + const [open, setOpen] = useState<boolean>(opened ?? false);
    18 19   
    19 20   // TODO: mock data, remove later
    20 21   const sites: Site[] = [
    skipped 17 lines
    38 39   },
    39 40   {
    40 41   id: '1231',
     42 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     43 + name: 'pinterest.com',
     44 + packagesCount: 151,
     45 + },
     46 + {
     47 + id: '12321',
     48 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     49 + name: 'pinterest.com',
     50 + packagesCount: 151,
     51 + },
     52 + {
     53 + id: '123123',
     54 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     55 + name: 'pinterest.com',
     56 + packagesCount: 151,
     57 + },
     58 + {
     59 + id: '12123132',
    41 60   image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
    42 61   name: 'pinterest.com',
    43 62   packagesCount: 151,
    skipped 196 lines
    240 259   <div className={styles.stat}>
    241 260   <div className={styles.statHeader}>Used on</div>
    242 261   
    243  - <SitesList sites={sites} />
     262 + <SitesList sites={sites} className={styles.usedOnList} />
    244 263   </div>
    245 264   
    246 265   <div className={styles.actions}>
    skipped 59 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/PackagePreview/PackgePreview.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import PackagePreview from './PackagePreview';
     4 + 
     5 +export default {
     6 + title: 'Interface / PackagePreview',
     7 + component: PackagePreview,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof PackagePreview>;
     12 + 
     13 +export const Closed: ComponentStory<typeof PackagePreview> = () => (
     14 + <PackagePreview name='name' version='1.0.0' />
     15 +);
     16 + 
     17 +export const Opened: ComponentStory<typeof PackagePreview> = () => (
     18 + <PackagePreview name='name' version='1.0.0' opened />
     19 +);
     20 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Person/Person.module.scss
     1 +@import '~styles/_vars.scss';
     2 + 
     3 +.person {
     4 + cursor: pointer;
     5 + display: flex;
     6 + align-items: center;
     7 + margin-bottom: 10px;
     8 + 
     9 + &:not(:last-child) {
     10 + margin-right: 16px;
     11 + }
     12 + 
     13 + &:hover {
     14 + .personName {
     15 + opacity: 0.8;
     16 + }
     17 + }
     18 +}
     19 + 
     20 +.personActive {
     21 + font-weight: 500;
     22 +}
     23 + 
     24 +.personImageWrapper {
     25 + display: flex;
     26 + flex-shrink: 0;
     27 + margin-right: 6px;
     28 + max-width: 36px;
     29 +}
     30 + 
     31 +.personImage {
     32 + width: 100%;
     33 + object-fit: cover;
     34 + border-radius: 50%;
     35 +}
     36 + 
     37 +.personName {
     38 + transition: opacity $transition-duration $transition-timing-function;
     39 +}
     40 + 
     41 +.personCheck {
     42 + display: inline-flex;
     43 + margin-left: 6px;
     44 +}
     45 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Person/Person.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import Person from './Person';
     4 + 
     5 +export default {
     6 + title: 'Interface / Person',
     7 + component: Person,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof Person>;
     12 + 
     13 +const Template: ComponentStory<typeof Person> = (args) => <Person {...args} />;
     14 + 
     15 +export const Default = Template.bind({});
     16 +Default.args = {
     17 + image: 'https://via.placeholder.com/36',
     18 + name: 'Lorem ipsum',
     19 +};
     20 + 
     21 +export const Selected = Template.bind({});
     22 +Selected.args = {
     23 + image: 'https://via.placeholder.com/36',
     24 + name: 'Lorem ipsum',
     25 + checked: true,
     26 +};
     27 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Person/Person.tsx
     1 +import React from 'react';
     2 +import clsx from 'clsx';
     3 +import styles from './Person.module.scss';
     4 +import { Icon } from '../Icon/Icon';
     5 + 
     6 +type Props = {
     7 + image?: string;
     8 + name: string;
     9 + checked?: boolean;
     10 +};
     11 + 
     12 +export default function Person({ image, name, checked }: Props) {
     13 + return (
     14 + <div className={clsx(styles.person, checked && styles.personActive)}>
     15 + <div className={styles.personImageWrapper}>
     16 + <img className={styles.personImage} src={image} alt='' />
     17 + </div>
     18 + <div className={styles.personText}>
     19 + <span className={styles.personName}>{name}</span>
     20 + {checked && (
     21 + <span className={styles.personCheck}>
     22 + <Icon kind='check' width={12} height={10} color='#212121' />
     23 + </span>
     24 + )}
     25 + </div>
     26 + </div>
     27 + );
     28 +}
     29 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SearchBar/SearchBar.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import SearchBar from './SearchBar';
     4 + 
     5 +export default {
     6 + title: 'Interface / SearchBar',
     7 + component: SearchBar,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof SearchBar>;
     12 + 
     13 +const Template: ComponentStory<typeof SearchBar> = (args) => <SearchBar {...args} />;
     14 + 
     15 +export const Empty = Template.bind({});
     16 +Empty.args = {};
     17 + 
     18 +export const WithValue = Template.bind({});
     19 +WithValue.args = {
     20 + value: 'https://reactjs.org',
     21 +};
     22 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SearchedResource/SearchedResource.module.scss
     1 +@import '~styles/_vars.scss';
     2 +@import '~styles/responsive.scss';
     3 + 
     4 +.searchedResource {
     5 + grid-column: 2 / -1;
     6 + display: flex;
     7 + align-items: flex-start;
     8 + margin-bottom: 36px;
     9 + 
     10 + @include mobile-and-tablet {
     11 + flex-direction: column;
     12 + grid-column: 1;
     13 + margin-bottom: 0;
     14 + }
     15 +}
     16 + 
     17 +.searchedResourceImageWrapper {
     18 + display: flex;
     19 + flex-shrink: 0;
     20 + margin-right: 24px;
     21 + max-width: 52px;
     22 + 
     23 + @include mobile-and-tablet {
     24 + max-width: 44px;
     25 + margin-right: 0;
     26 + margin-bottom: 24px;
     27 + }
     28 +}
     29 + 
     30 +.searchedResourceImage {
     31 + width: 100%;
     32 + object-fit: cover;
     33 +}
     34 + 
     35 +.searchedResourceContent {
     36 + display: flex;
     37 + flex-direction: column;
     38 +}
     39 + 
     40 +.searchedResourceTitle {
     41 + margin-bottom: 12px;
     42 + 
     43 + @include mobile-and-tablet {
     44 + margin-bottom: 8px;
     45 + }
     46 +}
     47 + 
     48 +.searchedResourceHighlight {
     49 + color: $gray-text;
     50 +}
     51 + 
     52 +.searchedResourceSubtitle {
     53 + color: $gray-text;
     54 +}
     55 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SearchedResource/SearchedResource.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import SearchedResource from './SearchedResource';
     4 + 
     5 +export default {
     6 + title: 'Interface / SearchedResource',
     7 + component: SearchedResource,
     8 + parameters: {
     9 + layout: 'centered',
     10 + },
     11 +} as ComponentMeta<typeof SearchedResource>;
     12 + 
     13 +const Template: ComponentStory<typeof SearchedResource> = (args) => <SearchedResource {...args} />;
     14 + 
     15 +export const Default = Template.bind({});
     16 +Default.args = {
     17 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     18 + name: 'example.com',
     19 + totalPackages: 42,
     20 + lastScanDate: '21 feb in 21:30',
     21 +};
     22 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SearchedResource/SearchedResource.tsx
     1 +import React from 'react';
     2 +import styles from './SearchedResource.module.scss';
     3 + 
     4 +type Props = {
     5 + image: string;
     6 + name: string;
     7 + totalPackages: number;
     8 + lastScanDate?: string;
     9 +};
     10 + 
     11 +export default function SearchedResource({ image, name, totalPackages, lastScanDate }: Props) {
     12 + return (
     13 + <div className={styles.searchedResource}>
     14 + <div className={styles.searchedResourceImageWrapper}>
     15 + <img className={styles.searchedResourceImage} src={image} alt='' />
     16 + </div>
     17 + <div className={styles.searchedResourceContent}>
     18 + <h3 className={styles.searchedResourceTitle}>
     19 + {name} <span className={styles.searchedResourceHighlight}>{totalPackages} packages</span>
     20 + </h3>
     21 + <div className={styles.searchedResourceSubtitle}>Last scanning {lastScanDate}</div>
     22 + </div>
     23 + </div>
     24 + );
     25 +}
     26 + 
  • ■ ■ ■ ■ ■
    packages/web/src/components/ui/SitesList/SitesList.module.scss
    1 1  @import '~styles/_vars.scss';
    2 2  @import '~styles/responsive.scss';
    3 3   
     4 +.sitesListWrapper {
     5 + display: grid;
     6 + grid-template-columns: minmax(0, 1fr);
     7 +}
     8 + 
    4 9  .sitesList {
    5 10   display: flex;
    6 11   flex-wrap: nowrap;
    skipped 10 lines
    17 22   }
    18 23   
    19 24   & > * + * {
    20  - margin-left: 40px;
     25 + margin-left: 68px;
     26 + 
     27 + @include lg {
     28 + margin-left: 40px;
     29 + }
    21 30   }
    22 31  }
    23 32   
    skipped 31 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SitesList/SitesList.stories.tsx
     1 +import React from 'react';
     2 +import { ComponentStory, ComponentMeta } from '@storybook/react';
     3 +import SitesList from './SitesList';
     4 +import Container from '../Container/Container';
     5 + 
     6 +export default {
     7 + title: 'Interface / SitesList',
     8 + component: SitesList,
     9 + parameters: {
     10 + layout: 'fullscreen',
     11 + },
     12 +} as ComponentMeta<typeof SitesList>;
     13 + 
     14 +const Template: ComponentStory<typeof SitesList> = (args) => (
     15 + <Container>
     16 + <SitesList {...args} />
     17 + </Container>
     18 +);
     19 + 
     20 +export const Default = Template.bind({});
     21 +Default.args = {
     22 + sites: [
     23 + {
     24 + id: '123',
     25 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     26 + name: 'pinterest.com',
     27 + packagesCount: 151,
     28 + },
     29 + {
     30 + id: '456',
     31 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     32 + name: 'pinterest.com',
     33 + packagesCount: 151,
     34 + },
     35 + {
     36 + id: '789',
     37 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     38 + name: 'pinterest.com',
     39 + packagesCount: 151,
     40 + },
     41 + {
     42 + id: '1231',
     43 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     44 + name: 'pinterest.com',
     45 + packagesCount: 151,
     46 + },
     47 + {
     48 + id: '12321',
     49 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     50 + name: 'pinterest.com',
     51 + packagesCount: 151,
     52 + },
     53 + {
     54 + id: '123123',
     55 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     56 + name: 'pinterest.com',
     57 + packagesCount: 151,
     58 + },
     59 + {
     60 + id: '12123132',
     61 + image: 'https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg',
     62 + name: 'pinterest.com',
     63 + packagesCount: 151,
     64 + },
     65 + ],
     66 +};
     67 + 
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/SitesList/SitesList.tsx
    1 1  import React from 'react';
    2 2  import styles from './SitesList.module.scss';
     3 +import clsx from 'clsx';
    3 4   
    4 5  export type Site = {
    5 6   id: string;
    skipped 4 lines
    10 11   
    11 12  type Props = {
    12 13   sites: Site[];
     14 + className?: string;
    13 15  };
    14 16   
    15 17  function Site({ image, name, packagesCount }: Site) {
    skipped 10 lines
    26 28   );
    27 29  }
    28 30   
    29  -export default function SitesList({ sites }: Props) {
     31 +export default function SitesList({ sites, className }: Props) {
    30 32   return (
    31  - <div className={styles.sitesList}>
    32  - {sites.map((site) => (
    33  - <Site key={site.id} {...site} />
    34  - ))}
     33 + <div className={styles.sitesListWrapper}>
     34 + <div className={clsx(styles.sitesList, className)}>
     35 + {sites.map((site) => (
     36 + <Site key={site.id} {...site} />
     37 + ))}
     38 + </div>
    35 39   </div>
    36 40   );
    37 41  }
    skipped 1 lines
Please wait...
Page is in error, reload to recover