From bf06ccdde9afe169e07b9e0d025e75cd2756abce Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Tue, 5 Dec 2017 14:49:33 -0200 Subject: [PATCH 01/12] Initial commit for the new widgets section --- website/site/content/docs/widgets/input.md | 22 ++++ website/site/content/docs/widgets/select.md | 22 ++++ website/site/content/docs/widgetsV2.md | 114 ++++++++++++++++++++ website/site/layouts/_default/test.html | 36 +++++++ website/site/layouts/_default/widgets.html | 30 ++++++ website/site/layouts/partials/footer.html | 3 + website/site/layouts/partials/widgets.html | 14 +++ website/site/static/widgets.js | 28 +++++ website/src/css/imports/widgets.css | 42 ++++++++ website/src/css/main.css | 1 + 10 files changed, 312 insertions(+) create mode 100644 website/site/content/docs/widgets/input.md create mode 100644 website/site/content/docs/widgets/select.md create mode 100644 website/site/content/docs/widgetsV2.md create mode 100644 website/site/layouts/_default/test.html create mode 100644 website/site/layouts/_default/widgets.html create mode 100644 website/site/layouts/partials/widgets.html create mode 100644 website/site/static/widgets.js create mode 100644 website/src/css/imports/widgets.css diff --git a/website/site/content/docs/widgets/input.md b/website/site/content/docs/widgets/input.md new file mode 100644 index 000000000000..22b493cf33a2 --- /dev/null +++ b/website/site/content/docs/widgets/input.md @@ -0,0 +1,22 @@ +--- +label: "Input" +target: "input" +type: "widget" +--- + +The input widget is the most basic of all the widgets, rendering a simple ` ` field for users to insert short text. + +**Name:** input + +**UI (renders as):** text input + +**Data Type:** string + +**Options:** none, but you can add [data validation](/docs/validation/) to it + +### Example +```yaml + - { label: "Page Title", name: title, widget: input} +``` +**Renders as:** +(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md new file mode 100644 index 000000000000..f6b9710129ab --- /dev/null +++ b/website/site/content/docs/widgets/select.md @@ -0,0 +1,22 @@ +--- +label: "Select" +target: "select" +type: "widget" +--- + +The select widget renders a select input with a dropdown containing all the options you specify for your field. + +**Name:** select + +**UI (renders as):** select input (dropdown) + +**Data Type:** string + +**Options:** 'options' containing a 'label' and a 'value' for each entry + +### Example +```yaml + - { label: "Category", name: category, widget: select, options: [{label: "News", value: "news"}, {label: "Articles", value: "articles"}, {label: "Case Studies", value: "case"}} +``` +**Renders as:** +(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md new file mode 100644 index 000000000000..02a162ebb9ff --- /dev/null +++ b/website/site/content/docs/widgetsV2.md @@ -0,0 +1,114 @@ +--- +title: Widgets V2 +position: 31 +description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" +layout: "widgets" +--- + +We’re always adding new widgets, and you can also [create your own](/docs/extending)! + +### Select Widget + +The select widget allows you to pick a string value from a drop down menu + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - {label: Align Content, name: align, widget: select, options: ['left', 'center', 'right']} +``` + +### List Widget + +The list widget allows you to map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - {label: Categories, name: categories, widget: list} + - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} +``` + +Lists of objects are supported as well and require a nested field list. + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - name: authors + label: Authors + widget: list + fields: + - {label: Name, name: name, widget: string} + - {label: Description, name: description, widget: markdown} +``` + +### Relation Widget + +The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. + +The following field configuration properties are specific to fields using the relation widget: + +Property | Accepted Values | Description +--- | --- | --- +`collection` | string | name of the collection being referenced +`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value +`valueField` | string | name a field from the referenced collection whose value will be stored for the relation +`name` | text input | string + +Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: + +```yaml +collections: + - name: authors + label: Authors + folder: "authors" + create: true + fields: + - {name: name, label: Name} + - {name: twitterHandle, label: "Twitter Handle"} + - {name: bio, label: Bio, widget: text} + - name: posts + label: Posts + folder: "posts" + create: true + fields: + - {name: title, label: Title} + - {name: body, label: Body, widget: markdown} + - name: author + label: Author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name +``` + +### Date Widget / DateTime Widget + +The date and datetime widgets provide date or datetime pickers when the widget is active. The resulting date string can be formatted (uses Moment.js), and accepts a default value. The initial value will be the current date unless `false` or an empty string are provided as the default value. + +The following field configuration properties are specific to fields using the date or datetime widget: + +Property | Accepted Values | Description +--- | --- | --- +`format` | string | format string uses Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/) +`default` | boolean, string | can be a date string, or else an empty string - defaults to current date \ No newline at end of file diff --git a/website/site/layouts/_default/test.html b/website/site/layouts/_default/test.html new file mode 100644 index 000000000000..036b81d7732b --- /dev/null +++ b/website/site/layouts/_default/test.html @@ -0,0 +1,36 @@ +{{ partial "header" . }} {{ $activePage := .Params.position }} + +
+
+ +
+ {{ partial "edit-link" . }} +
+
+ {{.Dir}} +
+
+ {{.Layout}} +
+
+
+ {{ .Content }} +
+
+
+ +{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/_default/widgets.html b/website/site/layouts/_default/widgets.html new file mode 100644 index 000000000000..28d1f6b03308 --- /dev/null +++ b/website/site/layouts/_default/widgets.html @@ -0,0 +1,30 @@ +{{ partial "header" . }} {{ $activePage := .Params.position }} + +
+
+ +
+ {{ partial "edit-link" . }} +

Widgets

+

{{.Params.description}}

+ {{- partial "widgets" . -}} + {{ .Content }} +
+
+
+ +{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index bdd3b4fcf8dd..5ee8ab72f3b6 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,5 +21,8 @@ debug: false // Set debug to true if you want to inspect the dropdown }); +{{- if eq .Layout "widgets" -}} + +{{- end -}} diff --git a/website/site/layouts/partials/widgets.html b/website/site/layouts/partials/widgets.html new file mode 100644 index 000000000000..6327195bac7f --- /dev/null +++ b/website/site/layouts/partials/widgets.html @@ -0,0 +1,14 @@ +
+
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}} + {{.Params.label}} + {{- end -}} +
+
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}} +
+ {{.Content}} +
+ {{- end -}} +
+
\ No newline at end of file diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js new file mode 100644 index 000000000000..8428f334fdb2 --- /dev/null +++ b/website/site/static/widgets.js @@ -0,0 +1,28 @@ +const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud +widgets = document.getElementsByClassName("widget"); // Widgets' bodies + +let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; + +for(let i = 0; i < widgetItems.length; i++) { + widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud + const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render + openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget + + targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + + openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget + openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + + activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud + activeWidgetItem = e.target; // Sets the new active widget item as the clicked one + activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it + + + setTimeout(() => { + targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition + targetWidget.classList.add("widget_open"); // Defines the new target widget + openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + + },200) // When the transition is done, finish the process by attributing the final classes to each widget + }) +} \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css new file mode 100644 index 000000000000..585fd90d20f3 --- /dev/null +++ b/website/src/css/imports/widgets.css @@ -0,0 +1,42 @@ +.widgets { + margin: 2rem 0; +} + +.widgets__cloud { + margin: $micro -$micro; +} + +.widgets__item { + color: $darkGreen; + border: 2px solid $darkGreen; + border-radius: $borderRadius; + padding: calc($micro /2) $micro; + margin: $micro; + cursor: pointer; + transition: color .2s ease, background .2s ease; +} + +.widgets__item:hover { + background: $darkGreen; + color: white; +} + +.widgets__item_active { + background: $darkGreen; + color: white; +} + +.widgets__container { + background: $lightGrey; + padding: .5em 1em; + margin: 1.5em 0; + transition: height .2s ease +} + +.widget { + display: none; +} + +.widget_open { + display: block; +} \ No newline at end of file diff --git a/website/src/css/main.css b/website/src/css/main.css index fb7e4bd2050b..b17041d0811d 100755 --- a/website/src/css/main.css +++ b/website/src/css/main.css @@ -6,5 +6,6 @@ @import "imports/features.css"; @import "imports/inspiration.css"; @import "imports/docs.css"; +@import "imports/widgets.css"; @import "imports/footer.css"; From 1afbbe6a954bf8271142da0748aa304e022537ec Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Wed, 6 Dec 2017 15:07:44 -0200 Subject: [PATCH 02/12] Placing all the widgets and refining the CSS and Hugo logic --- website/site/content/docs/widgets/boolean.md | 20 +++++++ website/site/content/docs/widgets/date.md | 25 +++++++++ website/site/content/docs/widgets/datetime.md | 25 +++++++++ website/site/content/docs/widgets/file.md | 23 ++++++++ website/site/content/docs/widgets/image.md | 23 ++++++++ website/site/content/docs/widgets/input.md | 22 -------- website/site/content/docs/widgets/list.md | 24 +++++++++ website/site/content/docs/widgets/number.md | 29 +++++++++++ website/site/content/docs/widgets/object.md | 38 ++++++++++++++ website/site/content/docs/widgets/relation.md | 45 ++++++++++++++++ website/site/content/docs/widgets/select.md | 41 ++++++++++----- website/site/content/docs/widgets/string.md | 20 +++++++ website/site/content/docs/widgets/text.md | 20 +++++++ website/site/content/docs/widgetsV2.md | 1 - website/site/layouts/_default/single.html | 11 ++++ website/site/layouts/_default/test.html | 36 ------------- website/site/layouts/_default/widgets.html | 30 ----------- website/site/layouts/partials/footer.html | 2 +- website/site/layouts/partials/widgets.html | 1 + website/site/static/widgets.js | 6 ++- website/src/css/imports/widgets.css | 52 +++++++++++++++++-- 21 files changed, 383 insertions(+), 111 deletions(-) create mode 100644 website/site/content/docs/widgets/boolean.md create mode 100644 website/site/content/docs/widgets/date.md create mode 100644 website/site/content/docs/widgets/datetime.md create mode 100644 website/site/content/docs/widgets/file.md create mode 100644 website/site/content/docs/widgets/image.md delete mode 100644 website/site/content/docs/widgets/input.md create mode 100644 website/site/content/docs/widgets/list.md create mode 100644 website/site/content/docs/widgets/number.md create mode 100644 website/site/content/docs/widgets/object.md create mode 100644 website/site/content/docs/widgets/relation.md create mode 100644 website/site/content/docs/widgets/string.md create mode 100644 website/site/content/docs/widgets/text.md delete mode 100644 website/site/layouts/_default/test.html delete mode 100644 website/site/layouts/_default/widgets.html diff --git a/website/site/content/docs/widgets/boolean.md b/website/site/content/docs/widgets/boolean.md new file mode 100644 index 000000000000..f45748da3a52 --- /dev/null +++ b/website/site/content/docs/widgets/boolean.md @@ -0,0 +1,20 @@ +--- +label: "Boolean" +target: "boolean" +type: "widget" +--- + +### Boolean + +The boolean widget translates a toggle switch input to a true/false value. + +- Name: `boolean` +- UI: toggle switch +- Data type: boolean +- Options: + - `default`: accepts `true` or `false`; defaults to `false` +- Example: + + ```yaml + - {label: "Draft", name: "draft", widget: "boolean", default: true} + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/date.md b/website/site/content/docs/widgets/date.md new file mode 100644 index 000000000000..89450ae37dfb --- /dev/null +++ b/website/site/content/docs/widgets/date.md @@ -0,0 +1,25 @@ +--- +label: "Date" +target: "date" +type: "widget" +--- + +### Date + +The date widget translates a date picker input to a date string. For saving date and time together, use the [DateTime](#datetime) widget. + +- Name: `date` +- UI: date picker +- Data type: Moment.js-formatted date string +- Options: + - `default`: accepts a date string, or an empty string to accept blank input; otherwise defaults to current date + - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DD` +- Example: + + ```yaml + - label: "Birthdate" + name: "birthdate" + widget: "date" + default: "" + format: "MMM Do YY" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/datetime.md b/website/site/content/docs/widgets/datetime.md new file mode 100644 index 000000000000..34858089732d --- /dev/null +++ b/website/site/content/docs/widgets/datetime.md @@ -0,0 +1,25 @@ +--- +label: "DateTime" +target: "datetime" +type: "widget" +--- + +### DateTime + +The datetime widget translates a datetime picker to a datetime string. For saving the date only, use the [Date](#date) widget. + +- Name: `datetime` +- UI: datetime picker +- Data type: Moment.js-formatted datetime string +- Options: + - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime + - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DDTHH:mm:ssZ` +- Example: + + ```yaml + - label: "Start time" + name: "start" + widget: "datetime" + default: "" + format: "LLL" + ``` diff --git a/website/site/content/docs/widgets/file.md b/website/site/content/docs/widgets/file.md new file mode 100644 index 000000000000..31c870f878d6 --- /dev/null +++ b/website/site/content/docs/widgets/file.md @@ -0,0 +1,23 @@ +--- +label: "File" +target: "file" +type: "widget" +--- + +### File + +The file widget allows editors to upload a file or select an existing one from the media library. The path to the file will be saved to the field as a string. + +- Name: `file` +- UI: file picker button opens media gallery +- Data type: file path string, based on `media_folder`/`public_folder` configuration +- Options: + - `default`: accepts a file path string; defaults to null +- Example: + + ```yaml + - label: "Manual PDF" + name: "manual_pdf" + widget: "file" + default: "/uploads/general-manual.pdf" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/image.md b/website/site/content/docs/widgets/image.md new file mode 100644 index 000000000000..4159dde751d9 --- /dev/null +++ b/website/site/content/docs/widgets/image.md @@ -0,0 +1,23 @@ +--- +label: "Image" +target: "image" +type: "widget" +--- + +### Image + +The image widget allows editors to upload an image or select an existing one from the media library. The path to the image file will be saved to the field as a string. + +- Name: `image` +- UI: file picker button opens media gallery allowing image files (jpg, jpeg, webp, gif, png, bmp, tiff, svg) only; displays selected image thumbnail +- Data type: file path string, based on `media_folder`/`public_folder` configuration +- Options: + - `default`: accepts a file path string; defaults to null +- Example: + + ```yaml + - label: "Featured Image" + name: "thumbnail" + widget: "image" + default: "/uploads/chocolate-dogecoin.jpg" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/input.md b/website/site/content/docs/widgets/input.md deleted file mode 100644 index 22b493cf33a2..000000000000 --- a/website/site/content/docs/widgets/input.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -label: "Input" -target: "input" -type: "widget" ---- - -The input widget is the most basic of all the widgets, rendering a simple ` ` field for users to insert short text. - -**Name:** input - -**UI (renders as):** text input - -**Data Type:** string - -**Options:** none, but you can add [data validation](/docs/validation/) to it - -### Example -```yaml - - { label: "Page Title", name: title, widget: input} -``` -**Renders as:** -(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgets/list.md b/website/site/content/docs/widgets/list.md new file mode 100644 index 000000000000..732f31256e7d --- /dev/null +++ b/website/site/content/docs/widgets/list.md @@ -0,0 +1,24 @@ +--- +label: "List" +target: "list" +type: "widget" +--- + +### List + +The list widget allows you to create a repeatable item in the UI which saves as a comma-delimited list of items. map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: + +```yaml + - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} +``` + +Lists of objects are supported as well and require a nested field list. + +```yaml +- label: Authors + name: authors + widget: list + fields: + - {label: Name, name: name, widget: string} + - {label: Description, name: description, widget: markdown} +``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/number.md b/website/site/content/docs/widgets/number.md new file mode 100644 index 000000000000..c89e598a7f4b --- /dev/null +++ b/website/site/content/docs/widgets/number.md @@ -0,0 +1,29 @@ +--- +label: "Number" +target: "number" +type: "widget" +--- + +### Number + +The number widget uses an HTML number input, saving the value as a string, integer, or floating point number. + +- Name: `number` +- UI: HTML [number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) +- Data type: string by default; configured by `valueType` option +- Options: + - `default`: accepts string or number value; defaults to empty string + - `valueType`: accepts `int` or `float`; any other value results in saving as a string + - `min`: accepts a number for minimum value accepted; unset by default + - `max`: accepts a number for maximum value accepted; unset by default +- Example: + + ```yaml + - label: "Puppy Count" + name: "puppies" + widget: "number" + default: 2 + valueType: "int" + min: 1 + max: 101 + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/object.md b/website/site/content/docs/widgets/object.md new file mode 100644 index 000000000000..d68eaf793db1 --- /dev/null +++ b/website/site/content/docs/widgets/object.md @@ -0,0 +1,38 @@ +--- +label: "Object" +target: "object" +type: "widget" +--- + +### Object + +The object widget allows you to group multiple widgets together, nested under a single field. You can choose any widget as a child of an object widget—even other objects. + +- Name: `object` +- UI: a field containing other fields +- Data type: immutable map containing the sub-field values +- Options: + - `default`: you can set defaults within each sub-field's configuration + - `fields`: (**required**) a nested list of fields to include in your widget +- Example: + + ```yaml + - label: "Profile" + name: "profile" + widget: "object" + fields: + - {label: "Public", name: "public", widget: "boolean", default: true} + - {label: "Name", name: "name", widget: "string"} + - label: "Birthdate" + name: "birthdate" + widget: "date" + default: "" + format: "MM/DD/YYYY" + - label: "Address" + name: "address" + widget: "object" + fields: + - {label: "Street Address", name: "street", widget: "string"} + - {label: "City", name: "city", widget: "string"} + - {label: "Postal Code", name: "post-code", widget: "string"} + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md new file mode 100644 index 000000000000..c7f9cfd0bdd7 --- /dev/null +++ b/website/site/content/docs/widgets/relation.md @@ -0,0 +1,45 @@ +--- +label: "Relation" +target: "relation" +type: "widget" +--- + +### Relation + +The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. + +The following field configuration properties are specific to fields using the relation widget: + +Property | Accepted Values | Description +--- | --- | --- +`collection` | string | name of the collection being referenced +`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value +`valueField` | string | name a field from the referenced collection whose value will be stored for the relation +`name` | text input | string + +Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: + +```yaml +collections: + - name: authors + label: Authors + folder: "authors" + create: true + fields: + - {name: name, label: Name} + - {name: twitterHandle, label: "Twitter Handle"} + - {name: bio, label: Bio, widget: text} + - name: posts + label: Posts + folder: "posts" + create: true + fields: + - {name: title, label: Title} + - {name: body, label: Body, widget: markdown} + - name: author + label: Author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name +``` diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md index f6b9710129ab..285a9937f6e6 100644 --- a/website/site/content/docs/widgets/select.md +++ b/website/site/content/docs/widgets/select.md @@ -4,19 +4,32 @@ target: "select" type: "widget" --- -The select widget renders a select input with a dropdown containing all the options you specify for your field. +### Select -**Name:** select +The select widget allows you to pick a single string value from a dropdown menu. -**UI (renders as):** select input (dropdown) - -**Data Type:** string - -**Options:** 'options' containing a 'label' and a 'value' for each entry - -### Example -```yaml - - { label: "Category", name: category, widget: select, options: [{label: "News", value: "news"}, {label: "Articles", value: "articles"}, {label: "Case Studies", value: "case"}} -``` -**Renders as:** -(image here) \ No newline at end of file +- Name: `select` +- UI: HTML select input +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string + - `options`: (**required**) an array or list of options for the dropdown menu; can be listed in two ways: + - string values: the label displayed in the dropdown is the value saved in the file + - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file +- Example (options as strings): + ```yaml + - label: "Align Content" + name: "align" + widget: "select" + options: ["left", "center", "right"] + ``` +- Example (options as objects): + ```yaml + - label: "City" + name: "airport-code" + widget: "select" + options: + - { label: "Chicago", value: "ORD" } + - { label: "Paris", value: "CDG" } + - { label: "Tokyo", value: "HND" } + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/string.md b/website/site/content/docs/widgets/string.md new file mode 100644 index 000000000000..c4788e035f09 --- /dev/null +++ b/website/site/content/docs/widgets/string.md @@ -0,0 +1,20 @@ +--- +label: "String" +target: "string" +type: "widget" +--- + +### String + +The string widget translates a basic text input to a string value. For larger textarea inputs, use the [text](#text) widget. + +- Name: `string` +- UI: text input +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string +- Example: + + ```yaml + - {label: "Title", name: "title", widget: "string"} + ``` diff --git a/website/site/content/docs/widgets/text.md b/website/site/content/docs/widgets/text.md new file mode 100644 index 000000000000..6e6141548a9c --- /dev/null +++ b/website/site/content/docs/widgets/text.md @@ -0,0 +1,20 @@ +--- +label: "Text" +target: "text" +type: "widget" +--- + +### Text + +The text widget takes a multiline text field and saves it as a string. For shorter text inputs, use the [string](#string) widget. + +- Name: `text` +- UI: HTML textarea +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string +- Example: + + ```yaml + - {label: "Description", name: "description", widget: "text"} + ``` diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md index 02a162ebb9ff..60c5dc878a0d 100644 --- a/website/site/content/docs/widgetsV2.md +++ b/website/site/content/docs/widgetsV2.md @@ -2,7 +2,6 @@ title: Widgets V2 position: 31 description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" -layout: "widgets" --- We’re always adding new widgets, and you can also [create your own](/docs/extending)! diff --git a/website/site/layouts/_default/single.html b/website/site/layouts/_default/single.html index 50c7057cbc54..e6b86785ba11 100644 --- a/website/site/layouts/_default/single.html +++ b/website/site/layouts/_default/single.html @@ -7,7 +7,9 @@
@@ -15,14 +17,23 @@ {{ $subjects := where .Site.Pages "Section" "docs" }} {{ range sort $subjects "Params.position" }} + {{- if ne .Type "widget" -}} + {{- end -}} {{ end }}
+ {{- if eq .Title "Widgets V2" -}} + {{ partial "edit-link" . }} +

