-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add Google fonts picker #2328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add Google fonts picker #2328
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
5b4f8e3
start
SaraVieira 38d03e1
add google font
SaraVieira 443ee4d
readd button
SaraVieira b691719
remove console.log
SaraVieira 044482d
style fixes
SaraVieira ad1b207
fix paddinhg
SaraVieira 761410f
redo react component
SaraVieira c23a958
pr review
SaraVieira d6794bc
pr review
SaraVieira 4b39cf5
remove suffix
SaraVieira 0c6cf23
add font preview
SaraVieira e5d5145
add tringle
SaraVieira 843c756
Update packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependenci…
SaraVieira 6188e4a
make it functional component
SaraVieira c74c96a
fix light themes
SaraVieira 6fd79c2
fix safari
SaraVieira a53d3f6
fix imports
SaraVieira 44dd4e9
render in portal
SaraVieira 629f73e
fix click
SaraVieira 1c1da65
make it lighter
SaraVieira 38d4e43
fix small a11y
SaraVieira 3872deb
Update packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependenci…
SaraVieira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddFont/FontPicker/List.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import React, { FunctionComponent, useState, useMemo } from 'react'; | ||
| import { Font } from '@samuelmeuli/font-manager'; | ||
| import { List, SearchFonts, FontLI, FontFamily, Arrow } from './elements'; | ||
|
|
||
| type Props = { | ||
| fonts: Font[]; | ||
| onSelection: (e: any) => void; | ||
| activeFontFamily: string; | ||
| expanded: boolean; | ||
| }; | ||
|
|
||
| export const FontList: FunctionComponent<Props> = ({ | ||
| fonts, | ||
| onSelection, | ||
| activeFontFamily, | ||
| expanded, | ||
| }) => { | ||
| const [searchTerm, setSearchTerm] = useState(''); | ||
|
|
||
| const updateSearch = (e: any) => setSearchTerm(e.target.value); | ||
|
|
||
| const getFontId = (fontFamily: string): string => | ||
| fontFamily.replace(/\s+/g, '-').toLowerCase(); | ||
|
|
||
| const getFonts: Font[] = useMemo( | ||
| () => | ||
| fonts.filter(f => | ||
| f.family.toLowerCase().includes(searchTerm.trim().toLowerCase()) | ||
| ), | ||
| [fonts, searchTerm] | ||
| ); | ||
| return ( | ||
| <> | ||
| <Arrow /> | ||
| <List expanded={expanded}> | ||
| <SearchFonts | ||
| type="text" | ||
| value={searchTerm} | ||
| onChange={updateSearch} | ||
| placeholder="Search Typefaces" | ||
| /> | ||
| {getFonts.map((font: Font) => ( | ||
| <FontLI | ||
| key={font.family} | ||
| onClick={onSelection} | ||
| onKeyPress={onSelection} | ||
| > | ||
| <FontFamily | ||
| type="button" | ||
| id={`font-button-${getFontId(font.family)}`} | ||
| active={font.family === activeFontFamily} | ||
| > | ||
| {font.family} | ||
| </FontFamily> | ||
| </FontLI> | ||
| ))} | ||
| </List> | ||
| </> | ||
| ); | ||
| }; |
138 changes: 138 additions & 0 deletions
138
...es/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddFont/FontPicker/elements.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| import styled, { css } from 'styled-components'; | ||
| import Color from 'color'; | ||
|
|
||
| const makeDarker = ({ theme }) => | ||
| Color(theme['input.background']) | ||
| .darken(theme.light ? 0.1 : 0.3) | ||
| .rgbString(); | ||
|
|
||
| const makeLighter = ({ theme }) => | ||
| Color(theme['sideBar.background']) | ||
| .lighten(0.3) | ||
| .rgbString(); | ||
|
|
||
| export const SearchFonts = styled.input` | ||
| border: 1px solid ${props => makeDarker(props)}; | ||
| box-sizing: border-box; | ||
| border-radius: 2px; | ||
| width: 100%; | ||
| margin-bottom: 0.5rem; | ||
| padding: 0.5rem; | ||
| background: transparent; | ||
| color: ${props => | ||
| props.theme['input.foreground'] || | ||
| (props.theme.light ? '#636363' : 'white')}; | ||
|
|
||
| ::-webkit-input-placeholder { | ||
| color: ${props => | ||
| props.theme['input.foreground'] || | ||
| (props.theme.light ? '#636363' : 'white')}; | ||
| } | ||
| ::-moz-placeholder { | ||
| color: ${props => | ||
| props.theme['input.foreground'] || | ||
| (props.theme.light ? '#636363' : 'white')}; | ||
| } | ||
| :-ms-input-placeholder { | ||
| color: ${props => | ||
| props.theme['input.foreground'] || | ||
| (props.theme.light ? '#636363' : 'white')}; | ||
| } | ||
| `; | ||
|
|
||
| export const FontFamily = styled.button<{ active?: boolean }>` | ||
| margin: 0; | ||
| padding: 0; | ||
| background-color: ${props => makeLighter(props)}; | ||
| width: 100%; | ||
| padding-left: 0.25rem; | ||
| border: none; | ||
| text-align: left; | ||
| color: ${props => props.theme['sideBar.foreground'] || 'inherit'}; | ||
| cursor: pointer; | ||
|
|
||
| &:focus { | ||
| border-color: ${props => props.theme.secondary.clearer(0.6)}; | ||
| } | ||
| `; | ||
|
|
||
| export const FontLI = styled.li` | ||
| color: ${props => props.theme['sideBar.foreground'] || 'inherit'}; | ||
| padding: 0.5rem; | ||
| text-align: left; | ||
| cursor: pointer; | ||
| `; | ||
|
|
||
| export const List = styled.ul<{ expanded?: boolean }>` | ||
| font-size: 13px; | ||
| list-style: none; | ||
| border: 1px solid ${props => makeDarker(props)}; | ||
| box-sizing: border-box; | ||
| padding: 0.5rem; | ||
| margin: 0; | ||
| box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.24), 0px 4px 4px rgba(0, 0, 0, 0.12); | ||
| max-height: 0; | ||
| overflow: scroll; | ||
| transition: all 200ms ease; | ||
| text-align: left; | ||
| display: none; | ||
| margin-top: 0.5rem; | ||
| background-color: ${props => makeLighter(props)}; | ||
| width: 240px; | ||
| z-index: 10; | ||
|
|
||
| ${props => | ||
| props.expanded && | ||
| css` | ||
| max-height: 130px; | ||
| display: block; | ||
| `} | ||
| `; | ||
|
|
||
| export const SelectedFont = styled.button<{ done?: boolean }>` | ||
| background-color: ${props => | ||
| props.theme['input.background'] || 'rgba(0, 0, 0, 0.3)'}; | ||
| color: ${props => | ||
| props.theme['input.foreground'] || | ||
| (props.theme.light ? '#636363' : 'white')}; | ||
| border: 1px solid ${props => makeDarker(props)}; | ||
|
|
||
| box-shadow: none; | ||
| text-align: left; | ||
| appearance: none; | ||
| width: 100%; | ||
| padding: 0.5rem 0.75rem; | ||
| position: relative; | ||
| box-sizing: border-box; | ||
| outline: none; | ||
|
|
||
| ${props => | ||
| props.done && | ||
| css` | ||
| :after { | ||
| content: ''; | ||
| background-image: url("${`data:image/svg+xml,%3Csvg width='7' height='4' viewBox='0 0 7 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.50007 4L1.27146e-07 1.35122e-07L7 -4.76837e-07L3.50007 4Z' fill='${ | ||
| props.theme.light ? 'black' : 'white' | ||
| }'/%3E%3C/svg%3E%0A`}"); | ||
| width: 7px; | ||
| height: 4px; | ||
| position: absolute; | ||
| right: 0.5rem; | ||
| top: 50%; | ||
| transform: translateY(-50%); | ||
| } | ||
| `} | ||
| `; | ||
|
|
||
| export const Arrow = styled.div` | ||
| width: 0; | ||
| height: 0; | ||
| border-style: solid; | ||
| border-width: 0 6px 6px 6px; | ||
| border-color: transparent transparent | ||
| ${props => props.theme['sideBar.background']} transparent; | ||
| position: absolute; | ||
| margin-top: 2px; | ||
| left: 50%; | ||
| margin-left: -6px; | ||
| `; |
102 changes: 102 additions & 0 deletions
102
...ages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddFont/FontPicker/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| import { | ||
| FontManager, | ||
| Font, | ||
| FONT_FAMILY_DEFAULT, | ||
| OPTIONS_DEFAULTS, | ||
| } from '@samuelmeuli/font-manager'; | ||
| import React, { useState, useEffect, useRef } from 'react'; | ||
| import OutsideClickHandler from 'react-outside-click-handler'; | ||
| import { Portal } from 'reakit'; | ||
| import { SelectedFont } from './elements'; | ||
| import { FontList } from './List'; | ||
|
|
||
| export const FontPicker = ({ | ||
| activeFontFamily = FONT_FAMILY_DEFAULT, | ||
| onChange, | ||
| apiKey, | ||
| }) => { | ||
| const [expanded, setExpanded] = useState(false); | ||
| const [loadingStatus, setLoadingStatus] = useState('loading'); | ||
| const [fontManager, setFontManager] = useState(); | ||
| const [style, setStyle] = useState({ x: 0, y: 0 }); | ||
| const ref = useRef(null); | ||
|
|
||
| useEffect(() => { | ||
| const manager = new FontManager( | ||
| apiKey, | ||
| activeFontFamily, | ||
| { ...OPTIONS_DEFAULTS, limit: 200 }, | ||
| onChange | ||
| ); | ||
| setFontManager(manager); | ||
|
|
||
| manager | ||
| .init() | ||
| .then(() => setLoadingStatus('finished')) | ||
| .catch((err: Error) => { | ||
| setLoadingStatus('error'); | ||
| console.error(err); | ||
| }); | ||
| // eslint-disable-next-line | ||
| }, []); | ||
|
|
||
| useEffect(() => { | ||
| if (ref && ref.current) { | ||
| const styles = ref.current.getBoundingClientRect(); | ||
| setStyle({ | ||
| x: styles.x, | ||
| y: styles.y, | ||
| }); | ||
| } | ||
| }, [ref]); | ||
|
|
||
| const onSelection = (e: any): void => { | ||
| const active = e.target.textContent; | ||
| if (!active) { | ||
| throw Error(`Missing font family in clicked font button`); | ||
| } | ||
| fontManager.setActiveFont(active); | ||
| toggleExpanded(); | ||
| }; | ||
|
|
||
| const toggleExpanded = () => setExpanded(exp => !exp); | ||
|
|
||
| const fonts: Font[] = | ||
| fontManager && Array.from(fontManager.getFonts().values()); | ||
|
|
||
| return ( | ||
| <> | ||
| <SelectedFont | ||
| ref={ref} | ||
| type="button" | ||
| done={loadingStatus === 'finished'} | ||
| onClick={toggleExpanded} | ||
| onKeyPress={toggleExpanded} | ||
| disabled={loadingStatus === 'loading'} | ||
| > | ||
| {loadingStatus === 'loading' ? 'Loading Typefaces' : activeFontFamily} | ||
| </SelectedFont> | ||
| {expanded && loadingStatus === 'finished' && ( | ||
| <Portal> | ||
| <div | ||
| style={{ | ||
| position: 'fixed', | ||
| zIndex: 11, | ||
| top: style.y + 201, | ||
| left: style.x, | ||
| }} | ||
| > | ||
| <OutsideClickHandler onOutsideClick={() => setExpanded(false)}> | ||
| <FontList | ||
| fonts={fonts} | ||
| onSelection={onSelection} | ||
| activeFontFamily={activeFontFamily} | ||
| expanded={expanded} | ||
| /> | ||
| </OutsideClickHandler> | ||
| </div> | ||
| </Portal> | ||
| )} | ||
| </> | ||
| ); | ||
| }; | ||
6 changes: 6 additions & 0 deletions
6
packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddFont/elements.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import styled from 'styled-components'; | ||
|
|
||
| export const Container = styled.div` | ||
| margin: 0.5rem 1rem; | ||
| position: relative; | ||
| `; |
33 changes: 33 additions & 0 deletions
33
packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/AddFont/index.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import React, { useState } from 'react'; | ||
| import { Button } from '@codesandbox/common/lib/components/Button'; | ||
| import { FontPicker } from './FontPicker/index'; | ||
| import { Container } from './elements'; | ||
|
|
||
| export const AddFont = ({ addResource }) => { | ||
| const [activeFontFamily, setActiveFontFamily] = useState('Roboto'); | ||
|
|
||
| const addFont = async () => { | ||
| if (activeFontFamily) { | ||
| const font = activeFontFamily.trim().replace(/ /g, '+'); | ||
| const link = `https://fonts.googleapis.com/css?family=${font}&display=swap`; | ||
| await addResource(link); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <> | ||
| <Container> | ||
| <FontPicker | ||
| apiKey="AIzaSyDQ9HOzvLFchvhfDG9MR0UeLpF8ScJshxU" | ||
| activeFontFamily={activeFontFamily} | ||
| onChange={nextFont => setActiveFontFamily(nextFont.family)} | ||
| /> | ||
| </Container> | ||
| <Container> | ||
| <Button disabled={!activeFontFamily} block small onClick={addFont}> | ||
| Add Typeface | ||
| </Button> | ||
| </Container> | ||
| </> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
packages/app/src/app/pages/Sandbox/Editor/Workspace/Dependencies/ExternalFonts/index.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import React from 'react'; | ||
|
|
||
| import CrossIcon from 'react-icons/lib/md/clear'; | ||
|
|
||
| import { EntryContainer, IconArea, Icon } from '../../elements'; | ||
| import { Link } from '../elements'; | ||
|
|
||
| const getFamily = search => { | ||
| const hashes = search.slice(search.indexOf('?') + 1).split('&'); | ||
| const family = hashes | ||
| .find(hash => hash.split('=')[0] === 'family') | ||
| .split('=')[1]; | ||
|
|
||
| return { | ||
| name: family.split('+').join(' '), | ||
| id: family | ||
| .split('+') | ||
| .join('-') | ||
| .toLowerCase(), | ||
| }; | ||
| }; | ||
|
|
||
| export const ExternalFonts = ({ removeResource, resource }) => ( | ||
| <EntryContainer as="li"> | ||
| <Link id={`font-button-${getFamily(resource).id}`} href={resource}> | ||
| {getFamily(resource).name} | ||
| </Link> | ||
| <IconArea> | ||
| <Icon | ||
| ariaLabel="Remove Resource" | ||
| onClick={() => removeResource(resource)} | ||
| > | ||
| <CrossIcon /> | ||
| </Icon> | ||
| </IconArea> | ||
| </EntryContainer> | ||
| ); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.