Git Product home page Git Product logo

elm-designer's People

Contributors

ahankinson avatar axelbdt avatar charlontank avatar dependabot[bot] avatar martinsstewart avatar passiomatic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elm-designer's Issues

CodeGen: rewrite module using elm-codegen

Recently released elm-codegen package will help greatly to avoid to produce code that doesn't compile.

The idea is to generate the bindings for the Elm-ui package, add to this repo, and make it straightforward for the Elm compiler to check for any mismatched type.

Add a pure Elm color picker widget

Currently Elm Designer uses HTML <input type=color..> to pick an element color. This is extremely simple to integrate but has several limitations.

We should adapt simonh1000/elm-colorpicker and extend it to allow users to pick recently used and theme colors too. Also we need to allow users to reset a color and set an "inherit" value (where applicable).

About colors and alpha

At this point specify an opacity value within the image picker seems an anti-pattern to me:

With a totally opaque color type, we can calculate contrast for accessibility evaluation easily. An alpha channel means we'd have to emulate browser mixing to do that, which I'm not sure is consistent.
— Source

So the idea is to provide a color picker without alpha value, and provide alternative UI controls to pick opacity value (for the record Adobe Photoshop does exactly that). At the moment I'm just waiting to Elm UI 2 to finalize and then follow its API.

Also interesting for the picker design:

Preserve font weight/italic styles when switching fonts

When switching fonts the weight of the new font should match, or be closer as possible, to the weight of the old one.

The typical use-case is the following:

  • User sets some text using Work Sans Heavy Italic
  • User later switches the font family to Helvetica
  • Font weight abruptly change to Regular, which is the first available weight for Helvetica. Instead Elm Designer should land to the closer weight Helvetica has, that is bold, and keep the italicized text.

We can probably reuse the font-weight CSS mapping where Hairline is 100 and Heavy is 900 to figure out the best match we have available in the new font.

  • Fix weight on changing current node font family
  • Fix italic too
  • Fix weight and italic styles on children of the changed node when their node is set to Inherit

"Insert" menu allows to create non-renderable nodes

The new "Insert" menu allows to create non-renderable nodes, e.g. Try to create a Radio Option outside a Radio Selection.

To fix this we need to enable/disable certain app menu items accordingly to the application status. Since we need to implement this mechanism anyway it is better to postpone this fix until we have a general purpose solution.

Segfault when running with appimage-run on NixOS (regression from 0.2.0 to 0.2.1)

I'm not sure if this issue is specific to my non-standard system or not.

I'm on NixOS, a Linux distribution that does not follow standard FHS conventions. AppImages are not completely portable on this system but a tool called appimage-run is provided.

Running appimage-run ElmDesigner-0.2.0-linux.AppImage works. It correctly opens the GUI and echoes the following in the console:

Uncompress ElmDesigner-0.2.0-linux.AppImage of type 02 @ offset 188392
[=================================================================================================================================================================================================-] 2930/2930 100%
ElmDesigner-0.2.0-linux.AppImage is now installed in /home/theo/.cache/appimage-run/4c97e0aae6d9c722d07a00e4af6318536b8f9bd26e26682e2c13fd8cf605a0c2
(node:4997) electron: The default of contextIsolation is deprecated and will be changing from false to true in a future release of Electron.  See https://github.com/electron/electron/issues/23506 for more information

On the contrary, calling appimage-run ElmDesigner-0.2.1-linux.AppImage does not work. It exits with error code 139, printing the following in the console (no GUI is opened at all):

ElmDesigner-0.2.1-linux.AppImage installed in /home/theo/.cache/appimage-run/b34818eed209fd01ac2eed62afc6b9f15fd1bb3b26040799093c1c6b0f74cd46
Segmentation fault (core dumped)

Cannot upload SVG images

This is an unfortunate limit of Imgbb service, which doesn't allow SVG upload. This is quite frustrating since SVG is perfect for resolution-independent icons.

I guess that for now we can restrict the accepted images types to JPEG, WebP, PNG and GIF.

Implement proper workspace pan and zoom capability

Currently Elm Designer uses the native page CSS overflow and scroll behavior to allow the workspace to be bigger than the browser viewport.

We can swap the current implementation with something more polished by leveraging the Zoom abstraction from the elm-visualization package or elm-pan-and-zoom .

A first proof of concept implementation seems promising: https://ellie-app.com/gS7tKm4BVPNa1

We aim to mimic Figma and Sketch here and map UI commands as follows:

  • Zoom in/out: Cmd/Ctrl down + mouse wheel
  • Combined X/Y panning: Spacebar down + dragging
  • Horizontal translation: horizontal scrolling/wheel
  • Vertical translation: horizontal scrolling/wheel

Double clicking button label text doesn't let me edit it