Widgets

+

{{.Params.description}}

+ {{- partial "widgets" . -}} {{ .Content }} + {{- else -}} {{ partial "edit-link" . }} {{ .Content }} + {{- end -}}
diff --git a/website/site/layouts/_default/test.html b/website/site/layouts/_default/test.html deleted file mode 100644 index 036b81d7732b..000000000000 --- a/website/site/layouts/_default/test.html +++ /dev/null @@ -1,36 +0,0 @@ -{{ partial "header" . }} {{ $activePage := .Params.position }} - -
-
- -
- {{ partial "edit-link" . }} -
-
- {{.Dir}} -
-
- {{.Layout}} -
-
-
- {{ .Content }} -
-
-
- -{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/_default/widgets.html b/website/site/layouts/_default/widgets.html deleted file mode 100644 index 28d1f6b03308..000000000000 --- a/website/site/layouts/_default/widgets.html +++ /dev/null @@ -1,30 +0,0 @@ -{{ partial "header" . }} {{ $activePage := .Params.position }} - -
-
- -
- {{ partial "edit-link" . }} -

Widgets

-

{{.Params.description}}

- {{- partial "widgets" . -}} - {{ .Content }} -
-
-
- -{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index 5ee8ab72f3b6..5ccee5543526 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,7 +21,7 @@ debug: false // Set debug to true if you want to inspect the dropdown }); -{{- if eq .Layout "widgets" -}} +{{- if eq .Title "Widgets V2" -}} {{- end -}} diff --git a/website/site/layouts/partials/widgets.html b/website/site/layouts/partials/widgets.html index 6327195bac7f..154b90cd2f96 100644 --- a/website/site/layouts/partials/widgets.html +++ b/website/site/layouts/partials/widgets.html @@ -5,6 +5,7 @@ {{- end -}}
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}}
{{.Content}} diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js index 8428f334fdb2..4e35b48d915f 100644 --- a/website/site/static/widgets.js +++ b/website/site/static/widgets.js @@ -1,5 +1,6 @@ const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud -widgets = document.getElementsByClassName("widget"); // Widgets' bodies +widgets = document.getElementsByClassName("widget"), // Widgets' bodies +widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; @@ -9,6 +10,7 @@ for(let i = 0; i < widgetItems.length; i++) { openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes @@ -23,6 +25,6 @@ for(let i = 0; i < widgetItems.length; i++) { targetWidget.classList.add("widget_open"); // Defines the new target widget openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget - },200) // When the transition is done, finish the process by attributing the final classes to each widget + },150) // When the transition is done, finish the process by attributing the final classes to each widget }) } \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index 585fd90d20f3..6cb9d8dbce15 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -3,7 +3,7 @@ } .widgets__cloud { - margin: $micro -$micro; + margin: $micro calc(-$micro / 2); } .widgets__item { @@ -11,9 +11,10 @@ border: 2px solid $darkGreen; border-radius: $borderRadius; padding: calc($micro /2) $micro; - margin: $micro; + margin: calc($micro / 2); cursor: pointer; transition: color .2s ease, background .2s ease; + display: inline-block; } .widgets__item:hover { @@ -27,16 +28,57 @@ } .widgets__container { + margin: 1em 0; + position: relative; +} + +.widgets__background { + position: absolute; + left: 0; + top: 0; background: $lightGrey; - padding: .5em 1em; - margin: 1.5em 0; - transition: height .2s ease + z-index: -1; + width: 100%; + height: 100%; + transition: height .15s ease; } .widget { + padding: .5em 1em; display: none; } .widget_open { display: block; +} + +.widget_closing { + display: block; + animation: widgetOpacity .15s ease forwards reverse; +} + +.widget_opening { + display: block; + position: absolute; + top: 0; + left: 0; + opacity: 0; + animation: widgetOpacity .15s .05s ease forwards; +} + +@keyframes widgetOpacity { + from { + opacity: 0 + } + to { + opacity: 1 + } +} + +.widget pre { + background: #eee !important; /* making sure the pre has proper background contrast */ +} + +.widget h3 { + margin-top: 0 !important; } \ No newline at end of file From b1bac3010c48879a0d1193979f8ed179431d6805 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Tue, 5 Dec 2017 14:49:33 -0200 Subject: [PATCH 03/12] Initial commit for the new widgets section --- website/site/content/docs/widgets/input.md | 22 ++++ website/site/content/docs/widgets/select.md | 22 ++++ website/site/content/docs/widgetsV2.md | 114 ++++++++++++++++++++ website/site/layouts/_default/test.html | 36 +++++++ website/site/layouts/_default/widgets.html | 30 ++++++ website/site/layouts/partials/footer.html | 3 + website/site/layouts/partials/widgets.html | 14 +++ website/site/static/widgets.js | 28 +++++ website/src/css/imports/widgets.css | 42 ++++++++ website/src/css/main.css | 1 + 10 files changed, 312 insertions(+) create mode 100644 website/site/content/docs/widgets/input.md create mode 100644 website/site/content/docs/widgets/select.md create mode 100644 website/site/content/docs/widgetsV2.md create mode 100644 website/site/layouts/_default/test.html create mode 100644 website/site/layouts/_default/widgets.html create mode 100644 website/site/layouts/partials/widgets.html create mode 100644 website/site/static/widgets.js create mode 100644 website/src/css/imports/widgets.css diff --git a/website/site/content/docs/widgets/input.md b/website/site/content/docs/widgets/input.md new file mode 100644 index 000000000000..22b493cf33a2 --- /dev/null +++ b/website/site/content/docs/widgets/input.md @@ -0,0 +1,22 @@ +--- +label: "Input" +target: "input" +type: "widget" +--- + +The input widget is the most basic of all the widgets, rendering a simple ` ` field for users to insert short text. + +**Name:** input + +**UI (renders as):** text input + +**Data Type:** string + +**Options:** none, but you can add [data validation](/docs/validation/) to it + +### Example +```yaml + - { label: "Page Title", name: title, widget: input} +``` +**Renders as:** +(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md new file mode 100644 index 000000000000..f6b9710129ab --- /dev/null +++ b/website/site/content/docs/widgets/select.md @@ -0,0 +1,22 @@ +--- +label: "Select" +target: "select" +type: "widget" +--- + +The select widget renders a select input with a dropdown containing all the options you specify for your field. + +**Name:** select + +**UI (renders as):** select input (dropdown) + +**Data Type:** string + +**Options:** 'options' containing a 'label' and a 'value' for each entry + +### Example +```yaml + - { label: "Category", name: category, widget: select, options: [{label: "News", value: "news"}, {label: "Articles", value: "articles"}, {label: "Case Studies", value: "case"}} +``` +**Renders as:** +(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md new file mode 100644 index 000000000000..02a162ebb9ff --- /dev/null +++ b/website/site/content/docs/widgetsV2.md @@ -0,0 +1,114 @@ +--- +title: Widgets V2 +position: 31 +description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" +layout: "widgets" +--- + +We’re always adding new widgets, and you can also [create your own](/docs/extending)! + +### Select Widget + +The select widget allows you to pick a string value from a drop down menu + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - {label: Align Content, name: align, widget: select, options: ['left', 'center', 'right']} +``` + +### List Widget + +The list widget allows you to map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - {label: Categories, name: categories, widget: list} + - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} +``` + +Lists of objects are supported as well and require a nested field list. + +```yaml +collections: + - name: posts + label: Post + folder: "_posts" + slug: "{{year}}-{{month}}-{{day}}-{{slug}}" + create: true + fields: + - {label: Title, name: title, widget: string, tagname: h1} + - {label: Body, name: body, widget: markdown} + - name: authors + label: Authors + widget: list + fields: + - {label: Name, name: name, widget: string} + - {label: Description, name: description, widget: markdown} +``` + +### Relation Widget + +The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. + +The following field configuration properties are specific to fields using the relation widget: + +Property | Accepted Values | Description +--- | --- | --- +`collection` | string | name of the collection being referenced +`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value +`valueField` | string | name a field from the referenced collection whose value will be stored for the relation +`name` | text input | string + +Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: + +```yaml +collections: + - name: authors + label: Authors + folder: "authors" + create: true + fields: + - {name: name, label: Name} + - {name: twitterHandle, label: "Twitter Handle"} + - {name: bio, label: Bio, widget: text} + - name: posts + label: Posts + folder: "posts" + create: true + fields: + - {name: title, label: Title} + - {name: body, label: Body, widget: markdown} + - name: author + label: Author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name +``` + +### Date Widget / DateTime Widget + +The date and datetime widgets provide date or datetime pickers when the widget is active. The resulting date string can be formatted (uses Moment.js), and accepts a default value. The initial value will be the current date unless `false` or an empty string are provided as the default value. + +The following field configuration properties are specific to fields using the date or datetime widget: + +Property | Accepted Values | Description +--- | --- | --- +`format` | string | format string uses Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/) +`default` | boolean, string | can be a date string, or else an empty string - defaults to current date \ No newline at end of file diff --git a/website/site/layouts/_default/test.html b/website/site/layouts/_default/test.html new file mode 100644 index 000000000000..036b81d7732b --- /dev/null +++ b/website/site/layouts/_default/test.html @@ -0,0 +1,36 @@ +{{ partial "header" . }} {{ $activePage := .Params.position }} + +
+
+ +
+ {{ partial "edit-link" . }} +
+
+ {{.Dir}} +
+
+ {{.Layout}} +
+
+
+ {{ .Content }} +
+
+
+ +{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/_default/widgets.html b/website/site/layouts/_default/widgets.html new file mode 100644 index 000000000000..28d1f6b03308 --- /dev/null +++ b/website/site/layouts/_default/widgets.html @@ -0,0 +1,30 @@ +{{ partial "header" . }} {{ $activePage := .Params.position }} + +
+
+ +
+ {{ partial "edit-link" . }} +

Widgets

+

{{.Params.description}}

+ {{- partial "widgets" . -}} + {{ .Content }} +
+
+
+ +{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index bdd3b4fcf8dd..5ee8ab72f3b6 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,5 +21,8 @@ debug: false // Set debug to true if you want to inspect the dropdown }); +{{- if eq .Layout "widgets" -}} + +{{- end -}} diff --git a/website/site/layouts/partials/widgets.html b/website/site/layouts/partials/widgets.html new file mode 100644 index 000000000000..6327195bac7f --- /dev/null +++ b/website/site/layouts/partials/widgets.html @@ -0,0 +1,14 @@ +
+
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}} + {{.Params.label}} + {{- end -}} +
+
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}} +
+ {{.Content}} +
+ {{- end -}} +
+
\ No newline at end of file diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js new file mode 100644 index 000000000000..8428f334fdb2 --- /dev/null +++ b/website/site/static/widgets.js @@ -0,0 +1,28 @@ +const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud +widgets = document.getElementsByClassName("widget"); // Widgets' bodies + +let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; + +for(let i = 0; i < widgetItems.length; i++) { + widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud + const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render + openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget + + targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + + openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget + openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + + activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud + activeWidgetItem = e.target; // Sets the new active widget item as the clicked one + activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it + + + setTimeout(() => { + targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition + targetWidget.classList.add("widget_open"); // Defines the new target widget + openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + + },200) // When the transition is done, finish the process by attributing the final classes to each widget + }) +} \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css new file mode 100644 index 000000000000..585fd90d20f3 --- /dev/null +++ b/website/src/css/imports/widgets.css @@ -0,0 +1,42 @@ +.widgets { + margin: 2rem 0; +} + +.widgets__cloud { + margin: $micro -$micro; +} + +.widgets__item { + color: $darkGreen; + border: 2px solid $darkGreen; + border-radius: $borderRadius; + padding: calc($micro /2) $micro; + margin: $micro; + cursor: pointer; + transition: color .2s ease, background .2s ease; +} + +.widgets__item:hover { + background: $darkGreen; + color: white; +} + +.widgets__item_active { + background: $darkGreen; + color: white; +} + +.widgets__container { + background: $lightGrey; + padding: .5em 1em; + margin: 1.5em 0; + transition: height .2s ease +} + +.widget { + display: none; +} + +.widget_open { + display: block; +} \ No newline at end of file diff --git a/website/src/css/main.css b/website/src/css/main.css index fb7e4bd2050b..b17041d0811d 100755 --- a/website/src/css/main.css +++ b/website/src/css/main.css @@ -6,5 +6,6 @@ @import "imports/features.css"; @import "imports/inspiration.css"; @import "imports/docs.css"; +@import "imports/widgets.css"; @import "imports/footer.css"; From e08d17e7fb75026d2034d775c9c2a9fe76955ce5 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Wed, 6 Dec 2017 15:07:44 -0200 Subject: [PATCH 04/12] Placing all the widgets and refining the CSS and Hugo logic --- website/site/content/docs/widgets/boolean.md | 20 +++++++ website/site/content/docs/widgets/date.md | 25 +++++++++ website/site/content/docs/widgets/datetime.md | 25 +++++++++ website/site/content/docs/widgets/file.md | 23 ++++++++ website/site/content/docs/widgets/image.md | 23 ++++++++ website/site/content/docs/widgets/input.md | 22 -------- website/site/content/docs/widgets/list.md | 24 +++++++++ website/site/content/docs/widgets/number.md | 29 +++++++++++ website/site/content/docs/widgets/object.md | 38 ++++++++++++++ website/site/content/docs/widgets/relation.md | 45 ++++++++++++++++ website/site/content/docs/widgets/select.md | 41 ++++++++++----- website/site/content/docs/widgets/string.md | 20 +++++++ website/site/content/docs/widgets/text.md | 20 +++++++ website/site/content/docs/widgetsV2.md | 1 - website/site/layouts/_default/single.html | 11 ++++ website/site/layouts/_default/test.html | 36 ------------- website/site/layouts/_default/widgets.html | 30 ----------- website/site/layouts/partials/footer.html | 2 +- website/site/layouts/partials/widgets.html | 1 + website/site/static/widgets.js | 6 ++- website/src/css/imports/widgets.css | 52 +++++++++++++++++-- 21 files changed, 383 insertions(+), 111 deletions(-) create mode 100644 website/site/content/docs/widgets/boolean.md create mode 100644 website/site/content/docs/widgets/date.md create mode 100644 website/site/content/docs/widgets/datetime.md create mode 100644 website/site/content/docs/widgets/file.md create mode 100644 website/site/content/docs/widgets/image.md delete mode 100644 website/site/content/docs/widgets/input.md create mode 100644 website/site/content/docs/widgets/list.md create mode 100644 website/site/content/docs/widgets/number.md create mode 100644 website/site/content/docs/widgets/object.md create mode 100644 website/site/content/docs/widgets/relation.md create mode 100644 website/site/content/docs/widgets/string.md create mode 100644 website/site/content/docs/widgets/text.md delete mode 100644 website/site/layouts/_default/test.html delete mode 100644 website/site/layouts/_default/widgets.html diff --git a/website/site/content/docs/widgets/boolean.md b/website/site/content/docs/widgets/boolean.md new file mode 100644 index 000000000000..f45748da3a52 --- /dev/null +++ b/website/site/content/docs/widgets/boolean.md @@ -0,0 +1,20 @@ +--- +label: "Boolean" +target: "boolean" +type: "widget" +--- + +### Boolean + +The boolean widget translates a toggle switch input to a true/false value. + +- Name: `boolean` +- UI: toggle switch +- Data type: boolean +- Options: + - `default`: accepts `true` or `false`; defaults to `false` +- Example: + + ```yaml + - {label: "Draft", name: "draft", widget: "boolean", default: true} + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/date.md b/website/site/content/docs/widgets/date.md new file mode 100644 index 000000000000..89450ae37dfb --- /dev/null +++ b/website/site/content/docs/widgets/date.md @@ -0,0 +1,25 @@ +--- +label: "Date" +target: "date" +type: "widget" +--- + +### Date + +The date widget translates a date picker input to a date string. For saving date and time together, use the [DateTime](#datetime) widget. + +- Name: `date` +- UI: date picker +- Data type: Moment.js-formatted date string +- Options: + - `default`: accepts a date string, or an empty string to accept blank input; otherwise defaults to current date + - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DD` +- Example: + + ```yaml + - label: "Birthdate" + name: "birthdate" + widget: "date" + default: "" + format: "MMM Do YY" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/datetime.md b/website/site/content/docs/widgets/datetime.md new file mode 100644 index 000000000000..34858089732d --- /dev/null +++ b/website/site/content/docs/widgets/datetime.md @@ -0,0 +1,25 @@ +--- +label: "DateTime" +target: "datetime" +type: "widget" +--- + +### DateTime + +The datetime widget translates a datetime picker to a datetime string. For saving the date only, use the [Date](#date) widget. + +- Name: `datetime` +- UI: datetime picker +- Data type: Moment.js-formatted datetime string +- Options: + - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime + - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DDTHH:mm:ssZ` +- Example: + + ```yaml + - label: "Start time" + name: "start" + widget: "datetime" + default: "" + format: "LLL" + ``` diff --git a/website/site/content/docs/widgets/file.md b/website/site/content/docs/widgets/file.md new file mode 100644 index 000000000000..31c870f878d6 --- /dev/null +++ b/website/site/content/docs/widgets/file.md @@ -0,0 +1,23 @@ +--- +label: "File" +target: "file" +type: "widget" +--- + +### File + +The file widget allows editors to upload a file or select an existing one from the media library. The path to the file will be saved to the field as a string. + +- Name: `file` +- UI: file picker button opens media gallery +- Data type: file path string, based on `media_folder`/`public_folder` configuration +- Options: + - `default`: accepts a file path string; defaults to null +- Example: + + ```yaml + - label: "Manual PDF" + name: "manual_pdf" + widget: "file" + default: "/uploads/general-manual.pdf" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/image.md b/website/site/content/docs/widgets/image.md new file mode 100644 index 000000000000..4159dde751d9 --- /dev/null +++ b/website/site/content/docs/widgets/image.md @@ -0,0 +1,23 @@ +--- +label: "Image" +target: "image" +type: "widget" +--- + +### Image + +The image widget allows editors to upload an image or select an existing one from the media library. The path to the image file will be saved to the field as a string. + +- Name: `image` +- UI: file picker button opens media gallery allowing image files (jpg, jpeg, webp, gif, png, bmp, tiff, svg) only; displays selected image thumbnail +- Data type: file path string, based on `media_folder`/`public_folder` configuration +- Options: + - `default`: accepts a file path string; defaults to null +- Example: + + ```yaml + - label: "Featured Image" + name: "thumbnail" + widget: "image" + default: "/uploads/chocolate-dogecoin.jpg" + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/input.md b/website/site/content/docs/widgets/input.md deleted file mode 100644 index 22b493cf33a2..000000000000 --- a/website/site/content/docs/widgets/input.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -label: "Input" -target: "input" -type: "widget" ---- - -The input widget is the most basic of all the widgets, rendering a simple ` ` field for users to insert short text. - -**Name:** input - -**UI (renders as):** text input - -**Data Type:** string - -**Options:** none, but you can add [data validation](/docs/validation/) to it - -### Example -```yaml - - { label: "Page Title", name: title, widget: input} -``` -**Renders as:** -(image here) \ No newline at end of file diff --git a/website/site/content/docs/widgets/list.md b/website/site/content/docs/widgets/list.md new file mode 100644 index 000000000000..732f31256e7d --- /dev/null +++ b/website/site/content/docs/widgets/list.md @@ -0,0 +1,24 @@ +--- +label: "List" +target: "list" +type: "widget" +--- + +### List + +The list widget allows you to create a repeatable item in the UI which saves as a comma-delimited list of items. map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: + +```yaml + - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} +``` + +Lists of objects are supported as well and require a nested field list. + +```yaml +- label: Authors + name: authors + widget: list + fields: + - {label: Name, name: name, widget: string} + - {label: Description, name: description, widget: markdown} +``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/number.md b/website/site/content/docs/widgets/number.md new file mode 100644 index 000000000000..c89e598a7f4b --- /dev/null +++ b/website/site/content/docs/widgets/number.md @@ -0,0 +1,29 @@ +--- +label: "Number" +target: "number" +type: "widget" +--- + +### Number + +The number widget uses an HTML number input, saving the value as a string, integer, or floating point number. + +- Name: `number` +- UI: HTML [number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) +- Data type: string by default; configured by `valueType` option +- Options: + - `default`: accepts string or number value; defaults to empty string + - `valueType`: accepts `int` or `float`; any other value results in saving as a string + - `min`: accepts a number for minimum value accepted; unset by default + - `max`: accepts a number for maximum value accepted; unset by default +- Example: + + ```yaml + - label: "Puppy Count" + name: "puppies" + widget: "number" + default: 2 + valueType: "int" + min: 1 + max: 101 + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/object.md b/website/site/content/docs/widgets/object.md new file mode 100644 index 000000000000..d68eaf793db1 --- /dev/null +++ b/website/site/content/docs/widgets/object.md @@ -0,0 +1,38 @@ +--- +label: "Object" +target: "object" +type: "widget" +--- + +### Object + +The object widget allows you to group multiple widgets together, nested under a single field. You can choose any widget as a child of an object widget—even other objects. + +- Name: `object` +- UI: a field containing other fields +- Data type: immutable map containing the sub-field values +- Options: + - `default`: you can set defaults within each sub-field's configuration + - `fields`: (**required**) a nested list of fields to include in your widget +- Example: + + ```yaml + - label: "Profile" + name: "profile" + widget: "object" + fields: + - {label: "Public", name: "public", widget: "boolean", default: true} + - {label: "Name", name: "name", widget: "string"} + - label: "Birthdate" + name: "birthdate" + widget: "date" + default: "" + format: "MM/DD/YYYY" + - label: "Address" + name: "address" + widget: "object" + fields: + - {label: "Street Address", name: "street", widget: "string"} + - {label: "City", name: "city", widget: "string"} + - {label: "Postal Code", name: "post-code", widget: "string"} + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md new file mode 100644 index 000000000000..c7f9cfd0bdd7 --- /dev/null +++ b/website/site/content/docs/widgets/relation.md @@ -0,0 +1,45 @@ +--- +label: "Relation" +target: "relation" +type: "widget" +--- + +### Relation + +The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. + +The following field configuration properties are specific to fields using the relation widget: + +Property | Accepted Values | Description +--- | --- | --- +`collection` | string | name of the collection being referenced +`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value +`valueField` | string | name a field from the referenced collection whose value will be stored for the relation +`name` | text input | string + +Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: + +```yaml +collections: + - name: authors + label: Authors + folder: "authors" + create: true + fields: + - {name: name, label: Name} + - {name: twitterHandle, label: "Twitter Handle"} + - {name: bio, label: Bio, widget: text} + - name: posts + label: Posts + folder: "posts" + create: true + fields: + - {name: title, label: Title} + - {name: body, label: Body, widget: markdown} + - name: author + label: Author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name +``` diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md index f6b9710129ab..285a9937f6e6 100644 --- a/website/site/content/docs/widgets/select.md +++ b/website/site/content/docs/widgets/select.md @@ -4,19 +4,32 @@ target: "select" type: "widget" --- -The select widget renders a select input with a dropdown containing all the options you specify for your field. +### Select -**Name:** select +The select widget allows you to pick a single string value from a dropdown menu. -**UI (renders as):** select input (dropdown) - -**Data Type:** string - -**Options:** 'options' containing a 'label' and a 'value' for each entry - -### Example -```yaml - - { label: "Category", name: category, widget: select, options: [{label: "News", value: "news"}, {label: "Articles", value: "articles"}, {label: "Case Studies", value: "case"}} -``` -**Renders as:** -(image here) \ No newline at end of file +- Name: `select` +- UI: HTML select input +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string + - `options`: (**required**) an array or list of options for the dropdown menu; can be listed in two ways: + - string values: the label displayed in the dropdown is the value saved in the file + - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file +- Example (options as strings): + ```yaml + - label: "Align Content" + name: "align" + widget: "select" + options: ["left", "center", "right"] + ``` +- Example (options as objects): + ```yaml + - label: "City" + name: "airport-code" + widget: "select" + options: + - { label: "Chicago", value: "ORD" } + - { label: "Paris", value: "CDG" } + - { label: "Tokyo", value: "HND" } + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/string.md b/website/site/content/docs/widgets/string.md new file mode 100644 index 000000000000..c4788e035f09 --- /dev/null +++ b/website/site/content/docs/widgets/string.md @@ -0,0 +1,20 @@ +--- +label: "String" +target: "string" +type: "widget" +--- + +### String + +The string widget translates a basic text input to a string value. For larger textarea inputs, use the [text](#text) widget. + +- Name: `string` +- UI: text input +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string +- Example: + + ```yaml + - {label: "Title", name: "title", widget: "string"} + ``` diff --git a/website/site/content/docs/widgets/text.md b/website/site/content/docs/widgets/text.md new file mode 100644 index 000000000000..6e6141548a9c --- /dev/null +++ b/website/site/content/docs/widgets/text.md @@ -0,0 +1,20 @@ +--- +label: "Text" +target: "text" +type: "widget" +--- + +### Text + +The text widget takes a multiline text field and saves it as a string. For shorter text inputs, use the [string](#string) widget. + +- Name: `text` +- UI: HTML textarea +- Data type: string +- Options: + - `default`: accepts a string; defaults to an empty string +- Example: + + ```yaml + - {label: "Description", name: "description", widget: "text"} + ``` diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md index 02a162ebb9ff..60c5dc878a0d 100644 --- a/website/site/content/docs/widgetsV2.md +++ b/website/site/content/docs/widgetsV2.md @@ -2,7 +2,6 @@ title: Widgets V2 position: 31 description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" -layout: "widgets" --- We’re always adding new widgets, and you can also [create your own](/docs/extending)! diff --git a/website/site/layouts/_default/single.html b/website/site/layouts/_default/single.html index 50c7057cbc54..e6b86785ba11 100644 --- a/website/site/layouts/_default/single.html +++ b/website/site/layouts/_default/single.html @@ -7,7 +7,9 @@
@@ -15,14 +17,23 @@ {{ $subjects := where .Site.Pages "Section" "docs" }} {{ range sort $subjects "Params.position" }} + {{- if ne .Type "widget" -}} + {{- end -}} {{ end }}
+ {{- if eq .Title "Widgets V2" -}} + {{ partial "edit-link" . }} +

