A place to cache linked articles (think custom and personal wayback machine)
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.html 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Design Notes (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://www.colophon.cards/notes/01-design-notes/">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Design Notes</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://www.colophon.cards/notes/01-design-notes/" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <h2>The high concept (in apps)</h2>
  71. <p>Colophon Cards should be the marriage of <a href="https://notational.net/">Notational Velocity’s search-first navigational model</a> with Twitter’s card stack model.</p>
  72. <p>Most people don’t notice this but Twitter’s conceptual model is that of a recursive stack of cards. Each tweet is about as much as you’d fit on one side of an index card. Each tweet is also a thread which is a stack of related cards. The timeline is a top-level thread/stack. This is the reason why the algorithmic timeline is such a disruption of how even non-techies use Twitter: it’s a fundamental break in the service’s basic design.</p>
  73. <p>From Notational Velocity’s website:</p>
  74. <blockquote>
  75. <p>The same area is used both for creating notes and searching. I.e., in the process of entering the title for a new note, related notes appear below, letting users file information there if they choose. Likewise, if a search reveals nothing, one need simply press return to create a note with the appropriate title.</p>
  76. <p>If a note’s title starts with the search term(s), that title will be “auto-completed”. This selects the note and consequently displays it. Correspondingly, selecting a note places its title in the search area (De-selecting the note restores the search terms).</p>
  77. <p>To create a new note, just type its title and press return. Edit the note as needed in the bottom pane.</p>
  78. <p>To view or edit an existing note, type one or more words contained in its body or title. Reveal a note’s content by using the up/down arrow keys to select it.</p>
  79. </blockquote>
  80. <p>My theory is that I can adapt this navigational model to work with the cards and stacks model popularized by Twitter.</p>
  81. <h2>Terminology</h2>
  82. <p><em>Threads</em>: I’ve decided to prefer threads over stacks as, even though, they would mean the same thing when you are building with cards as a core metaphor, they’ve come to have specialised meanings in UX and UI in general. Namely, a thread has come to be the standard term for “a linear sequence of things, some of which may also be similar linear sequences of their own”.</p>
  83. <p><em>Cards</em>: this has also become a generic term for a UI widget that contains some form of content.</p>
  84. <p><em>Activity/Activity Stream</em>: often called event stream. This is a stream of the events/activities that form all of the data belonging to a particular user. This is usually an implementation detail (every social media platform implements something like this, as do most apps/services that need to sync data from one place to another). But I would like to test surfacing it as a UI element to see if it helps recall and aids understanding.</p>
  85. <h2>The main single-user loops</h2>
  86. <h3>The thread</h3>
  87. <p><img src="/images/threads-sketch2.jpg" alt="Sketch of how threads might work"></p>
  88. <p>The core UI view of the app is a thread of cards (or cards and actions on cards, if I follow through with the activity streams idea).</p>
  89. <p>The UI would be structured in a way that’s similar to Twitter or Mastodon:</p>
  90. <ol>
  91. <li>At the top you have an input box.</li>
  92. <li>Below it you have a stream of cards and activities in reverse-chronological order (newest first).</li>
  93. <li>Type text in the search box</li>
  94. <li>The thread is then filtered to only shows cards whose name begins with the search text until there is one (to update) or none.</li>
  95. <li>At any point in the search, the user can hit the button or press return to create a card with that name. Or they can edit the top card and autocomplete the term to that card’s name.</li>
  96. </ol>
  97. <p>One of the core properties of a search-first UI like this (<em>true</em> search first, not baked-on-because-we-don’t-do-design search first like Google Drive) is that it makes you much more aware of the names of things and constantly surfaces older, relevant, cards as you are thinking about names for your new thing.</p>
  98. <p>The innovation here over Notational Velocity is that each card is also a thread and therefore a completely encapsulated search space. So, you can have a thread for ebooks. A thread for images. A thread for a project. For bookmarks.</p>
  99. <p>Thoughts:</p>
  100. <ul>
  101. <li>I am tempted to have the thread be an activity stream. Instead of just the cards, you would also have the activities on those cards listed in the thread. Like “You updated ‘design notes’” or “You archived ‘design notes’”. I would like to see if having explicit records on your activities in a thread is a helpful mnemonic or not. AFAIK there hasn’t been much research on whether this is helpful in a single-user context so I’m tempted to test it out.</li>
  102. <li>Full-text search would be on the roadmap but I need to demonstrate the practicality of the basic design model first.</li>
  103. <li>The user shouldn’t be able to create multiple cards with the same name in the same thread. Trying to create a card with a name identical to another would bring up an edit view for that card.</li>
  104. </ul>
  105. <h3>The Card</h3>
  106. <p><img src="/images/card-sketch.jpg" alt="Sketch of how cards might work"></p>
  107. <p>The created card has a name, replies (only displayed when you open the card as a thread), attachments, and a body. Possibly later a drag handle.</p>
  108. <p>Thoughts:</p>
  109. <ul>
  110. <li>“name” might be the wrong term for what is, in effect, the main text of the card and should be thought of as more akin to a tweet than document title. Maybe ‘card text’ (plain text, quick search) versus ‘card body’ (rich text, only findable using a full-text-search feature down the line).</li>
  111. <li>Should the body be rich text, plain text or markdown (irrespective of what it’s stored as)? Markdown is the de facto note standard but is honestly a mess of partially compatible implementations. It also forces a modality to your editing: notes have two completely different modes that look and work in very different ways. Plain text is universal but incredibly limited. A rich text interface has the most potential but is more complicated and harder to pull off.</li>
  112. <li>More on modality: getting rid of modes does more to make a UI feel fast than most of the performance work engineers love to throw at problems like these. The “find item -&gt; click edit on item -&gt; edit -&gt; save item” cycle is always going to feel slow, no matter how many optimisations through throw at it. If you figure out a way to make it “find item -&gt; edit item” (no ‘edit mode’) then the UI will feel fast no matter how unoptimised the implementation is.</li>
  113. </ul>
  114. <h3>Tags</h3>
  115. <p>Add tag support by assigning all tags mentioned in the body or name to the card. You can show all cards with that tag by entering it (with the preceding #) in the search box.</p>
  116. <h3>Replies</h3>
  117. <p>Every card is also a thread. The replies link on the card is a link to the card’s thread. The card thread UI is identical to the top thread UI. Replies are created in the same way with the same loop as in the top thread.</p>
  118. <p>Thoughts</p>
  119. <ul>
  120. <li>I would like to avoid having a specific reply UI and instead keep the conceptual model the same all the way down.</li>
  121. </ul>
  122. <h3>Workspaces/Accounts?</h3>
  123. <p>Should the user be able to have multiple top-level threads, each a separate workspace? Or do the child cards of a solo top thread serve the same function?</p>
  124. <h3>Pinning</h3>
  125. <p>The UI should support pinned notes that are persistently floated to the top. One idea is that on displays that are wide enough the pinboard should be a sidebar space and that pinned cards don’t have to just be pinned up to but that they could be arranged freely in the sidebar space.</p>
  126. <h3>Bookmarks</h3>
  127. <p>Much like Twitter or Facebook, the URLs mentioned in the name or the body are automatically added as attachments.</p>
  128. <h3>Attachments</h3>
  129. <p>File attachments are added via an attach button.</p>
  130. <p>Thought:</p>
  131. <ul>
  132. <li>I could implement a website archiving system that archives a bookmark URL if you add the URL via the attachment UI instead of directly as text?</li>
  133. </ul>
  134. <h3>Quoted Cards</h3>
  135. <p>A special kind of attachment is the quoted card (a concept stolen from Twitter). This is a mechanism for bringing a card from one thread in as a reply to another. Cards shared from other users would also be read-only quoted cards in your threads.</p>
  136. <h3>Cross-linking</h3>
  137. <p>If I go with markdown or plaintext <code>[[Note Name]]</code> would be used to automatically link to the note.</p>
  138. <p>If I go with rich text I would probably try to implement it using a <code>+Name</code> mentioning system similar to Slack’s @ mentioning system that autocompletes including the spaces.</p>
  139. <p>Or, I could go with the original WikiWiki design and convert all camel-cased words to links to other notes?</p>
  140. <p>Links to nonexistent notes let you create that note by clicking on them.</p>
  141. <h3>Backlinks</h3>
  142. <p>Automatic backlinks are not a good idea. They create clutter, complexity and confusion. See <a href="https://zettelkasten.de/posts/backlinks-are-bad-links/">Backlinking Is Not Very Useful – Often Even Harmful</a>. Intentional backlinks, however, are amazing. The ability to explicitly add a backlink from another note to the current note you’re editing, preferably with custom link text for that context, is an extremely useful organisational tool.</p>
  143. <p>How to design it, though, is a question, and it depends on the text format and link format.</p>
  144. <h3>Sharing</h3>
  145. <p>Designing the sharing and collaboration mode should be a separate document. But the threads and cards UI should be <em>single user</em>. Nothing should happen in your threads or to your cards that isn’t done by you. Sharing should be about data, attachments and sharing your threads (or subsets of your threads) with others as documents.</p>
  146. </article>
  147. <hr>
  148. <footer>
  149. <p>
  150. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  151. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  152. </svg> Accueil</a> •
  153. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  154. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  155. </svg> Suivre</a> •
  156. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  157. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  158. </svg> Pro</a> •
  159. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  160. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  161. </svg> Email</a> •
  162. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  163. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  164. </svg> Légal</abbr>
  165. </p>
  166. <template id="theme-selector">
  167. <form>
  168. <fieldset>
  169. <legend><svg class="icon icon-brightness-contrast">
  170. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  171. </svg> Thème</legend>
  172. <label>
  173. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  174. </label>
  175. <label>
  176. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  177. </label>
  178. <label>
  179. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  180. </label>
  181. </fieldset>
  182. </form>
  183. </template>
  184. </footer>
  185. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  186. <script>
  187. function loadThemeForm(templateName) {
  188. const themeSelectorTemplate = document.querySelector(templateName)
  189. const form = themeSelectorTemplate.content.firstElementChild
  190. themeSelectorTemplate.replaceWith(form)
  191. form.addEventListener('change', (e) => {
  192. const chosenColorScheme = e.target.value
  193. localStorage.setItem('theme', chosenColorScheme)
  194. toggleTheme(chosenColorScheme)
  195. })
  196. const selectedTheme = localStorage.getItem('theme')
  197. if (selectedTheme && selectedTheme !== 'undefined') {
  198. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  199. }
  200. }
  201. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  202. window.addEventListener('load', () => {
  203. let hasDarkRules = false
  204. for (const styleSheet of Array.from(document.styleSheets)) {
  205. let mediaRules = []
  206. for (const cssRule of styleSheet.cssRules) {
  207. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  208. continue
  209. }
  210. // WARNING: Safari does not have/supports `conditionText`.
  211. if (cssRule.conditionText) {
  212. if (cssRule.conditionText !== prefersColorSchemeDark) {
  213. continue
  214. }
  215. } else {
  216. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  217. continue
  218. }
  219. }
  220. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  221. }
  222. // WARNING: do not try to insert a Rule to a styleSheet you are
  223. // currently iterating on, otherwise the browser will be stuck
  224. // in a infinite loop…
  225. for (const mediaRule of mediaRules) {
  226. styleSheet.insertRule(mediaRule.cssText)
  227. hasDarkRules = true
  228. }
  229. }
  230. if (hasDarkRules) {
  231. loadThemeForm('#theme-selector')
  232. }
  233. })
  234. </script>
  235. </body>
  236. </html>