The Examples site has been made available to aid developers interested in building web apps with Draggable and/or contributing back to the library.
The Examples sandbox aims to answer common questions concerning Draggable’s implementation, as well as provide solutions to any conceivable drag and drop problem.
For instance, our solution to resolving touch events required duplicating the source
node in the DOM. Depending on your design, this could cause friction as you attempt to maintain the correct layout while dragging. A bit of clever CSS can help resolve such layout issues. There are several examples in this repo that demonstrate solutions to this exact layout concern.
- Clone the
draggable
repo:git clone [email protected]:Shopify/draggable.git
. - Run
yarn && yarn start
in the rootdraggable
directory. - You can now access the local site at
http://localhost:3000
(local address may vary - see console for correct url).
This project uses Shopify’s eslint and stylelint configs with a few alterations, defined in their respective dot rc
file. If contributing back to this project, you must conform to the code style enforced by the config. If you are just playing around and don’t care about code style, just disable your editor’s linter.
This project uses a co-located component structure, meaning everything relating to an individual component should all be found in the same folder. For the most part, you will work only in the src/components
and src/content
folders.
The root directory contains many config files that you can safely ignore unless you aim to change how files are compiled. It is strongly recommended to read the package.json
to familiarize yourself with the available scripts
.
This folder contains the top-level page templates. The project uses Nunjucks for a templating language.
There is only one layout template, views/templates/document.html
, which is extended by all of the .html
files in the root of /views
. These root views do the following:
- Import global components such as
Sidebar
andPageHeader
- Define the
ViewAttr
for the view (Page title, description, etc). - Import and render the content component for that view.
This is where “global” styles, along with the examples-app.scss
manifest, are located. There shouldn’t be much reason to alter any of these files other than adding new imports to examples-app.scss
.
This project uses Threads to manage style properties. You can see all of the Threads theme values in styles/themes/examples
.
Just like with styles/
, this is where our “global” scripts, along with the examples-app.js
entry script is located. There shouldn’t be much reason to alter any of these files other than adding new imports and initializations to examples-app.js
.
This folder contains all the “content components”, which means all the code specific to an individual Example. Content is grouped by the “example type”: Draggable
, Droppable
, Sortable
, Swappable
, or Plugins
. There is also a Home
folder just for the landing page, and a shared
folder for common functions and mixins that are reused across multiple content components.
Each individual example will have a single .html
view, .scss
file, and a index.js
. The index.js
is where you will initialize and author any draggable
logic. The default function exported from each index.js
file is imported and initialized in the src/scripts/examples-app.js
entry file.
Here are all of the shared components, such as the Block
component, used in many examples as draggable elements.
Sometimes these are just .scss
files, and the markup is written within a content component. If the styles contain values specific to that component, but need to be shared with other components, they will be split out into a props.scss
file. Variant classes are split out into a variants.scss
file.
Some components have a .html
file, which uses Nunjucks macros to define reusable components. For example, Block
has several variations that can be toggled through its component API. Once a Block
is imported into a view, you can render using:
{{ Block.render('one', {index: 1, draggable: true}) }}
That will render all of the markup for a Block
component, using the string one
as its Heading
, and appending the classes Block--item1
and Block--isDraggable
.
Some components will also have their own JavaScript logic, such as Plate
, which manages how the Plate
component gets transformed via a drag event.
This folder simply contains any files that need to be copied to the root dist/
folder, such as a manifest.json
or .htaccess
. There should be no reason to alter files in this folder.
All of the build scripts are found in this folder. You shouldn’t need to go in here unless you want to change how the code is compiled.
All JavaScript is generated with source maps, so you should be able to dig through errors and console.log
statements without issue.
Running yarn start
fires up a browsersync
server to view the site. While running the server, when you add/make changes to any of the files in src/
, the appropriate files will then be recompiled and output to the dist/
folder. Once a file has been compiled, the browser will automatically reload the page. For scss
changes, the new styles are injected into the page without causing a refresh.
The file watcher will also look for changes in the draggable/lib
folder, which means you can be running the examples server and making changes to the core library at the same time. Scripts will get recompiled and the browser will reload.
If while using Draggable, you encounter something that is not already covered in the Examples, please contribute back by creating a new Example under the correct grouping.
We ask that you follow our code style config and try your best to make the example consistent with the design of the site. Lean on the components already created to compose your example. If required, you can design and build your own components.
There is an open issue for building a CLI generator for new pages. If you are interested in taking this on, please assign yourself to the issue.
If you are unsure if your example has merit, feel free to open an issue and propose your idea. Always ping @tsov and @beefchimi for issues and code review!