Widgets

+

{{.Params.description}}

+ {{- partial "widgets" . -}} {{ .Content }} + {{- else -}} {{ partial "edit-link" . }} {{ .Content }} + {{- end -}}
diff --git a/website/site/layouts/_default/test.html b/website/site/layouts/_default/test.html deleted file mode 100644 index 036b81d7732b..000000000000 --- a/website/site/layouts/_default/test.html +++ /dev/null @@ -1,36 +0,0 @@ -{{ partial "header" . }} {{ $activePage := .Params.position }} - -
-
- -
- {{ partial "edit-link" . }} -
-
- {{.Dir}} -
-
- {{.Layout}} -
-
-
- {{ .Content }} -
-
-
- -{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/_default/widgets.html b/website/site/layouts/_default/widgets.html deleted file mode 100644 index 28d1f6b03308..000000000000 --- a/website/site/layouts/_default/widgets.html +++ /dev/null @@ -1,30 +0,0 @@ -{{ partial "header" . }} {{ $activePage := .Params.position }} - -
-
- -
- {{ partial "edit-link" . }} -

Widgets

-

{{.Params.description}}

- {{- partial "widgets" . -}} - {{ .Content }} -
-
-
- -{{ partial "footer" . }} \ No newline at end of file diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index 5ee8ab72f3b6..5ccee5543526 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,7 +21,7 @@ debug: false // Set debug to true if you want to inspect the dropdown }); -{{- if eq .Layout "widgets" -}} +{{- if eq .Title "Widgets V2" -}} {{- end -}} diff --git a/website/site/layouts/partials/widgets.html b/website/site/layouts/partials/widgets.html index 6327195bac7f..154b90cd2f96 100644 --- a/website/site/layouts/partials/widgets.html +++ b/website/site/layouts/partials/widgets.html @@ -5,6 +5,7 @@ {{- end -}}
+ {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}}
{{.Content}} diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js index 8428f334fdb2..4e35b48d915f 100644 --- a/website/site/static/widgets.js +++ b/website/site/static/widgets.js @@ -1,5 +1,6 @@ const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud -widgets = document.getElementsByClassName("widget"); // Widgets' bodies +widgets = document.getElementsByClassName("widget"), // Widgets' bodies +widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; @@ -9,6 +10,7 @@ for(let i = 0; i < widgetItems.length; i++) { openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes @@ -23,6 +25,6 @@ for(let i = 0; i < widgetItems.length; i++) { targetWidget.classList.add("widget_open"); // Defines the new target widget openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget - },200) // When the transition is done, finish the process by attributing the final classes to each widget + },150) // When the transition is done, finish the process by attributing the final classes to each widget }) } \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index 585fd90d20f3..6cb9d8dbce15 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -3,7 +3,7 @@ } .widgets__cloud { - margin: $micro -$micro; + margin: $micro calc(-$micro / 2); } .widgets__item { @@ -11,9 +11,10 @@ border: 2px solid $darkGreen; border-radius: $borderRadius; padding: calc($micro /2) $micro; - margin: $micro; + margin: calc($micro / 2); cursor: pointer; transition: color .2s ease, background .2s ease; + display: inline-block; } .widgets__item:hover { @@ -27,16 +28,57 @@ } .widgets__container { + margin: 1em 0; + position: relative; +} + +.widgets__background { + position: absolute; + left: 0; + top: 0; background: $lightGrey; - padding: .5em 1em; - margin: 1.5em 0; - transition: height .2s ease + z-index: -1; + width: 100%; + height: 100%; + transition: height .15s ease; } .widget { + padding: .5em 1em; display: none; } .widget_open { display: block; +} + +.widget_closing { + display: block; + animation: widgetOpacity .15s ease forwards reverse; +} + +.widget_opening { + display: block; + position: absolute; + top: 0; + left: 0; + opacity: 0; + animation: widgetOpacity .15s .05s ease forwards; +} + +@keyframes widgetOpacity { + from { + opacity: 0 + } + to { + opacity: 1 + } +} + +.widget pre { + background: #eee !important; /* making sure the pre has proper background contrast */ +} + +.widget h3 { + margin-top: 0 !important; } \ No newline at end of file From a9ab8fdeac9bcab64b0de4e28c5f2bd92326b88e Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Thu, 7 Dec 2017 10:40:42 -0200 Subject: [PATCH 05/12] Rebased and updated the info according to @verythorough contribution --- website/site/content/docs/widgets/hidden.md | 20 +++ website/site/content/docs/widgets/list.md | 59 ++++++--- website/site/content/docs/widgets/relation.md | 54 +++----- website/site/content/docs/widgetsV2.md | 120 +++--------------- website/site/layouts/_default/single.html | 4 +- website/src/css/imports/widgets.css | 5 + 6 files changed, 108 insertions(+), 154 deletions(-) create mode 100644 website/site/content/docs/widgets/hidden.md diff --git a/website/site/content/docs/widgets/hidden.md b/website/site/content/docs/widgets/hidden.md new file mode 100644 index 000000000000..6a17db732e75 --- /dev/null +++ b/website/site/content/docs/widgets/hidden.md @@ -0,0 +1,20 @@ +--- +label: "Hidden" +target: "hidden" +type: "widget" +--- + +### Hidden + +Hidden widgets do not display in the UI. In folder collections that allow users to create new items, you will often want to set a default for hidden fields, so they will be set without requiring an input. + +- **Name:** `hidden` +- **UI:** none +- **Data type:** any valid data type +- **Options:** + - `default`: accepts any valid data type; recommended for collections that allow adding new items +- **Example:** + + ```yaml + - {label: "Layout", name: "layout", widget: "hidden", default: "blog"} + ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/list.md b/website/site/content/docs/widgets/list.md index 732f31256e7d..fac4e3201f68 100644 --- a/website/site/content/docs/widgets/list.md +++ b/website/site/content/docs/widgets/list.md @@ -6,19 +6,46 @@ type: "widget" ### List -The list widget allows you to create a repeatable item in the UI which saves as a comma-delimited list of items. map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: - -```yaml - - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} -``` - -Lists of objects are supported as well and require a nested field list. - -```yaml -- label: Authors - name: authors - widget: list - fields: - - {label: Name, name: name, widget: string} - - {label: Description, name: description, widget: markdown} -``` \ No newline at end of file +The list widget allows you to create a repeatable item in the UI which saves as a list of widget values. map a user-provided string with a comma delimiter into a list. You can choose any widget as a child of a list widget—even other lists. + +- **Name:** `list` +- **UI:** if `fields` is specified, field containing a repeatable child widget, with controls for adding, deleting, and re-ordering the repeated widgets; if unspecified, a text input for entering comma-separated values +- **Data type:** list of widget values +- **Options:** + - `default`: if `fields` is specified, declare defaults on the child widgets; if not, you may specify a list of strings to populate the text field + - `field`: a single widget field to be repeated + - `fields`: a nested list of multiple widget fields to be included in each repeatable iteration +- **Example** (`field`/`fields` not specified): + + ```yaml + - label: "Tags" + name: "tags" + widget: "list" + default: ["news"] + ``` + +- **Example** (with `field`): + + ```yaml + - label: "Gallery" + name: "galleryImages" + widget: "list" + field: + - {label: Image, name: image, widget: image} + ``` + +- **Example** (with `fields`): + + ```yaml + - label: "Testimonials" + name: "testimonials" + widget: "list" + fields: + - {label: Quote, name: quote, widget: string, default: "Everything is awesome!"} + - label: Author + name: author + widget: object + fields: + - {label: Name, name: name, widget: string, default: "Emmet"} + - {label: Avatar, name: avatar, widget: image, default: "/img/emmet.jpg"} + ``` diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md index c7f9cfd0bdd7..9b7049b26577 100644 --- a/website/site/content/docs/widgets/relation.md +++ b/website/site/content/docs/widgets/relation.md @@ -6,40 +6,24 @@ type: "widget" ### Relation -The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. +The relation widget allows you to reference items from another collection. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. -The following field configuration properties are specific to fields using the relation widget: +- **Name:** `realtion` +- **UI:** text input with search result dropdown +- **Data type:** data type of the value pulled from the related collection item +- **Options:** + - `default`: accepts any widget data type; defaults to an empty string + - `collection`: (**required**) name of the collection being referenced (string) + - `searchFields`: (**required**) list of one or more names of fields in the referenced collection to search for the typed value + - `valueField`: (**required**) name of the field from the referenced collection whose value will be stored for the relation +- **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields): -Property | Accepted Values | Description ---- | --- | --- -`collection` | string | name of the collection being referenced -`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value -`valueField` | string | name a field from the referenced collection whose value will be stored for the relation -`name` | text input | string - -Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: - -```yaml -collections: - - name: authors - label: Authors - folder: "authors" - create: true - fields: - - {name: name, label: Name} - - {name: twitterHandle, label: "Twitter Handle"} - - {name: bio, label: Bio, widget: text} - - name: posts - label: Posts - folder: "posts" - create: true - fields: - - {name: title, label: Title} - - {name: body, label: Body, widget: markdown} - - name: author - label: Author - widget: relation - collection: authors - searchFields: [name, twitterHandle] - valueField: name -``` + ```yaml + - label: Post Author + name: author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name + ``` + The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. \ No newline at end of file diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md index 60c5dc878a0d..24562cb96cb0 100644 --- a/website/site/content/docs/widgetsV2.md +++ b/website/site/content/docs/widgetsV2.md @@ -1,113 +1,31 @@ --- title: Widgets V2 position: 31 -description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" +paragraphs: + - "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)!" + - "Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both." + - "To see working examples of all of the built-in widgets, try making a 'Kitchen Sink' collection item on the [CMS demo site](https://cms-demo.netlify.com). (No login required: click the login button and the CMS will open.) You can refer to the demo [configuration code](https://github.com/netlify/netlify-cms/blob/master/example/config.yml#L60) to see how each field was configured." --- -We’re always adding new widgets, and you can also [create your own](/docs/extending)! +Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)! -### Select Widget +Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both. -The select widget allows you to pick a string value from a drop down menu +To see working examples of all of the built-in widgets, try making a 'Kitchen Sink' collection item on the [CMS demo site](https://cms-demo.netlify.com). (No login required: click the login button and the CMS will open.) You can refer to the demo [configuration code](https://github.com/netlify/netlify-cms/blob/master/example/config.yml#L60) to see how each field was configured. -```yaml -collections: - - name: posts - label: Post - folder: "_posts" - slug: "{{year}}-{{month}}-{{day}}-{{slug}}" - create: true - fields: - - {label: Title, name: title, widget: string, tagname: h1} - - {label: Body, name: body, widget: markdown} - - {label: Align Content, name: align, widget: select, options: ['left', 'center', 'right']} -``` +## Common widget options -### List Widget +The following options are available on all fields: -The list widget allows you to map a user-provided string with a comma delimiter into a list. Consider the following example that also demonstrates how to set default values: +- `required`: specify as `false` to make a field optional; defaults to `true` +- `pattern`: add field validation by specifying a list with a regex pattern and an error message; more extensive validation can be achieved with [custom widgets](https://www.netlifycms.org/docs/custom-widgets/#advanced-field-validation) + - **Example:** -```yaml -collections: - - name: posts - label: Post - folder: "_posts" - slug: "{{year}}-{{month}}-{{day}}-{{slug}}" - create: true - fields: - - {label: Title, name: title, widget: string, tagname: h1} - - {label: Body, name: body, widget: markdown} - - {label: Categories, name: categories, widget: list} - - {label: Tags, name: tags, widget: list, default: ['term_1', 'term_2']} -``` + ```yaml + - label: "Title" + name: "title" + widget: "string" + pattern: ['.{10,}', "Must have at least 20 characters"] + ``` -Lists of objects are supported as well and require a nested field list. - -```yaml -collections: - - name: posts - label: Post - folder: "_posts" - slug: "{{year}}-{{month}}-{{day}}-{{slug}}" - create: true - fields: - - {label: Title, name: title, widget: string, tagname: h1} - - {label: Body, name: body, widget: markdown} - - name: authors - label: Authors - widget: list - fields: - - {label: Name, name: name, widget: string} - - {label: Description, name: description, widget: markdown} -``` - -### Relation Widget - -The relation widget allows you to reference an existing entry from within the entry you're editing. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. - -The following field configuration properties are specific to fields using the relation widget: - -Property | Accepted Values | Description ---- | --- | --- -`collection` | string | name of the collection being referenced -`searchFields` | list | one or more names of fields in the referenced colleciton to search for the typed value -`valueField` | string | name a field from the referenced collection whose value will be stored for the relation -`name` | text input | string - -Let's say we have a "posts" collection and an "authors" collection, and we want to select an author for each post - our config might look something like this: - -```yaml -collections: - - name: authors - label: Authors - folder: "authors" - create: true - fields: - - {name: name, label: Name} - - {name: twitterHandle, label: "Twitter Handle"} - - {name: bio, label: Bio, widget: text} - - name: posts - label: Posts - folder: "posts" - create: true - fields: - - {name: title, label: Title} - - {name: body, label: Body, widget: markdown} - - name: author - label: Author - widget: relation - collection: authors - searchFields: [name, twitterHandle] - valueField: name -``` - -### Date Widget / DateTime Widget - -The date and datetime widgets provide date or datetime pickers when the widget is active. The resulting date string can be formatted (uses Moment.js), and accepts a default value. The initial value will be the current date unless `false` or an empty string are provided as the default value. - -The following field configuration properties are specific to fields using the date or datetime widget: - -Property | Accepted Values | Description ---- | --- | --- -`format` | string | format string uses Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/) -`default` | boolean, string | can be a date string, or else an empty string - defaults to current date \ No newline at end of file +## Check out all of the widgets \ No newline at end of file diff --git a/website/site/layouts/_default/single.html b/website/site/layouts/_default/single.html index e6b86785ba11..5927be15ba92 100644 --- a/website/site/layouts/_default/single.html +++ b/website/site/layouts/_default/single.html @@ -28,8 +28,8 @@ {{- if eq .Title "Widgets V2" -}} {{ partial "edit-link" . }}

