Skip to content

Commit

Permalink
Merge pull request #1 from igoradamenko/improvement/react-example
Browse files Browse the repository at this point in the history
Improve React example
  • Loading branch information
igoradamenko authored Oct 25, 2023
2 parents 5349361 + 72a52e6 commit b0b79ca
Show file tree
Hide file tree
Showing 16 changed files with 1,048 additions and 94 deletions.
70 changes: 68 additions & 2 deletions examples/react-uploader/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,73 @@
# Blocks ❤️ React
<p align="center">
<a href="https://uploadcare.com/?ref=github-react-example-readme">
<picture>
<source media="(prefers-color-scheme: light)" srcset="./assets/media/logo-safespace-transparent.svg">
<source media="(prefers-color-scheme: dark)" srcset="./assets/media/logo-transparent-inverted.svg">
<img width=250 alt="Uploadcare logo" src="./assets/media/logo-safespace-transparent.svg">
</picture>
</a>
</p>
<p align="center">
<a href="https://uploadcare.com?ref=github-readme">Website</a> •
<a href="https://uploadcare.com/docs/start/quickstart?ref=github-readme">Quick Start</a> •
<a href="https://uploadcare.com/docs?ref=github-readme">Docs</a> •
<a href="https://uploadcare.com/blog?ref=github-readme">Blog</a> •
<a href="https://discord.gg/mKWRgRsVz8?ref=github-readme">Discord</a> •
<a href="https://twitter.com/Uploadcare?ref=github-readme">Twitter</a>
</p>

# React File Uploader with Uploadcare Blocks