For normal text I can double click it and to turn it into a text input that I can then edit. It seems intuitive that the same behavior would be present for the text shown on buttons, but currently it doesn't work like that.

User library

It can be convenient to save a node/group of elements for later. The idea is to allow the user to select a document element, name it, and save into a "user library", which is a particular section of the element library.

A user library item could be also reused in the codegen phase, by referencing it instead of duplicate its code over and over. This is probably the most straightforward way to allow some code reuse/structure in the generated code.

One interesting extension of this process could be the ability of alter the original document element and reflect changes to the "replicas" of such element. This mirrors similar concepts found in Figma or Sketch (Components and Symbols respectively).

In Elm we can think about it as a "view function": define once and reuse multiple times.

Implementation

Currently library has a default number of primitive elements, which mostly maps 1:1 with Elm UI functions, stored in Library.elm. The idea is to enrich such library at runtime, maybe using a List field in the model, and add more document nodes when user needs it. Every new node becomes a LibraryItem when added into such list.

Elm Designer already knows how to transform a LibraryItem into a Tree Node when use drags it into the workspace, and these new nodes are no exceptions.

So, if we want to implement the original-replicas scenario described above we need a way to discriminate the concrete, original elements and the replicas. We could turn Node into a custom type:

type Node 
  = Original NodeData
  | ReplicaOf NodeId 

While traversing the document for rendering we need to handle both custom type variants, and with replicas we need look up the data for the original one, including its children - because a replica doesn't have any content.

When a replica node is selected you can go back to its original node and edit it.

Visually there's should be an obvious way to tell apart a replica from an original node. Maybe we could mark the selection border with a different color and add a little label showing the library item name.

User library must be persistent, and for now we can save it within the current document. Ideally they should be tied to user, and available cross-documents.

Notes from Slack

Georges Boris

  • maybe this should lock the view in its own space and if the user wants to edit it it needs to open the block view. any changes will impact all blocks. the user cannot select a single piece of this block after it is grouped unless they are inside the block edit view.
  • with this, you could add fields to the block that would be the only updatable things appearing on the right pane when the user selects the block.
  • inside the block you could access those fields values through some placeholders perhaps?
  • if you want to break out of the block somewhere you just copy the current contents and make them static again.

Add a Google Font picker

Instead of hand picking nice fonts from Google service we could embed in Elm Designer information for all available typefaces (see attachment) and let users to pick all the fonts they need. Picked fonts will then appear in the inspector font family drop down.

UI changes

To pick more fonts we could have a "Settings" modal which includes a "Fonts" section.

Initially the modal can preset a list of top 20 used/most popular (we have some data about that in the JSON file). The user can expand one of these fonts and see its specimen, filter by category (Top 20, Sans Serif, Serif, Display, Scripts, etc.) or search for a font name. By clicking on a "Add font" button user adds the font to those available in the workspace.

Referencing document fonts

Each font is referenced by name in the serialized document (see Codecs.fontFamilyCodec) so it is easy to lookup a font (see Fonts.findFamily).

Note: the issue that can arise is that a user install a font using the picker, save a document with that font, uninstall it and later then reopen the document. This trigger a "missing font" scenario that we'll handle in a separate way.

Building the final font URL

Using the font JSON information we can easily build the final font URL and requests actual font files from Google, like we do today.

Refreshing the data

Periodically (at each release?) we can easily refresh the font list using the Google Webfont Helper public API: https://gwfh.mranftl.com/fonts

curl https://gwfh.mranftl.com/api/font > google-fonts.json

Google Fonts dump:
google-fonts.json.zip

Adding a page into outline or using Insert dropdown positions it at 0;0

In the new web app version of Elm Designer, when user adds a new page by dropping it onto the outline view, or using Insert->Page menu item, the software sets its position to the upper left portion of the workspace (0;0).

This forces the user to "hunt" for the new page within the workspace or use "Show in workspace" context menu item to see it. We can improve the situation in various ways:

  1. Enter a special "insert mode" where the app waits for a click into the workspace to place the page. This is a good solution for the Insert->page scenario but it feels strange when user drops items into the outline, so we could fallback to point 2) in the latter case.
  2. Using current selected element figure out its containing page and place the new page next to it, on the right or on the left, depending of the space available. This potentially overlaps other pages, but user can always rearrange them. If the are no current selection (that is, the workspace is the current document node) place the page in the center of the visibile portion of the workspace.
  3. Always place the page in the middle on the visibile portion of the workspace. This is probably the less surprising, straight behavior to keep. It has the same limitation on the point 2), potentially it makes the new page overlapping existing pages.

Codegen: don't let Elm UI defaults to leak

Currently code emitter tries to reduce to write redundant values like: zero padding, zero spacing, "regular" font weight, etc.