Widgets

-

{{.Params.description}}

- {{- partial "widgets" . -}} {{ .Content }} + {{ .Content }} + {{- partial "widgets" . -}} {{- else -}} {{ partial "edit-link" . }} {{ .Content }} diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index 6cb9d8dbce15..43e26d5f8359 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -37,6 +37,7 @@ left: 0; top: 0; background: $lightGrey; + border-radius: $borderRadius; z-index: -1; width: 100%; height: 100%; @@ -66,6 +67,10 @@ animation: widgetOpacity .15s .05s ease forwards; } +.widget#list { + padding-bottom: 3em; /* For some weird reason the list widget was overflowing the background, so this dirty fix works */ +} + @keyframes widgetOpacity { from { opacity: 0 From 7cb8c8f4c7a89e3c2af746b4976f1bacc9abeca8 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Thu, 7 Dec 2017 10:51:59 -0200 Subject: [PATCH 06/12] Fixing the yaml codes for the relation and select widget sections --- website/site/content/docs/widgets/relation.md | 12 ++++++------ website/site/content/docs/widgets/select.md | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md index 9b7049b26577..54cae2cb8262 100644 --- a/website/site/content/docs/widgets/relation.md +++ b/website/site/content/docs/widgets/relation.md @@ -19,11 +19,11 @@ The relation widget allows you to reference items from another collection. It pr - **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields): ```yaml - - label: Post Author - name: author - widget: relation - collection: authors - searchFields: [name, twitterHandle] - valueField: name + - label: "Post Author" + name: "author" + widget: "relation" + collection: "authors" + searchFields: "[name, twitterHandle]" + valueField: "name" ``` The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. \ No newline at end of file diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md index 285a9937f6e6..810c6da925b1 100644 --- a/website/site/content/docs/widgets/select.md +++ b/website/site/content/docs/widgets/select.md @@ -17,6 +17,7 @@ The select widget allows you to pick a single string value from a dropdown menu. - string values: the label displayed in the dropdown is the value saved in the file - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file - Example (options as strings): + ```yaml - label: "Align Content" name: "align" @@ -24,6 +25,7 @@ The select widget allows you to pick a single string value from a dropdown menu. options: ["left", "center", "right"] ``` - Example (options as objects): + ```yaml - label: "City" name: "airport-code" From 68fe38908dfc1fd9996d7f5c53c5ceaf66fc5af1 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Tue, 12 Dec 2017 17:15:21 -0200 Subject: [PATCH 07/12] Merging with widgets.md and app.j --- website/site/content/docs/widgets.md | 311 +----------------- website/site/content/docs/widgets/boolean.md | 8 +- website/site/content/docs/widgets/date.md | 10 +- website/site/content/docs/widgets/datetime.md | 10 +- website/site/content/docs/widgets/file.md | 8 +- website/site/content/docs/widgets/image.md | 8 +- website/site/content/docs/widgets/number.md | 12 +- website/site/content/docs/widgets/object.md | 12 +- website/site/content/docs/widgets/relation.md | 16 +- website/site/content/docs/widgets/select.md | 21 +- website/site/content/docs/widgets/string.md | 12 +- website/site/content/docs/widgets/text.md | 14 +- website/site/layouts/_default/single.html | 2 +- website/site/static/widgets.js | 30 -- website/src/css/imports/widgets.css | 14 +- website/src/js/app.js | 40 ++- 16 files changed, 119 insertions(+), 409 deletions(-) delete mode 100644 website/site/static/widgets.js diff --git a/website/site/content/docs/widgets.md b/website/site/content/docs/widgets.md index 5d1e84588879..3d4ebd7dd455 100644 --- a/website/site/content/docs/widgets.md +++ b/website/site/content/docs/widgets.md @@ -1,10 +1,9 @@ --- title: Widgets position: 30 +description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" --- -# Widgets - Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)! Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both. @@ -27,310 +26,4 @@ The following options are available on all fields: pattern: ['.{10,}', "Must have at least 20 characters"] ``` - -## Boolean - -The boolean widget translates a toggle switch input to a true/false value. - -- **Name:** `boolean` -- **UI:** toggle switch -- **Data type:** boolean -- **Options:** - - `default`: accepts `true` or `false`; defaults to `false` -- **Example:** - - ```yaml - - {label: "Draft", name: "draft", widget: "boolean", default: true} - ``` - - -## Date - -The date widget translates a date picker input to a date string. For saving date and time together, use the [DateTime](#datetime) widget. - -- **Name:** `date` -- **UI:** date picker -- **Data type:** Moment.js-formatted date string -- **Options:** - - `default`: accepts a date string, or an empty string to accept blank input; otherwise defaults to current date - - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DD` -- **Example:** - - ```yaml - - label: "Birthdate" - name: "birthdate" - widget: "date" - default: "" - format: "MMM Do YY" - ``` - - -## DateTime - -The datetime widget translates a datetime picker to a datetime string. For saving the date only, use the [Date](#date) widget. - -- **Name:** `datetime` -- **UI:** datetime picker -- **Data type:** Moment.js-formatted datetime string -- **Options:** - - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime - - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DDTHH:mm:ssZ` -- **Example:** - - ```yaml - - label: "Start time" - name: "start" - widget: "datetime" - default: "" - format: "LLL" - ``` - - -## File - -The file widget allows editors to upload a file or select an existing one from the media library. The path to the file will be saved to the field as a string. - -- **Name:** `file` -- **UI:** file picker button opens media gallery -- **Data type:** file path string, based on `media_folder`/`public_folder` configuration -- **Options:** - - `default`: accepts a file path string; defaults to null -- **Example:** - - ```yaml - - label: "Manual PDF" - **Name:** "manual_pdf" - widget: "file" - default: "/uploads/general-manual.pdf" - ``` - - -## Hidden - -Hidden widgets do not display in the UI. In folder collections that allow users to create new items, you will often want to set a default for hidden fields, so they will be set without requiring an input. - -- **Name:** `hidden` -- **UI:** none -- **Data type:** any valid data type -- **Options:** - - `default`: accepts any valid data type; recommended for collections that allow adding new items -- **Example:** - - ```yaml - - {label: "Layout", name: "layout", widget: "hidden", default: "blog"} - ``` - - -## Image - -The image widget allows editors to upload an image or select an existing one from the media library. The path to the image file will be saved to the field as a string. - -- **Name:** `image` -- **UI:** file picker button opens media gallery allowing image files (jpg, jpeg, webp, gif, png, bmp, tiff, svg) only; displays selected image thumbnail -- **Data type:** file path string, based on `media_folder`/`public_folder` configuration -- **Options:** - - `default`: accepts a file path string; defaults to null -- **Example:** - - ```yaml - - label: "Featured Image" - name: "thumbnail" - widget: "image" - default: "/uploads/chocolate-dogecoin.jpg" - ``` - - -## List - -The list widget allows you to create a repeatable item in the UI which saves as a list of widget values. map a user-provided string with a comma delimiter into a list. You can choose any widget as a child of a list widget—even other lists. - -- **Name:** `list` -- **UI:** if `fields` is specified, field containing a repeatable child widget, with controls for adding, deleting, and re-ordering the repeated widgets; if unspecified, a text input for entering comma-separated values -- **Data type:** list of widget values -- **Options:** - - `default`: if `fields` is specified, declare defaults on the child widgets; if not, you may specify a list of strings to populate the text field - - `field`: a single widget field to be repeated - - `fields`: a nested list of multiple widget fields to be included in each repeatable iteration -- **Example** (`field`/`fields` not specified): - - ```yaml - - label: "Tags" - name: "tags" - widget: "list" - default: ["news"] - ``` - -- **Example** (with `field`): - - ```yaml - - label: "Gallery" - name: "galleryImages" - widget: "list" - field: - - {label: Image, name: image, widget: image} - ``` - -- **Example** (with `fields`): - - ```yaml - - label: "Testimonials" - name: "testimonials" - widget: "list" - fields: - - {label: Quote, name: quote, widget: string, default: "Everything is awesome!"} - - label: Author - name: author - widget: object - fields: - - {label: Name, name: name, widget: string, default: "Emmet"} - - {label: Avatar, name: avatar, widget: image, default: "/img/emmet.jpg"} - ``` - - -## Number - -The number widget uses an HTML number input, saving the value as a string, integer, or floating point number. - -- **Name:** `number` -- **UI:** HTML [number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) -- **Data type:** string by default; configured by `valueType` option -- **Options:** - - `default`: accepts string or number value; defaults to empty string - - `valueType`: accepts `int` or `float`; any other value results in saving as a string - - `min`: accepts a number for minimum value accepted; unset by default - - `max`: accepts a number for maximum value accepted; unset by default -- **Example:** - - ```yaml - - label: "Puppy Count" - name: "puppies" - widget: "number" - default: 2 - valueType: "int" - min: 1 - max: 101 - ``` - - -## Object - -The object widget allows you to group multiple widgets together, nested under a single field. You can choose any widget as a child of an object widget—even other objects. - -- **Name:** `object` -- **UI:** a field containing one or more child widgets -- **Data type:** list of child widget values -- **Options:** - - `default`: you can set defaults within each sub-field's configuration - - `fields`: (**required**) a nested list of widget fields to include in your widget -- **Example:** - - ```yaml - - label: "Profile" - name: "profile" - widget: "object" - fields: - - {label: "Public", name: "public", widget: "boolean", default: true} - - {label: "Name", name: "name", widget: "string"} - - label: "Birthdate" - name: "birthdate" - widget: "date" - default: "" - format: "MM/DD/YYYY" - - label: "Address" - name: "address" - widget: "object" - fields: - - {label: "Street Address", name: "street", widget: "string"} - - {label: "City", name: "city", widget: "string"} - - {label: "Postal Code", name: "post-code", widget: "string"} - ``` - - -## Relation - -The relation widget allows you to reference items from another collection. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. - -- **Name:** `realtion` -- **UI:** text input with search result dropdown -- **Data type:** data type of the value pulled from the related collection item -- **Options:** - - `default`: accepts any widget data type; defaults to an empty string - - `collection`: (**required**) name of the collection being referenced (string) - - `searchFields`: (**required**) list of one or more names of fields in the referenced collection to search for the typed value - - `valueField`: (**required**) name of the field from the referenced collection whose value will be stored for the relation -- **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields): - - ```yaml - - label: Post Author - name: author - widget: relation - collection: authors - searchFields: [name, twitterHandle] - valueField: name - ``` - The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. - - -## Select - -The select widget allows you to pick a single string value from a dropdown menu. - -- **Name:** `select` -- **UI:** HTML select input -- **Data type:** string -- **Options:** - - `default`: accepts a string; defaults to an empty string - - `options`: (**required**) a list of options for the dropdown menu; can be listed in two ways: - - string values: the label displayed in the dropdown is the value saved in the file - - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file -- **Example** (options as strings): - - ```yaml - - label: "Align Content" - name: "align" - widget: "select" - options: ["left", "center", "right"] - ``` -- **Example** (options as objects): - - ```yaml - - label: "City" - name: "airport-code" - widget: "select" - options: - - { label: "Chicago", value: "ORD" } - - { label: "Paris", value: "CDG" } - - { label: "Tokyo", value: "HND" } - ``` - - -## String - -The string widget translates a basic text input to a string value. For larger textarea inputs, use the [text](#text) widget. - -- **Name:** `string` -- **UI:** text input -- **Data type:** string -- **Options:** - - `default`: accepts a string; defaults to an empty string -- **Example:** - - ```yaml - - {label: "Title", name: "title", widget: "string"} - ``` - - -## Text - -The text widget takes a multiline text field and saves it as a string. For shorter text inputs, use the [string](#string) widget. - -- **Name:** `text` -- **UI:** HTML textarea -- **Data type:** string -- **Options:** - - `default`: accepts a string; defaults to an empty string -- **Example:** - - ```yaml - - {label: "Description", name: "description", widget: "text"} - ``` \ No newline at end of file +## Default widgets \ No newline at end of file diff --git a/website/site/content/docs/widgets/boolean.md b/website/site/content/docs/widgets/boolean.md index f45748da3a52..2205b6566100 100644 --- a/website/site/content/docs/widgets/boolean.md +++ b/website/site/content/docs/widgets/boolean.md @@ -8,10 +8,10 @@ type: "widget" The boolean widget translates a toggle switch input to a true/false value. -- Name: `boolean` -- UI: toggle switch -- Data type: boolean -- Options: +- **Name:** `boolean` +- **UI:** toggle switch +- **Data type:** boolean +- **Options:** - `default`: accepts `true` or `false`; defaults to `false` - Example: diff --git a/website/site/content/docs/widgets/date.md b/website/site/content/docs/widgets/date.md index 89450ae37dfb..10c8fa208743 100644 --- a/website/site/content/docs/widgets/date.md +++ b/website/site/content/docs/widgets/date.md @@ -6,12 +6,12 @@ type: "widget" ### Date -The date widget translates a date picker input to a date string. For saving date and time together, use the [DateTime](#datetime) widget. +The date widget translates a date picker input to a date string. For saving date and time together, use the datetime widget. -- Name: `date` -- UI: date picker -- Data type: Moment.js-formatted date string -- Options: +- **Name:** `date` +- **UI:** date picker +- **Data type:** Moment.js-formatted date string +- **Options:** - `default`: accepts a date string, or an empty string to accept blank input; otherwise defaults to current date - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DD` - Example: diff --git a/website/site/content/docs/widgets/datetime.md b/website/site/content/docs/widgets/datetime.md index 34858089732d..ff8d19559837 100644 --- a/website/site/content/docs/widgets/datetime.md +++ b/website/site/content/docs/widgets/datetime.md @@ -6,12 +6,12 @@ type: "widget" ### DateTime -The datetime widget translates a datetime picker to a datetime string. For saving the date only, use the [Date](#date) widget. +The datetime widget translates a datetime picker to a datetime string. For saving the date only, use the date widget. -- Name: `datetime` -- UI: datetime picker -- Data type: Moment.js-formatted datetime string -- Options: +- **Name:** `datetime` +- **UI:** datetime picker +- **Data type:** Moment.js-formatted datetime string +- **Options:** - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DDTHH:mm:ssZ` - Example: diff --git a/website/site/content/docs/widgets/file.md b/website/site/content/docs/widgets/file.md index 31c870f878d6..47de1ca8b575 100644 --- a/website/site/content/docs/widgets/file.md +++ b/website/site/content/docs/widgets/file.md @@ -8,10 +8,10 @@ type: "widget" The file widget allows editors to upload a file or select an existing one from the media library. The path to the file will be saved to the field as a string. -- Name: `file` -- UI: file picker button opens media gallery -- Data type: file path string, based on `media_folder`/`public_folder` configuration -- Options: +- **Name:** `file` +- **UI:** file picker button opens media gallery +- **Data type:** file path string, based on `media_folder`/`public_folder` configuration +- **Options:** - `default`: accepts a file path string; defaults to null - Example: diff --git a/website/site/content/docs/widgets/image.md b/website/site/content/docs/widgets/image.md index 4159dde751d9..e953315518c4 100644 --- a/website/site/content/docs/widgets/image.md +++ b/website/site/content/docs/widgets/image.md @@ -8,10 +8,10 @@ type: "widget" The image widget allows editors to upload an image or select an existing one from the media library. The path to the image file will be saved to the field as a string. -- Name: `image` -- UI: file picker button opens media gallery allowing image files (jpg, jpeg, webp, gif, png, bmp, tiff, svg) only; displays selected image thumbnail -- Data type: file path string, based on `media_folder`/`public_folder` configuration -- Options: +- **Name:** `image` +- **UI:** file picker button opens media gallery allowing image files (jpg, jpeg, webp, gif, png, bmp, tiff, svg) only; displays selected image thumbnail +- **Data type:** file path string, based on `media_folder`/`public_folder` configuration +- **Options:** - `default`: accepts a file path string; defaults to null - Example: diff --git a/website/site/content/docs/widgets/number.md b/website/site/content/docs/widgets/number.md index c89e598a7f4b..956cf186ce98 100644 --- a/website/site/content/docs/widgets/number.md +++ b/website/site/content/docs/widgets/number.md @@ -6,17 +6,18 @@ type: "widget" ### Number + The number widget uses an HTML number input, saving the value as a string, integer, or floating point number. -- Name: `number` -- UI: HTML [number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) -- Data type: string by default; configured by `valueType` option -- Options: +- **Name:** `number` +- **UI:** HTML [number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) +- **Data type:** string by default; configured by `valueType` option +- **Options:** - `default`: accepts string or number value; defaults to empty string - `valueType`: accepts `int` or `float`; any other value results in saving as a string - `min`: accepts a number for minimum value accepted; unset by default - `max`: accepts a number for maximum value accepted; unset by default -- Example: +- **Example:** ```yaml - label: "Puppy Count" @@ -26,4 +27,5 @@ The number widget uses an HTML number input, saving the value as a string, integ valueType: "int" min: 1 max: 101 + ``` ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/object.md b/website/site/content/docs/widgets/object.md index d68eaf793db1..83a1dcb3f967 100644 --- a/website/site/content/docs/widgets/object.md +++ b/website/site/content/docs/widgets/object.md @@ -8,13 +8,13 @@ type: "widget" The object widget allows you to group multiple widgets together, nested under a single field. You can choose any widget as a child of an object widget—even other objects. -- Name: `object` -- UI: a field containing other fields -- Data type: immutable map containing the sub-field values -- Options: +- **Name:** `object` +- **UI:** a field containing one or more child widgets +- **Data type:** list of child widget values +- **Options:** - `default`: you can set defaults within each sub-field's configuration - - `fields`: (**required**) a nested list of fields to include in your widget -- Example: + - `fields`: (**required**) a nested list of widget fields to include in your widget +- **Example:** ```yaml - label: "Profile" diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md index 54cae2cb8262..dec33d22b8c4 100644 --- a/website/site/content/docs/widgets/relation.md +++ b/website/site/content/docs/widgets/relation.md @@ -8,7 +8,7 @@ type: "widget" The relation widget allows you to reference items from another collection. It provides a search input with a list of entries from the collection you're referencing, and the list automatically updates with matched entries based on what you've typed. -- **Name:** `realtion` +- **Name:** `relation` - **UI:** text input with search result dropdown - **Data type:** data type of the value pulled from the related collection item - **Options:** @@ -19,11 +19,11 @@ The relation widget allows you to reference items from another collection. It pr - **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields): ```yaml - - label: "Post Author" - name: "author" - widget: "relation" - collection: "authors" - searchFields: "[name, twitterHandle]" - valueField: "name" + - label: Post Author + name: author + widget: relation + collection: authors + searchFields: [name, twitterHandle] + valueField: name ``` - The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. \ No newline at end of file + The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. diff --git a/website/site/content/docs/widgets/select.md b/website/site/content/docs/widgets/select.md index 810c6da925b1..d5e7fda657f2 100644 --- a/website/site/content/docs/widgets/select.md +++ b/website/site/content/docs/widgets/select.md @@ -8,15 +8,15 @@ type: "widget" The select widget allows you to pick a single string value from a dropdown menu. -- Name: `select` -- UI: HTML select input -- Data type: string -- Options: +- **Name:** `select` +- **UI:** HTML select input +- **Data type:** string +- **Options:** - `default`: accepts a string; defaults to an empty string - - `options`: (**required**) an array or list of options for the dropdown menu; can be listed in two ways: - - string values: the label displayed in the dropdown is the value saved in the file - - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file -- Example (options as strings): + - `options`: (**required**) a list of options for the dropdown menu; can be listed in two ways: + - string values: the label displayed in the dropdown is the value saved in the file + - object with `label` and `value` fields: the label displays in the dropdown; the value is saved in the file +- **Example** (options as strings): ```yaml - label: "Align Content" @@ -24,7 +24,7 @@ The select widget allows you to pick a single string value from a dropdown menu. widget: "select" options: ["left", "center", "right"] ``` -- Example (options as objects): +- **Example** (options as objects): ```yaml - label: "City" @@ -34,4 +34,5 @@ The select widget allows you to pick a single string value from a dropdown menu. - { label: "Chicago", value: "ORD" } - { label: "Paris", value: "CDG" } - { label: "Tokyo", value: "HND" } - ``` \ No newline at end of file + ``` + diff --git a/website/site/content/docs/widgets/string.md b/website/site/content/docs/widgets/string.md index c4788e035f09..8d62c7edaae0 100644 --- a/website/site/content/docs/widgets/string.md +++ b/website/site/content/docs/widgets/string.md @@ -6,14 +6,14 @@ type: "widget" ### String -The string widget translates a basic text input to a string value. For larger textarea inputs, use the [text](#text) widget. +The string widget translates a basic text input to a string value. For larger textarea inputs, use the text widget. -- Name: `string` -- UI: text input -- Data type: string -- Options: +- **Name:** `string` +- **UI:** text input +- **Data type:** string +- **Options:** - `default`: accepts a string; defaults to an empty string -- Example: +- **Example:** ```yaml - {label: "Title", name: "title", widget: "string"} diff --git a/website/site/content/docs/widgets/text.md b/website/site/content/docs/widgets/text.md index 6e6141548a9c..476bc2a5af5a 100644 --- a/website/site/content/docs/widgets/text.md +++ b/website/site/content/docs/widgets/text.md @@ -6,15 +6,15 @@ type: "widget" ### Text -The text widget takes a multiline text field and saves it as a string. For shorter text inputs, use the [string](#string) widget. +The text widget takes a multiline text field and saves it as a string. For shorter text inputs, use the string widget. -- Name: `text` -- UI: HTML textarea -- Data type: string -- Options: +- **Name:** `text` +- **UI:** HTML textarea +- **Data type:** string +- **Options:** - `default`: accepts a string; defaults to an empty string -- Example: +- **Example:** ```yaml - {label: "Description", name: "description", widget: "text"} - ``` + diff --git a/website/site/layouts/_default/single.html b/website/site/layouts/_default/single.html index 5927be15ba92..6452ab92e921 100644 --- a/website/site/layouts/_default/single.html +++ b/website/site/layouts/_default/single.html @@ -25,7 +25,7 @@
- {{- if eq .Title "Widgets V2" -}} + {{- if eq .Title "Widgets" -}} {{ partial "edit-link" . }}