[![Edit react-uploader](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/uploadcare/blocks-examples/tree/main/examples/react-uploader/)

This is an example project of implementing a file uploader in a React application with [Uploadcare Blocks](https://github.com/uploadcare/blocks).

## Installation

All you need to do is to install [`@uploadcare/blocks`](https://www.npmjs.com/package/@uploadcare/blocks) from npm
via your favorite Node package manager.

The package provides TypeScript types, so you do not need to install `@types/anything` if you need a proper typing.

[Read more about installation](https://uploadcare.com/docs/file-uploader/installation/) in the Uploadcare documentation.

## Configutration

Please, read the [File Uploader documentation](https://uploadcare.com/docs/file-uploader/).

## Integration notes

WIP
Blocks are native to the Web but not to React. It's easy to use Blocks in a React app, but note that a part of your solution will encapsulate non-React code.

In this example we created a [FileUploader](./src/FileUploader/FileUploader.tsx) component
which provides React-friendly API for the rest of the app. There are Blocks inside of this component and nowhere else.

### Non-React things you should know about

1. Communicate with Blocks File Uploader with [events](https://uploadcare.com/docs/file-uploader/data-and-events/).
You will find them in the example. It's easy to handle using hooks like [`useEffect`](https://react.dev/reference/react/useEffect).

2. Use `class` attribute instead of `className`.

3. Some attributes required by Blocks are kebab-cased, not camelCased as usual for React world.

4. You are able to invoke [some methods of File Uploader](https://uploadcare.com/docs/file-uploader/api/)
to control its behavior.

### Styling

If your styling solution may provide class string or style object, feel free to use them on blocks like
`lr-file-uploader-regular` and override default class using CSS variables.

Otherwise you may go “full override” way and pass a string with styles to a File Uploader type of your choice.

[Read more about styling](https://uploadcare.com/docs/file-uploader/styling/) in the File Uploader docs.

## Contribution

You’re always welcome to contribute:

* Create [issues](https://github.com/uploadcare/blocks/issues) every time you feel something is missing or goes wrong.
* Provide your feedback or drop us a support request at <a href="mailto:[email protected]">[email protected]</a>.
* Ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/uploadcare) with "uploadcare" tag if others can have these questions as well.
* Star this repo if you like it ⭐️
3 changes: 1 addition & 2 deletions examples/react-uploader/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Uploadcare React Example</title>
</head>
<body>
<div id="root"></div>
Expand Down
9 changes: 6 additions & 3 deletions examples/react-uploader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --force",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@uploadcare/blocks": "0.25.6",
"@uploadcare/blocks": "0.27.6",
"classnames": "2.3.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-toggle": "4.1.3"
},
"devDependencies": {
"@types/react": "^18.0.35",
"@types/react-dom": "^18.0.11",
"@types/react-toggle": "4.0.4",
"@vitejs/plugin-react": "^3.1.0",
"typescript": "^5.0.4",
"vite": "^4.2.1"
Expand Down
13 changes: 0 additions & 13 deletions examples/react-uploader/src/App.module.css

This file was deleted.

158 changes: 158 additions & 0 deletions examples/react-uploader/src/App.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
.app {
padding: 16px 24px;
max-width: 480px;
margin: 0 auto;
}

.header {
margin-bottom: 48px;
display: flex;
justify-content: space-between;
}

.themeToggle {
:global(.react-toggle-track) {
box-shadow: 0 0 16px 0 var(--ui-control-box-shadow-color);
background-color: var(--ui-control-background-color);
border: 1px solid var(--ui-control-border-color-default);
transition: none;
}

&:global(.react-toggle:hover .react-toggle-track),
&:global(.react-toggle--checked:hover .react-toggle-track) {
background-color: var(--ui-control-background-color);
border: 1px solid var(--ui-control-border-color-default);
outline: 2px solid var(--ui-control-outline-color-focus);
}

:global(.react-toggle-track-check), :global(.react-toggle-track-x) {
width: auto;
height: auto;
display: flex;
align-items: center;
}

:global(.react-toggle-track-check) {
left: 6px;
}

:global(.react-toggle-track-x) {
right: 8px;
}

:global(.react-toggle-thumb) {
top: 2px;
left: 2px;
background: var(--ui-control-background-color);
border-color: var(--ui-control-border-color-default);
transition: left 0.25s ease;
}

&:global(.react-toggle--checked .react-toggle-thumb) {
left: 28px;
}

&:global(.react-toggle--active .react-toggle-thumb),
&:global(.react-toggle:active .react-toggle-thumb) {
box-shadow: none;
}

&:global(.react-toggle--focus .react-toggle-thumb) {
box-shadow: none;
}
}

.viewTitle {
margin: 0;
font-size: 16px;
font-weight: 400;
color: var(--ui-text-color);
}

.input {
box-sizing: border-box;
width: 100%;
padding: 8px 12px;
font-family: monospace;
font-size: 16px;
border: 1px solid var(--ui-control-border-color-default);
border-radius: 8px;
background: var(--ui-control-background-color);
box-shadow: 0 0 16px 0 var(--ui-control-box-shadow-color);
color: var(--ui-control-text-color);

&:focus {
outline: 3px solid var(--ui-control-outline-color-focus);
border-color: var(--ui-control-border-color-focus);
}

// trying to prevent scrollbar overflowing textarea borders =/
&::-webkit-scrollbar-corner {
display: none;
}
}

.field {
margin-top: 24px;

&:last-child {
margin-top: 48px;
}
}

.label {
position: relative;
z-index: 1;
display: block;
margin-bottom: 8px;
color: var(--ui-text-color);
}

.button {
font-size: 16px;
font-family: monospace;
line-height: 1;
padding: 10px 12px;
border: 1px solid var(--ui-control-border-color-default);
border-radius: 8px;
box-shadow: 0 0 16px 0 var(--ui-control-box-shadow-color);
background: var(--ui-action-button-background);
color: var(--ui-action-button-text-color);
cursor: pointer;

&:hover, &:focus {
outline: 3px solid var(--ui-control-outline-color-focus);
}

&:active {
border-color: var(--ui-control-border-color-focus);
}
}

.result {
font-size: 14px;
line-height: 18px;
font-family: monospace;
white-space: pre-wrap;
}

/*
Note: Localization of File Uploader is done via CSS variables.
You can change any piece of text of File Uploader this way.
See more: https://uploadcare.com/docs/file-uploader/localization/
*/
.fileUploader {
// TODO: rewrite other texts related to plural nouns
--l10n-upload-file: 'Upload photo';
--l10n-upload-files: 'Upload photos';
--l10n-choose-file: 'Choose photo';
--l10n-choose-files: 'Choose photos';
--l10n-drop-files-here: 'Drop photos here';
--l10n-select-file-source: 'Select photo source';
--l10n-edit-image: 'Edit photo';
--l10n-no-files: 'No photos selected';
--l10n-caption-edit-file: 'Edit photo';
--l10n-files-count-allowed: 'Only {{count}} photos are allowed';
--l10n-files-max-size-limit-error: 'Photo is too big. Max photo size is {{maxFileSize}}.';
}
Loading

0 comments on commit b0b79ca

Please sign in to comment.