This is great but for certain elements this causes to Elm UI to pick its default values in the generate Elm code. I'll keep the list updated with the values that needs to be specified even if they are zero:

  • Padding for text fields
  • ✅ Background color for text fields
  • Border corner for text fields and buttons

This boils down to check for Node.type_ and decide what to do while emitting each style.

Improve UI for images fit/fill strategy

Element.shrink “Shrink an element to fit its contents.” — says the docs.

However, images has an intrinsic size so apply a shrink has no effect (see https://ellie-app.com/hqMkTncprgpa1). On the other hand, Element.fill applied to an image should shrink or enlarge it to fill the available space.

So the UI should reflect this peculiarity. The idea is to remove the "Fit" label and allow only "Fill" and "Px" options. Now that we know uploaded images dimension (stored in ImageData record) we could pre-populate the "Max" field if empty.

The above scenario works mostly fine. The only doubt is how we can have vertically responsive images, because if we fill along X, Y should be constrained to maintain the aspect-ratio. Vice versa, if we fill along Y, X should be constrained. It is unclear to me if elm-ui works like this at all.

Codegen: native font-stack is incorrect

Native font-stack is emitted incorrectly:

Font.family
    [ Font.typeface "System"
    , Font.typeface "System"
    , Font.typeface "System"
    ]

Instead, this should list all the typefaces in the font stack.

Implement border style switcher in inspector

We miss the ability to specify a border style for every element (https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Border#solid).

So let's add a new button group switcher (https://getbootstrap.com/docs/4.5/components/button-group/#basic-example) like the ones we have already, most likely positioned in the inspector between Border size and color, which sets Node.borderStyle property accordingly. I would call the three border styles labels "Solid", "Dashed" and "Dotted".

To accomplish that a new Msg is needed, so BorderStyleChanged BorderStyle would do the trick.

Media library

Add a media library to the UI so user can see and select again every document image.

We can add a "Media" tab right where the element library currently is and list all used images there. Once located the user could drop the image again on the document.

Features

  • The UI should show a list of image thumbnails with image dimensions on the right, perhaps together with the original image name
  • When dragged on a page an image should be copied into the document, so one can apply different padding, borders, cropping, etc. for the same image.

Nice-to-have features

  • Allow to drop images directly on the media library
  • Background images are used in the document too, so user expects to find them in the media library. This somewhat is linked to issue #39

Implementation

Once loaded to the document an image is added to the media library. The library could be a dictionary or a similar structure that is serialized together with the document.

If an image is deleted from the document it still remains in the library, ready to be added back later.

While still on an inspector focused field hitting "backspace" deletes a node instead

Steps to reproduce:

  • Drag a button on the page
  • Focus the horizontal position field
  • Enter a number, e.g. 10, press enter key
  • The button moves 10 to the right
  • The focus is still on the horizontal position field
  • Press backspace key to remove the 0 from the 10

The focus needs to be reset after hitting the enter key. I need to investigate on why this is not the case.

This is most likely linked to #7.

Change border and shadow type to allow a "none" option

Currently we have a sloppy way to figure out if a border or shadow style is specified:

  • Shadow: check if blur or size values are /= 0
  • Border: check if width or corner values are /= 0

When the user, after tweaking the shadow or border fields, set them back to a zero value the panel collapses unexpectedly.

This is caused by the way types are currently written, e.g.:

type alias BorderWidth =
    { locked : Bool
    , top : Int
    , right : Int
    , bottom : Int
    , left : Int
    }

Compare these with the Background type which has a None variant which precisely turns off the background style.

Border

So a first step would be to unify the BorderWidth, BorderStyle , BorderCorner and Node.borderColor values, since it makes no sense to have separate records for them. I can see something like this could work better:

type alias BorderData =
    { locked : Bool
    , top : Int
    , topLeftCorner: Int
    , right : Int
    , topRightCorner: Int
    ...
    , style: BorderStyle
    , color: Color
    }

Then we need to add the Border type to the mix, adding a None variant:

type Border 
   = None
   | Solid BorderData
   | Dashed BorderData
   | Dotted BorderData

This way to define an element border one needs to set at least a color and a width. Elm Designer can always generate some defaults: 1px border width, solid style, dark gray color and square corners (radius with 0px).

Shadow

We could change the Shadow type in the same way:

type alias ShadowData =
    { offsetX : Float
    , offsetY : Float
    , size : Float
    , blur : Float
    , color : Color    
    }

type Shadow
    = None 
    | Inner ShadowData
    | Outer ShadowData

With these changes None in the UI is then set only by the click on the panel trash can icon, make it more obvious that user is gonna to delete some styles. On the contrary, when switching from Inner to Outer style we copy the ShadowData record from one variant to another.

Note: This change causes a MAJOR schema change and it needs to be handled accordingly. We need to bump the schema version and create a decoder which reads back old JSON data serialized with v4.

Implement text transformation (uppercase, lowercase)

CSS has the ability to do text transformations: (uppercase, lowercase, etc). Does Elm UI has it? It seems not the case.

Generated Elm code

So, how do you translate lower case, uppercase in the generated Elm code? Should we pass the typed string value in the editor thru String.toUpper before rendering or CodeGen it?

Or maybe we leave the typed value untouched and we generate code that calls String.toUpper?

The UI

I guess this is best done via a pill selector Aa | AA | aa similar to Sketch (see below), mapped to a Elm type:

type FontTransform
    = Uppercase
    | Lowercase
    | None

A little digression about Small-caps

On related topic: should stuff like “small-caps”, which in Elm UI is a font feature, be in the same group of the text transformation functions? Perhaps it makes sense to a have a different place in the UI for the OpenType features.

If I look at Sketch it has a little Text Options panel (first), while Figma group everything into a Type details panel (second).

Schermata 2021-11-30 alle 17 27 08
Schermata 2021-11-30 alle 17 28 47

Triple click needed to edit paragraph

After placing a paragraph element it says "Double click to edit" but only double clicking doesn't set focus to the text input region that becomes visible. Instead a third click is needed before the user can enter text in the paragraph.

Add "space evenly" option to inspector spacing field

Internally we represent Spacing like this:

type Spacing
    = SpaceEvenly
    | Spacing ( Int, Int )

This matches Elm UI nicely. However we currently don't expose this in the UI. We should model the Spacing X/Y fields accordingly. A few gotchas:

  • row accepts an horizontal spacing only
  • column accepts a vertical spacing only
  • textColumn accepts both values and uses horizontal spacing for "floated" elements on left and right
  • paragraph seems to happily ignore SpaceEvenly (see Para1) but works like textColumn (see Para2), see: https://ellie-app.com/c2jCXBTFB5Va1

The reason why this hasn't been implemented yet is because it isn't clear how to design the UI. We can have:

  • ❌A toggle/button/whatever to switch between the evenly status and the actual horizontal spacing value (numeric input)
  • ❌A toggle/button/whatever to switch between the evenly status and the actual vertical spacing value (numeric input)
  • ❌A toggle/button/whatever to switch between the evenly status and combined horizontal and vertical spacing values (two numeric inputs) for a TextColumn node (and we need to fix this #59 fist!)
  • ✅ No spacing evenly toggle for paragraphs, instead a vertical spacing input in the inspector text spacing section (think this as a line-height)

So the only implemented scenario right now is the paragraph one, since it is quite an ad-hoc solution.

Implement outer/inner toggle for Shadow settings

Current shadow box is nice but doesn't expose the Shadow.type_ field. We should add a Outer|Inner UI toggle/chekbox which emits the corresponding shadow and innerShadow Elm UI calls.

We could use a negative value for shadow "Size" field but I fear it is too obscure to find out. One nice UI thing that could be added once we have the toggle in place is to switch it by assigning a negative value to "Size" field.

Allow to load a background image via drag and drop

Currently isn't possible to drop a background image into an element, because this will create a new image node. Hence you have to specify the image URL in the background -> image inspector panel.

The idea is to remove the editable image URL field and to allow to drop the image in the background inspector panel. The operation will trigger the usual upload progress bar, and at the end it will assign the uploaded image to the selected element background.

We can put back the image URL as a readonly field with a "copy" button aside (just like the regular image node 'info' panel).

CodeGen: selecting a radio option produce invalid code

This is caused by the option function signature: https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#option which produces Option value msg.

We could avoid to generate code for certain nodes, requiring the user to select a different element. That is, if she wants to output an option she needs to select the parent radio.

This is probably handled out-of-the-box by a more type safe generator tool like elm-codegen, see: #63

Make Parcel 2 to work or switch to a different bundler

Elm Designer still uses Parcel 1 for development and build phases.

Parcel 2

As today I have tried unsuccessfully to switch to Parcel 2 (see the parcel2 branch). While running in dev mode everything seems smooth, but when running the "build" command Parcel hangs indefinitely.

We identified the issues being in the terser module which interacts weirdly with the Parcel's Elm plugin, disabling it (manually) fix things.

So we can wait a bit and hope that Em and Terser work better together or we'll be forced to switch to a different bundler.

Other options

Vite seems very popular these days and it has an Elm plugin (https://github.com/hmsk/vite-plugin-elm) , but I personally never used it, so if you have experience with it let me now.

What do we need?

  • Elm transformer
  • Sass compiler (we have Bootstrap sass files to convert into CSS)
  • Minimal support for static assets (PNG, JPEG and SVG)

Add undo/redo commands

It happened to me to remove what I've done by pressing 4 times backspaces to remove a text but I selected the field. I had 20 minutes of work disappeared haha.

I know this is early beta but this has to be done for sure ;)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.