Widgets

{{ .Content }} diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js deleted file mode 100644 index 4e35b48d915f..000000000000 --- a/website/site/static/widgets.js +++ /dev/null @@ -1,30 +0,0 @@ -const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud -widgets = document.getElementsByClassName("widget"), // Widgets' bodies -widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background - -let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; - -for(let i = 0; i < widgetItems.length; i++) { - widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud - const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render - openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget - - targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget - widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections - - openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget - openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes - - activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud - activeWidgetItem = e.target; // Sets the new active widget item as the clicked one - activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it - - - setTimeout(() => { - targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition - targetWidget.classList.add("widget_open"); // Defines the new target widget - openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget - - },150) // When the transition is done, finish the process by attributing the final classes to each widget - }) -} \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index 43e26d5f8359..5015ac62db28 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -67,10 +67,6 @@ animation: widgetOpacity .15s .05s ease forwards; } -.widget#list { - padding-bottom: 3em; /* For some weird reason the list widget was overflowing the background, so this dirty fix works */ -} - @keyframes widgetOpacity { from { opacity: 0 @@ -86,4 +82,14 @@ .widget h3 { margin-top: 0 !important; +} + +#list { + padding-bottom: 3rem +} + +@media screen and (max-width: $tablet) { + #list, #relation, #object, #text, #string { + padding-bottom: 3rem; + } } \ No newline at end of file diff --git a/website/src/js/app.js b/website/src/js/app.js index 163695fbafeb..52900f15111e 100755 --- a/website/src/js/app.js +++ b/website/src/js/app.js @@ -121,4 +121,42 @@ var eventInfoLoad = function() { } } -eventInfoLoad(); \ No newline at end of file +eventInfoLoad(); + +// Widgets section +function widgetsCloud() { + if ($('.widgets')) { + const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud + widgets = document.getElementsByClassName("widget"), // Widgets' bodies + widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background + + let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; + + for (let i = 0; i < widgetItems.length; i++) { + widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud + const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render + openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget + + targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections + + openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget + openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + + activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud + activeWidgetItem = e.target; // Sets the new active widget item as the clicked one + activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it + + + setTimeout(() => { + targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition + targetWidget.classList.add("widget_open"); // Defines the new target widget + openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + + }, 150) // When the transition is done, finish the process by attributing the final classes to each widget + }) + } + } +} + +widgetsCloud(); \ No newline at end of file From 2457350baf03af8f23ef2a6d601e1f0d9d12e6b0 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Tue, 12 Dec 2017 17:19:36 -0200 Subject: [PATCH 08/12] Fixing some silly mistakes (sorry!) --- website/site/content/docs/widgets.md | 1 - website/site/content/docs/widgets/number.md | 1 - website/site/content/docs/widgets/relation.md | 12 +++---- website/site/content/docs/widgets/text.md | 1 + website/site/content/docs/widgetsV2.md | 31 ------------------- website/site/layouts/partials/footer.html | 3 -- 6 files changed, 7 insertions(+), 42 deletions(-) delete mode 100644 website/site/content/docs/widgetsV2.md diff --git a/website/site/content/docs/widgets.md b/website/site/content/docs/widgets.md index 3d4ebd7dd455..cda7fbe4bfc4 100644 --- a/website/site/content/docs/widgets.md +++ b/website/site/content/docs/widgets.md @@ -1,7 +1,6 @@ --- title: Widgets position: 30 -description: "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets, including:" --- Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)! diff --git a/website/site/content/docs/widgets/number.md b/website/site/content/docs/widgets/number.md index 956cf186ce98..027705e5082b 100644 --- a/website/site/content/docs/widgets/number.md +++ b/website/site/content/docs/widgets/number.md @@ -27,5 +27,4 @@ The number widget uses an HTML number input, saving the value as a string, integ valueType: "int" min: 1 max: 101 - ``` ``` \ No newline at end of file diff --git a/website/site/content/docs/widgets/relation.md b/website/site/content/docs/widgets/relation.md index dec33d22b8c4..c8b363fdba5c 100644 --- a/website/site/content/docs/widgets/relation.md +++ b/website/site/content/docs/widgets/relation.md @@ -19,11 +19,11 @@ The relation widget allows you to reference items from another collection. It pr - **Example** (assuming a separate "authors" collection with "name" and "twitterHandle" fields): ```yaml - - label: Post Author - name: author - widget: relation - collection: authors - searchFields: [name, twitterHandle] - valueField: name + - label: "Post Author" + name: "author" + widget: "relation" + collection: "authors" + searchFields: "[name, twitterHandle]" + valueField: "name" ``` The generated UI input will search the authors collection by name and twitterHandle as the user types. On selection, the author name will be saved for the field. diff --git a/website/site/content/docs/widgets/text.md b/website/site/content/docs/widgets/text.md index 476bc2a5af5a..2898c897b09c 100644 --- a/website/site/content/docs/widgets/text.md +++ b/website/site/content/docs/widgets/text.md @@ -17,4 +17,5 @@ The text widget takes a multiline text field and saves it as a string. For short ```yaml - {label: "Description", name: "description", widget: "text"} + ``` diff --git a/website/site/content/docs/widgetsV2.md b/website/site/content/docs/widgetsV2.md deleted file mode 100644 index 24562cb96cb0..000000000000 --- a/website/site/content/docs/widgetsV2.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Widgets V2 -position: 31 -paragraphs: - - "Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)!" - - "Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both." - - "To see working examples of all of the built-in widgets, try making a 'Kitchen Sink' collection item on the [CMS demo site](https://cms-demo.netlify.com). (No login required: click the login button and the CMS will open.) You can refer to the demo [configuration code](https://github.com/netlify/netlify-cms/blob/master/example/config.yml#L60) to see how each field was configured." ---- - -Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)! - -Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both. - -To see working examples of all of the built-in widgets, try making a 'Kitchen Sink' collection item on the [CMS demo site](https://cms-demo.netlify.com). (No login required: click the login button and the CMS will open.) You can refer to the demo [configuration code](https://github.com/netlify/netlify-cms/blob/master/example/config.yml#L60) to see how each field was configured. - -## Common widget options - -The following options are available on all fields: - -- `required`: specify as `false` to make a field optional; defaults to `true` -- `pattern`: add field validation by specifying a list with a regex pattern and an error message; more extensive validation can be achieved with [custom widgets](https://www.netlifycms.org/docs/custom-widgets/#advanced-field-validation) - - **Example:** - - ```yaml - - label: "Title" - name: "title" - widget: "string" - pattern: ['.{10,}', "Must have at least 20 characters"] - ``` - -## Check out all of the widgets \ No newline at end of file diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index 5ccee5543526..bdd3b4fcf8dd 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,8 +21,5 @@ debug: false // Set debug to true if you want to inspect the dropdown }); -{{- if eq .Title "Widgets V2" -}} - -{{- end -}} From 42317317e99a94cc9f4c9538172ecf1e09a26a91 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Thu, 14 Dec 2017 09:33:11 -0200 Subject: [PATCH 09/12] Following @verythorough contributions :) --- website/site/content/docs/widgets.md | 2 + website/site/content/docs/widgets/boolean.md | 2 +- website/site/content/docs/widgets/date.md | 2 +- website/site/content/docs/widgets/datetime.md | 2 +- website/site/content/docs/widgets/file.md | 2 +- website/site/content/docs/widgets/image.md | 2 +- website/site/layouts/_default/single.html | 8 +--- website/site/layouts/partials/footer.html | 3 ++ website/site/static/widgets.js | 37 ++++++++++++++++++ website/src/js/app.js | 38 ------------------- 10 files changed, 49 insertions(+), 49 deletions(-) create mode 100644 website/site/static/widgets.js diff --git a/website/site/content/docs/widgets.md b/website/site/content/docs/widgets.md index cda7fbe4bfc4..272de49b8ba6 100644 --- a/website/site/content/docs/widgets.md +++ b/website/site/content/docs/widgets.md @@ -3,6 +3,8 @@ title: Widgets position: 30 --- +# Widgets + Widgets define the data type and interface for entry fields. Netlify CMS comes with several built-in widgets. Click the widget names in the sidebar to jump to specific widget details. We’re always adding new widgets, and you can also [create your own](https://www.netlifycms.org/docs/custom-widgets)! Widgets are specified as collection fields in the `config.yml` file. Note that [YAML syntax](https://en.wikipedia.org/wiki/YAML#Basic_components) allows lists and objects to be written in block or inline style, and the code samples below include a mix of both. diff --git a/website/site/content/docs/widgets/boolean.md b/website/site/content/docs/widgets/boolean.md index 2205b6566100..7105a9bb2571 100644 --- a/website/site/content/docs/widgets/boolean.md +++ b/website/site/content/docs/widgets/boolean.md @@ -13,7 +13,7 @@ The boolean widget translates a toggle switch input to a true/false value. - **Data type:** boolean - **Options:** - `default`: accepts `true` or `false`; defaults to `false` -- Example: +- **Example:** ```yaml - {label: "Draft", name: "draft", widget: "boolean", default: true} diff --git a/website/site/content/docs/widgets/date.md b/website/site/content/docs/widgets/date.md index 10c8fa208743..05f2e65961df 100644 --- a/website/site/content/docs/widgets/date.md +++ b/website/site/content/docs/widgets/date.md @@ -14,7 +14,7 @@ The date widget translates a date picker input to a date string. For saving date - **Options:** - `default`: accepts a date string, or an empty string to accept blank input; otherwise defaults to current date - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DD` -- Example: +- **Example:** ```yaml - label: "Birthdate" diff --git a/website/site/content/docs/widgets/datetime.md b/website/site/content/docs/widgets/datetime.md index ff8d19559837..b6e4d91c9bc2 100644 --- a/website/site/content/docs/widgets/datetime.md +++ b/website/site/content/docs/widgets/datetime.md @@ -14,7 +14,7 @@ The datetime widget translates a datetime picker to a datetime string. For savin - **Options:** - `default`: accepts a datetime string, or an empty string to accept blank input; otherwise defaults to current datetime - `format`: accepts Moment.js [tokens](https://momentjs.com/docs/#/parsing/string-format/); defaults to ISO8601 format `YYYY-MM-DDTHH:mm:ssZ` -- Example: +- **Example:** ```yaml - label: "Start time" diff --git a/website/site/content/docs/widgets/file.md b/website/site/content/docs/widgets/file.md index 47de1ca8b575..a332a1b454e2 100644 --- a/website/site/content/docs/widgets/file.md +++ b/website/site/content/docs/widgets/file.md @@ -13,7 +13,7 @@ The file widget allows editors to upload a file or select an existing one from t - **Data type:** file path string, based on `media_folder`/`public_folder` configuration - **Options:** - `default`: accepts a file path string; defaults to null -- Example: +- **Example:** ```yaml - label: "Manual PDF" diff --git a/website/site/content/docs/widgets/image.md b/website/site/content/docs/widgets/image.md index e953315518c4..afaed0cda1fd 100644 --- a/website/site/content/docs/widgets/image.md +++ b/website/site/content/docs/widgets/image.md @@ -13,7 +13,7 @@ The image widget allows editors to upload an image or select an existing one fro - **Data type:** file path string, based on `media_folder`/`public_folder` configuration - **Options:** - `default`: accepts a file path string; defaults to null -- Example: +- **Example:** ```yaml - label: "Featured Image" diff --git a/website/site/layouts/_default/single.html b/website/site/layouts/_default/single.html index 6452ab92e921..9d7fc970c78a 100644 --- a/website/site/layouts/_default/single.html +++ b/website/site/layouts/_default/single.html @@ -25,14 +25,10 @@
- {{- if eq .Title "Widgets" -}} - {{ partial "edit-link" . }} -

Widgets

- {{ .Content }} - {{- partial "widgets" . -}} - {{- else -}} {{ partial "edit-link" . }} {{ .Content }} + {{- if eq .Title "Widgets" -}} + {{- partial "widgets" . -}} {{- end -}}
diff --git a/website/site/layouts/partials/footer.html b/website/site/layouts/partials/footer.html index bdd3b4fcf8dd..09af0b720aed 100755 --- a/website/site/layouts/partials/footer.html +++ b/website/site/layouts/partials/footer.html @@ -21,5 +21,8 @@ debug: false // Set debug to true if you want to inspect the dropdown }); +{{- if eq .Title "Widgets" -}} + +{{- end -}} diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js new file mode 100644 index 000000000000..3db89e058fb1 --- /dev/null +++ b/website/site/static/widgets.js @@ -0,0 +1,37 @@ +// Widgets section +function widgetsCloud() { + if ($('.widgets')) { + const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud + widgets = document.getElementsByClassName("widget"), // Widgets' bodies + widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background + + let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; + + for (let i = 0; i < widgetItems.length; i++) { + widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud + const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render + openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget + + targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections + + openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget + openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + + activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud + activeWidgetItem = e.target; // Sets the new active widget item as the clicked one + activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it + + + setTimeout(() => { + targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition + targetWidget.classList.add("widget_open"); // Defines the new target widget + openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + + }, 150) // When the transition is done, finish the process by attributing the final classes to each widget + }) + } + } +} + +widgetsCloud(); \ No newline at end of file diff --git a/website/src/js/app.js b/website/src/js/app.js index 52900f15111e..77e979e0e569 100755 --- a/website/src/js/app.js +++ b/website/src/js/app.js @@ -122,41 +122,3 @@ var eventInfoLoad = function() { } eventInfoLoad(); - -// Widgets section -function widgetsCloud() { - if ($('.widgets')) { - const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud - widgets = document.getElementsByClassName("widget"), // Widgets' bodies - widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background - - let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; - - for (let i = 0; i < widgetItems.length; i++) { - widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud - const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render - openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget - - targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget - widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections - - openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget - openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes - - activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud - activeWidgetItem = e.target; // Sets the new active widget item as the clicked one - activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it - - - setTimeout(() => { - targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition - targetWidget.classList.add("widget_open"); // Defines the new target widget - openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget - - }, 150) // When the transition is done, finish the process by attributing the final classes to each widget - }) - } - } -} - -widgetsCloud(); \ No newline at end of file From f627f35dcee2c56fdaf501e2c64f86aaf57d0f98 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Thu, 14 Dec 2017 15:08:27 -0200 Subject: [PATCH 10/12] Adding the markdown widget and fixing the widgets container background --- website/site/content/docs/widgets/markdown.md | 27 ++++++++++++++++++ website/site/layouts/partials/widgets.html | 1 - website/site/static/img/widgets-markdown.PNG | Bin 0 -> 18501 bytes website/site/static/widgets.js | 4 +-- website/src/css/imports/widgets.css | 20 ------------- 5 files changed, 28 insertions(+), 24 deletions(-) create mode 100644 website/site/content/docs/widgets/markdown.md create mode 100644 website/site/static/img/widgets-markdown.PNG diff --git a/website/site/content/docs/widgets/markdown.md b/website/site/content/docs/widgets/markdown.md new file mode 100644 index 000000000000..58034cb13f65 --- /dev/null +++ b/website/site/content/docs/widgets/markdown.md @@ -0,0 +1,27 @@ +--- +label: "Markdown" +target: "markdown" +type: "widget" +--- + +### Markdown + +The markdown widget provides a full fledged text editor - which is based on [slate](https://github.com/ianstormtaylor/slate) - that allows users to format text with features such as headings and blockquotes. Users are also allowed to write in markdown by simply flipping a switch. + +*Please note:* in case you want to use your markdown editor to fill a markdown's file content after the frontmatter, you'll have name the field as `body` so then the CMS can recognize it and save the file accordingly. + +- **Name:** `markdown` +- **UI:** full text editor +- **Data type:** markdown +- **Options:** + - `default`: accepts markdown content +- **Example:** + + ```yaml + - {label: "Blog post content", name: "body", widget: "markdown"} + ``` + +This would render as: + +![Markdown widget example](/img/widgets-markdown.png) + diff --git a/website/site/layouts/partials/widgets.html b/website/site/layouts/partials/widgets.html index 154b90cd2f96..6327195bac7f 100644 --- a/website/site/layouts/partials/widgets.html +++ b/website/site/layouts/partials/widgets.html @@ -5,7 +5,6 @@ {{- end -}}
- {{- range $index, $widget := where .Site.RegularPages "Type" "eq" "widget" -}}
{{.Content}} diff --git a/website/site/static/img/widgets-markdown.PNG b/website/site/static/img/widgets-markdown.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a42726c12664762b9e848509ee494381434a595e GIT binary patch literal 18501 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 ZCX+nRk~vA4>&GwA(>B(s)_m~dzX51ZuIc~) literal 0 HcmV?d00001 diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js index 3db89e058fb1..cde7e8ee88b6 100644 --- a/website/site/static/widgets.js +++ b/website/site/static/widgets.js @@ -2,8 +2,7 @@ function widgetsCloud() { if ($('.widgets')) { const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud - widgets = document.getElementsByClassName("widget"), // Widgets' bodies - widgetBackground = document.getElementsByClassName("widgets__background")[0]; // Widget container flexible height background + widgets = document.getElementsByClassName("widget"); // Widgets' bodies let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; @@ -13,7 +12,6 @@ function widgetsCloud() { openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget - widgetBackground.style.height = targetWidget.offsetHeight + "px"; // Changes the widgets container background's height in order for a smoother transition between sections openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index 5015ac62db28..e903cb1d4f7e 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -29,18 +29,8 @@ .widgets__container { margin: 1em 0; - position: relative; -} - -.widgets__background { - position: absolute; - left: 0; - top: 0; background: $lightGrey; border-radius: $borderRadius; - z-index: -1; - width: 100%; - height: 100%; transition: height .15s ease; } @@ -82,14 +72,4 @@ .widget h3 { margin-top: 0 !important; -} - -#list { - padding-bottom: 3rem -} - -@media screen and (max-width: $tablet) { - #list, #relation, #object, #text, #string { - padding-bottom: 3rem; - } } \ No newline at end of file From ca05ae406e543c215a915aff6e8f85107a276176 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Mon, 18 Dec 2017 11:56:21 -0200 Subject: [PATCH 11/12] Adding the URL functionality and myself as a contributor :) --- .all-contributorsrc | 9 ++++ README.md | 18 +++---- website/site/content/docs/widgets.md | 2 +- website/site/static/widgets.js | 75 ++++++++++++++++++++-------- website/src/css/imports/widgets.css | 12 ++--- 5 files changed, 76 insertions(+), 40 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0177e1ed55d4..5b9f67277773 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -429,6 +429,15 @@ "code", "plugin" ] + }, + { + "login": "hcavalieri", + "name": "Henrique Cavalieri", + "avatar_url": "https://avatars0.githubusercontent.com/u/27744332?v=4", + "profile": "https://kaordica.com.br", + "contributions": [ + "doc" + ] } ] } diff --git a/README.md b/README.md index 024b5dfc21d0..814d6f83b4ec 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Netlify CMS -[![All Contributors](https://img.shields.io/badge/all_contributors-53-orange.svg)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-54-orange.svg?style=flat-square)](#contributors) [![](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/netlify/netlifycms) A CMS for static site generators. Give non-technical users a simple way to edit @@ -48,15 +48,15 @@ Please make sure you understand its [implications and guarantees](https://writin Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)): -| [
Cássio Souza](https://twitter.com/cassiozen)
[💻](https://github.com/netlify/netlify-cms/commits?author=cassiozen "Code") | [
Shawn Erquhart](https://erquh.art)
[💻](https://github.com/netlify/netlify-cms/commits?author=erquhart "Code") | [
Andrey Okonetchnikov](http://okonet.ru)
[💻](https://github.com/netlify/netlify-cms/commits?author=okonet "Code") | [
Mathias Biilmann](https://www.netlify.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=biilmann "Code") | [
Benaiah Mischenko](http://benaiah.me)
[💻](https://github.com/netlify/netlify-cms/commits?author=Benaiah "Code") | [
Rafael Conde](http://rafaelconde.net)
[🎨](#design-rafaelconde "Design") | [
Joseph Earl](http://josephearl.co.uk)
[💻](https://github.com/netlify/netlify-cms/commits?author=josephearl "Code") | +| [
Cássio Souza](https://twitter.com/cassiozen)
[💻](https://github.com/netlify/netlify-cms/commits?author=cassiozen "Code") | [
Shawn Erquhart](https://erquh.art)
[💻](https://github.com/netlify/netlify-cms/commits?author=erquhart "Code") | [
Andrey Okonetchnikov](http://okonet.ru)
[💻](https://github.com/netlify/netlify-cms/commits?author=okonet "Code") | [
Mathias Biilmann](https://www.netlify.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=biilmann "Code") | [
Benaiah Mischenko](http://benaiah.me)
[💻](https://github.com/netlify/netlify-cms/commits?author=Benaiah "Code") | [
Rafael Conde](http://rafaelconde.net)
[🎨](#design-rafaelconde "Design") | [
Joseph Earl](http://josephearl.co.uk)
[💻](https://github.com/netlify/netlify-cms/commits?author=josephearl "Code") | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| [
Brian Douglas](https://briandouglas.me/)
[💻](https://github.com/netlify/netlify-cms/commits?author=bdougie "Code") | [
Frances Berriman](https://fberriman.com)
[🎨](#design-phae "Design") | [
David Calavera](https://github.com/calavera)
[💻](https://github.com/netlify/netlify-cms/commits?author=calavera "Code") | [
Luis Correia](https://luisc.pt)
[💻](https://github.com/netlify/netlify-cms/commits?author=lmcorreia "Code") | [
Caleb](https://github.com/tech4him1)
[💻](https://github.com/netlify/netlify-cms/commits?author=tech4him1 "Code") | [
Jerry Holmes](http://www.pagedragon.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=jholmes033169 "Code") | [
abumalick](https://github.com/abumalick)
[💻](https://github.com/netlify/netlify-cms/commits?author=abumalick "Code") | -| [
Eamonn Bell](http://www.eamonnbell.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=eamonnbell "Code") | [
Jessica Parsons](https://github.com/verythorough)
[📖](https://github.com/netlify/netlify-cms/commits?author=verythorough "Documentation") | [
Kyle Mathews](https://www.bricolage.io)
[💻](https://github.com/netlify/netlify-cms/commits?author=KyleAMathews "Code") | [
americool](https://github.com/americool)
[💻](https://github.com/netlify/netlify-cms/commits?author=americool "Code") | [
Damien Duhamel](http://www.damienduhamel.fr)
| [
Julian Krispel-Samsel](http://reactrocket.com)
| [
Kevin McCormack](http://harlemsquirrel.github.io/)
| -| [
Kalin Chernev](https://github.com/kalinchernev)
| [
tortilaman](https://github.com/tortilaman)
| [
Václav Klecanda](http://www.vxk.cz)
| [
DrianHillman](http://drianhillman.me)
| [
Sean Crawford](https://github.com/seantcoyote)
| [
Robert Riemann](http://blog.riemann.cc)
| [
Ben Berman](http://jygabyte.com)
| -| [
Benjamin Kniffler](https://github.com/bkniffler)
| [
Mike Wickett](http://www.wickett.ca)
| [
Rory Claasen](http://roryclaasen.me)
| [
Frederic Brodbeck](http://www.freder.io/)
| [
Stuart Dum](https://github.com/simplystuart)
| [
Ryan Watters](https://github.com/rdwatters)
| [
Helder S Ribeiro](https://twitter.com/hsribei)
| -| [
Artem Govorov](http://dm.gl)
| [
Cédric Delpoux](http://xuopled.netlify.com/)
| [
imorente](https://github.com/imorente)
| [
David Francoeur](http://davidfrancoeur.com)
| [
Rusta](https://github.com/Rusta)
| [
Henrik Lau Eriksson](http://henrik.laueriksson.com)
| [
Kraig Walker](https://www.kraigwalker.com)
| -| [
Rich Cook](http://www.TalesofMurder.com)
| [
Damien Van Der Windt](https://github.com/damienvdw)
| [
Matt Jared](http://mattjared.github.io/)
| [
bruce-one](https://github.com/bruce-one)
| [
Frank Taillandier](https://frank.taillandier.me)
[📖](https://github.com/netlify/netlify-cms/commits?author=DirtyF "Documentation") | [
Aquib Master](http://aquibm.com/)
[💻](https://github.com/netlify/netlify-cms/commits?author=aquibm "Code") | [
Eric Jinks](http://ericjinks.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=Jinksi "Code") | -| [
Tony Alves](https://github.com/talves)
[💻](https://github.com/netlify/netlify-cms/commits?author=talves "Code") | [
Ernie Bello](http://ern.me)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aebello "Bug reports") | [
Alexander Kushi-Willis](https://ackushiw.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=ackushiw "Documentation") | [
Igor Kuznetsov](http://www.igk.ru)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aigk1972 "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=igk1972 "Code") [🔌](#plugin-igk1972 "Plugin/utility libraries") | +| [
Brian Douglas](https://briandouglas.me/)
[💻](https://github.com/netlify/netlify-cms/commits?author=bdougie "Code") | [
Frances Berriman](https://fberriman.com)
[🎨](#design-phae "Design") | [
David Calavera](https://github.com/calavera)
[💻](https://github.com/netlify/netlify-cms/commits?author=calavera "Code") | [
Luis Correia](https://luisc.pt)
[💻](https://github.com/netlify/netlify-cms/commits?author=lmcorreia "Code") | [
Caleb](https://github.com/tech4him1)
[💻](https://github.com/netlify/netlify-cms/commits?author=tech4him1 "Code") | [
Jerry Holmes](http://www.pagedragon.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=jholmes033169 "Code") | [
abumalick](https://github.com/abumalick)
[💻](https://github.com/netlify/netlify-cms/commits?author=abumalick "Code") | +| [
Eamonn Bell](http://www.eamonnbell.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=eamonnbell "Code") | [
Jessica Parsons](https://github.com/verythorough)
[📖](https://github.com/netlify/netlify-cms/commits?author=verythorough "Documentation") | [
Kyle Mathews](https://www.bricolage.io)
[💻](https://github.com/netlify/netlify-cms/commits?author=KyleAMathews "Code") | [
americool](https://github.com/americool)
[💻](https://github.com/netlify/netlify-cms/commits?author=americool "Code") | [
Damien Duhamel](http://www.damienduhamel.fr)
| [
Julian Krispel-Samsel](http://reactrocket.com)
| [
Kevin McCormack](http://harlemsquirrel.github.io/)
| +| [
Kalin Chernev](https://github.com/kalinchernev)
| [
tortilaman](https://github.com/tortilaman)
| [
Václav Klecanda](http://www.vxk.cz)
| [
DrianHillman](http://drianhillman.me)
| [
Sean Crawford](https://github.com/seantcoyote)
| [
Robert Riemann](http://blog.riemann.cc)
| [
Ben Berman](http://jygabyte.com)
| +| [
Benjamin Kniffler](https://github.com/bkniffler)
| [
Mike Wickett](http://www.wickett.ca)
| [
Rory Claasen](http://roryclaasen.me)
| [
Frederic Brodbeck](http://www.freder.io/)
| [
Stuart Dum](https://github.com/simplystuart)
| [
Ryan Watters](https://github.com/rdwatters)
| [
Helder S Ribeiro](https://twitter.com/hsribei)
| +| [
Artem Govorov](http://dm.gl)
| [
Cédric Delpoux](http://xuopled.netlify.com/)
| [
imorente](https://github.com/imorente)
| [
David Francoeur](http://davidfrancoeur.com)
| [
Rusta](https://github.com/Rusta)
| [
Henrik Lau Eriksson](http://henrik.laueriksson.com)
| [
Kraig Walker](https://www.kraigwalker.com)
| +| [
Rich Cook](http://www.TalesofMurder.com)
| [
Damien Van Der Windt](https://github.com/damienvdw)
| [
Matt Jared](http://mattjared.github.io/)
| [
bruce-one](https://github.com/bruce-one)
| [
Frank Taillandier](https://frank.taillandier.me)
[📖](https://github.com/netlify/netlify-cms/commits?author=DirtyF "Documentation") | [
Aquib Master](http://aquibm.com/)
[💻](https://github.com/netlify/netlify-cms/commits?author=aquibm "Code") | [
Eric Jinks](http://ericjinks.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=Jinksi "Code") | +| [
Tony Alves](https://github.com/talves)
[💻](https://github.com/netlify/netlify-cms/commits?author=talves "Code") | [
Ernie Bello](http://ern.me)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aebello "Bug reports") | [
Alexander Kushi-Willis](https://ackushiw.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=ackushiw "Documentation") | [
Igor Kuznetsov](http://www.igk.ru)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aigk1972 "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=igk1972 "Code") [🔌](#plugin-igk1972 "Plugin/utility libraries") | [
Henrique Cavalieri](https://kaordica.com.br)
[📖](https://github.com/netlify/netlify-cms/commits?author=hcavalieri "Documentation") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! diff --git a/website/site/content/docs/widgets.md b/website/site/content/docs/widgets.md index 272de49b8ba6..37ae9c817986 100644 --- a/website/site/content/docs/widgets.md +++ b/website/site/content/docs/widgets.md @@ -17,7 +17,7 @@ To see working examples of all of the built-in widgets, try making a 'Kitchen Si The following options are available on all fields: - `required`: specify as `false` to make a field optional; defaults to `true` -- `pattern`: add field validation by specifying a list with a regex pattern and an error message; more extensive validation can be achieved with [custom widgets](https://www.netlifycms.org/docs/custom-widgets/#advanced-field-validation) +- `pattern`: add field validation by specifying a list with a [regex pattern](https://regexr.com/) and an error message; more extensive validation can be achieved with [custom widgets](https://www.netlifycms.org/docs/custom-widgets/#advanced-field-validation) - **Example:** ```yaml diff --git a/website/site/static/widgets.js b/website/site/static/widgets.js index cde7e8ee88b6..5d18fabef7ac 100644 --- a/website/site/static/widgets.js +++ b/website/site/static/widgets.js @@ -1,35 +1,66 @@ // Widgets section function widgetsCloud() { - if ($('.widgets')) { - const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud - widgets = document.getElementsByClassName("widget"); // Widgets' bodies - let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; + const widgetItems = document.getElementsByClassName("widgets__item"), // Widget word cloud + widgets = document.getElementsByClassName("widget"); // Widgets' bodies + let activeWidgetItem = document.getElementsByClassName("widgets__item_active")[0]; // Active button in the widgets cloud - for (let i = 0; i < widgetItems.length; i++) { - widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud - const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render - openedWidget = document.getElementsByClassName("widget_open")[0]; // Defines the current open widget - - targetWidget.classList.add("widget_opening"); // Starts the process of opening the next widget + if (document.getElementsByClassName("widgets")) { - openedWidget.classList.remove("widget_open"); // Removes the active state of the current widget - openedWidget.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + if (window.location.hash) { // Function to check if the given URL has a hash to make each widget shareable + const targetWidget = document.getElementById(window.location.hash.substr(1)), + openedWidget = document.getElementsByClassName("widget_open")[0]; - activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud - activeWidgetItem = e.target; // Sets the new active widget item as the clicked one - activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it - - - setTimeout(() => { - targetWidget.classList.remove("widget_opening"); // Removes the opening class to finish transition - targetWidget.classList.add("widget_open"); // Defines the new target widget - openedWidget.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + let targetWidgetItem = ""; + for (let i = 0; i < widgetItems.length; i++) { + if (widgetItems[i].dataset.widgetTarget == window.location.hash.substr(1)) { + targetWidgetItem = widgetItems[i] + } + }; + changeWidgets(openedWidget, targetWidget, targetWidgetItem); // Runs the function to change which widget is displayed + setTimeout(() => { + document.getElementsByClassName("widgets")[0].scrollIntoView({ + behavior: "smooth", + block: "nearest" + }); // Scrolls to the widgets section + },200) + } - }, 150) // When the transition is done, finish the process by attributing the final classes to each widget + for (let i = 0; i < widgetItems.length; i++) { + widgetItems[i].addEventListener("click", e => { // Add click event for each widget button in the cloud + const targetWidget = document.getElementById(e.target.dataset.widgetTarget), // Defines which widget the user is trying to render + openedWidget = document.getElementsByClassName("widget_open")[0], // Defines the current open widget + targetWidgetItem = e.target; // Defines the current open widget + changeWidgets(openedWidget, targetWidget, targetWidgetItem); // Runs the function to change which widget is displayed }) } } + function changeWidgets(active, target, cloudItem) { + + target.classList.add("widget_opening"); // Starts the process of opening the next widget + + active.classList.remove("widget_open"); // Removes the active state of the current widget + active.classList.add("widget_closing"); // But guarantees the current active widget a closing class for transition purposes + + activeWidgetItem.classList.remove("widgets__item_active"); // Removes the active state of the current widget item in the cloud + activeWidgetItem = cloudItem; // Sets the new active widget item as the clicked one + activeWidgetItem.classList.add("widgets__item_active"); // And adds the active CSS class to it + + if (history.pushState) { + history.pushState(null, null, '#' + cloudItem.dataset.widgetTarget); + } + else { + location.hash = '#' + cloudItem.dataset.widgetTarget; + } + + setTimeout(() => { + target.classList.remove("widget_opening"); // Removes the opening class to finish transition + target.classList.add("widget_open"); // Defines the new target widget + active.classList.remove("widget_closing"); // Finally gets completely rid of the previously openened widget + + }, 150) // When the transition is done, finish the process by attributing the final classes to each widget + } } + widgetsCloud(); \ No newline at end of file diff --git a/website/src/css/imports/widgets.css b/website/src/css/imports/widgets.css index e903cb1d4f7e..0ebc878faff0 100644 --- a/website/src/css/imports/widgets.css +++ b/website/src/css/imports/widgets.css @@ -7,7 +7,7 @@ } .widgets__item { - color: $darkGreen; + color: $darkGrey; border: 2px solid $darkGreen; border-radius: $borderRadius; padding: calc($micro /2) $micro; @@ -15,16 +15,12 @@ cursor: pointer; transition: color .2s ease, background .2s ease; display: inline-block; + font-weight: normal; } -.widgets__item:hover { +.widgets__item:hover, .widgets__item_active { background: $darkGreen; - color: white; -} - -.widgets__item_active { - background: $darkGreen; - color: white; + color: white !important; } .widgets__container { From b6ff20c7467927a924db36cb00d8c8f4e71e3bd7 Mon Sep 17 00:00:00 2001 From: hcavalieri Date: Wed, 20 Dec 2017 19:58:32 -0200 Subject: [PATCH 12/12] Adding myself as a contributor :) --- .all-contributorsrc | 19 +++++++++++++++++++ README.md | 6 +++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5b9f67277773..65d3b53fe6e4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6,6 +6,7 @@ ], "imageSize": 100, "commit": false, + "badgeTemplate": "[![All Contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg)](#contributors)", "contributors": [ { "login": "cassiozen", @@ -430,6 +431,24 @@ "plugin" ] }, + { + "login": "neutyp", + "name": "Tim Erickson", + "avatar_url": "https://avatars2.githubusercontent.com/u/1312538?v=4", + "profile": "http://neutyp.com", + "contributions": [ + "design" + ] + }, + { + "login": "davidejones", + "name": "David Jones", + "avatar_url": "https://avatars0.githubusercontent.com/u/871552?v=4", + "profile": "http://davidejones.com", + "contributions": [ + "doc" + ] + }, { "login": "hcavalieri", "name": "Henrique Cavalieri", diff --git a/README.md b/README.md index 814d6f83b4ec..4d91d2188ce3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Netlify CMS -[![All Contributors](https://img.shields.io/badge/all_contributors-54-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-56-orange.svg)](#contributors) [![](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/netlify/netlifycms) A CMS for static site generators. Give non-technical users a simple way to edit @@ -56,7 +56,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds | [
Benjamin Kniffler](https://github.com/bkniffler)
| [
Mike Wickett](http://www.wickett.ca)
| [
Rory Claasen](http://roryclaasen.me)
| [
Frederic Brodbeck](http://www.freder.io/)
| [
Stuart Dum](https://github.com/simplystuart)
| [
Ryan Watters](https://github.com/rdwatters)
| [
Helder S Ribeiro](https://twitter.com/hsribei)
| | [
Artem Govorov](http://dm.gl)
| [
Cédric Delpoux](http://xuopled.netlify.com/)
| [
imorente](https://github.com/imorente)
| [
David Francoeur](http://davidfrancoeur.com)
| [
Rusta](https://github.com/Rusta)
| [
Henrik Lau Eriksson](http://henrik.laueriksson.com)
| [
Kraig Walker](https://www.kraigwalker.com)
| | [
Rich Cook](http://www.TalesofMurder.com)
| [
Damien Van Der Windt](https://github.com/damienvdw)
| [
Matt Jared](http://mattjared.github.io/)
| [
bruce-one](https://github.com/bruce-one)
| [
Frank Taillandier](https://frank.taillandier.me)
[📖](https://github.com/netlify/netlify-cms/commits?author=DirtyF "Documentation") | [
Aquib Master](http://aquibm.com/)
[💻](https://github.com/netlify/netlify-cms/commits?author=aquibm "Code") | [
Eric Jinks](http://ericjinks.com)
[💻](https://github.com/netlify/netlify-cms/commits?author=Jinksi "Code") | -| [
Tony Alves](https://github.com/talves)
[💻](https://github.com/netlify/netlify-cms/commits?author=talves "Code") | [
Ernie Bello](http://ern.me)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aebello "Bug reports") | [
Alexander Kushi-Willis](https://ackushiw.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=ackushiw "Documentation") | [
Igor Kuznetsov](http://www.igk.ru)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aigk1972 "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=igk1972 "Code") [🔌](#plugin-igk1972 "Plugin/utility libraries") | [
Henrique Cavalieri](https://kaordica.com.br)
[📖](https://github.com/netlify/netlify-cms/commits?author=hcavalieri "Documentation") | +| [
Tony Alves](https://github.com/talves)
[💻](https://github.com/netlify/netlify-cms/commits?author=talves "Code") | [
Ernie Bello](http://ern.me)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aebello "Bug reports") | [
Alexander Kushi-Willis](https://ackushiw.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=ackushiw "Documentation") | [
Igor Kuznetsov](http://www.igk.ru)
[🐛](https://github.com/netlify/netlify-cms/issues?q=author%3Aigk1972 "Bug reports") [💻](https://github.com/netlify/netlify-cms/commits?author=igk1972 "Code") [🔌](#plugin-igk1972 "Plugin/utility libraries") | [
Tim Erickson](http://neutyp.com)
[🎨](#design-neutyp "Design") | [
David Jones](http://davidejones.com)
[📖](https://github.com/netlify/netlify-cms/commits?author=davidejones "Documentation") | [
Henrique Cavalieri](https://kaordica.com.br)
[📖](https://github.com/netlify/netlify-cms/commits?author=hcavalieri "Documentation") | -This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! +This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file