SebastianKra
The mental model of describing a series of reproducible transformations on normalized tables is more intuitive to me.
Excel lets you do too many things. As a result, I mostly see spreadsheets that aren't much more machine-parsanle than a word document.
We had to write a score-table at a party lately, and a while ago, and I managed to get it working with DataSpell faster, than it took us to figure out how Google Sheets stupid date-parsing works.
- no columns view
- no quick look
- freezes for 5 seconds when you accidentally drag over a disconnected network location
- when opening a files, doesn't let you drag in an file to select it.
- no shortcut for toggling hidden files
- no tabs until Win 11
- no tags
- no sorting by "date added"
This was mostly a check for myself to see if I had Stockholm syndrome. But I keep finding more reasons to prefer Finder.
All UI's should be tab-able, but that's still a miserable experience for keyboard users. A keyboard-centric UI must provide instantly discoverable shortcuts. Possible methods:
- Put all elements on a grid so that they can be navigable with the keyboard. This is a significant restriction for the designer.
- Put keyboard shortcuts next to every button. It's not enough to put them in tooltips (*cough* Raycast). Common in games, but wastes space.
- Add a Command Palette. This is the easiest, but it requires mirroring every action, and is suboptimal when you have the same action for each item in a set.
When designing for technical users: all of the above please. But for average users it's less clear. I think there's still room for innovation, both on the software architecture and the UI side.
But Sequoia and up have strict management of background agents in "Settings / Login Items".
It fills up with so many broken references, duplicate entries, etc... I have no idea how a normal user is supposed to remove trash from that list. I pointed an agent at it, asking it to remove any broken references.
CSS for design systems is fine. You can define a .button[data-variant=”primary”]. It’s intuitive, performant, makes sense.
CSS for application code is terrible — specifically layout & typography. The different kinds of flex/grid layouts are tightly coupled to the dom structure. Tailwind is a great fit here:
<li class=”flex flex-col”>
<div class=”font-medium”>Title</div>
<div class=”text-sm”>Subtitle</div>
</li>
When you remove layouting concerns and maybe typography. You actually get close to the separation of concerns that CSS was initially aiming for. HTML determines arrangement and css determines the design system (colors, borders, shadows etc...).I havent seen this discussed a lot. The old Radix team had a short note: https://www.radix-ui.com/blog/themes-3#the-best-of-both-worl...
It's so common, that there is an expensive runtime package, `tailwind-merge`, that is used by default in the most popular component library.
I believe most people are influenced by these constant micro-impressions far more than they realize.
My best defense is to build a resentment towards the companies being advertised.
Can we not just do `:host { display: contents }` and use the same approach?
2. This isn't true for apps anymore. Server driven ui is a thing.
3. JS runs locally. You can inspect the network traffic more easily than you can with an app.
4. You can audit OSS websites too.
5. Your personal preferences have nothing to do with the fact that Apple makes tons of money from apps but not websites.
- Steam forces game updates, even for single player games.
- terrible delta updates. Baldurs Gate 3 had 8 patches in 3 Years. That's 800GB of updates.
If a patch drops on the afternoon you planned with your friends, you're not playing that night (actually happened to us). Both decisions should have caused outcries, but I guess people would rather overpay for fast internet contracts.
There are some techniques that aren't immediately obvious. Look into...
- type guards
- pushing constraints up: `function print(i: Invoice & { issueDate: string })` is better than `assert(i.issueDate)`
- discriminated unions
I don't get this. Many things like changing the IP or audio devices were so unintuitive that I just memorized them. They're still burned into my brain. In Win 11, you just search for 'IP', click 'Ethernet-Settings', done.
Same for the signifiers: In the Win 11 Settings, give me an example of an element that is not obviously clickable. Everything has button shapes, or step-in indicators.
To be clear, I'm neutral towards that settings app. But UI back then was nowhere near as good as claimed here, and flat design (at least the current iteration) isn't to blame for Teams being bad.
It took them ~4 years to ship this editor, and it shows. They managed to find the perfect balance between formatting markdown as you type and minimizing content shift. It's feature-rich while still providing the interoperability I expect from Markdown.
"Siri, start a stopwatch" - runs the App "Stopwatch" without starting it
Such errors happen maybe 50% of the time. You can never just ask something without double-checking afterwards.
"We can't bring Time Machine to Europe, because we would have to allow other backup solutions, and that would mean other backups would have unrestricted access to your data"
Maybe there's more to it, but I'm not giving Apple the benefit of the doubt after their hostile strategy regarding third-party app stores.
> Every UI is always some mapping of the state.
Sure, but it previously wasn't described as such. It was described as a list of imperative operations "if x do that" (unless the developer just gave up and had a giant refreshEverything() function). IIRC, at the time, MVC had a common problem of controller bloat, precisely because it was trying to perform the reconciliation between view and model imperatively rather than simply describing it as a function. MVVM solved this partially with data-binding, but depending on the framework, you still had lackluster handling of derived state inside the view-model.
> What does "pure representation" mean to you?
I mean that, the render function of the component is a 100% pure function of the state that the framework injects. By "render function" I mean everything except the statements beginning with `use...`. Those are just React's syntax for defining the component. Another framework such as SwiftUI might have defined them outside the function.
> But can you elaborate the specific advantages you believe the react approach gives us over, say, MVC?
There are so many resources on this, so I don't know what I can say to convince you, but I'll try:
* The Compiler. Regardless of whether you think it’s self-inflicted complexity (I don’t), functional patterns generally are easier to statically analyze and transform.
* Transitions, concurrent rendering, suspense, & time-slicing. All of these are possible by rendering components with outdated state. A low priority update may trigger a loading state and defer its commit. Meanwhile, high priority updates can continue to work as usual. In the past ~2 years, this is easily where I've seen the most UX & DX gains in frontend.
* Most importantly: readability. Even if components are only 90% pure, I still see side-effects and state clearly marked. Even in MVVM, I've seen so much spaghetti from my coworkers. In React & post-React frameworks, when debugging a component, I have a much narrower range of things I need to check. For example, I don't have to worry that an object I'm reading from is being mutated by a component on a completely different route.
Overall, the reason why this post rubs me the wrong way, is that you took a theoretical design document, misunderstood it for the actual, practical implementation and snarked at the authors for not going with the "obviously correct" solution of OOP. Not seeing the bigger picture in 2018 is understandable, but now it's... interesting.
Narrowmindedly worrying about syntactical differences is contributing nothing to the conversation. The point is relinquishing control of state to the framework (be it via props, hooks or @State), and drawing the UI as a pure representation of whatever the framework tells you. Hence ui = f(state). This gets you a metric ton of advantages, which is why every modern framework is doing it.
Classes, by themselves, are inadequate as containers for state unless that state must only exist in memory and never be observed, synchronized or serialized. You can attempt to patch that with decorators, ORMs or whatever, but now you're doing the same thing as React is doing with functions.
Obviously thats not what we got, but I feel like the set of established UI patterns is manageable enough that it could be built.
A great example is the new <select> styling that developers styled in all kinds of creative ways. Now give me that for comboboxes, trees, data-grids etc...
What annoys me is how little they want to integrate with ...anything. Wanna open a link in your default browser? Use our built-in chromium fork, we insist. Wanna open a location in Zed? No, please use our half-baked editor re-implementation. Wanna open a location in Cursors own vscode-based editor? You can't. Managed to work around that somehow? We changed your files to "Worktree TS", disabling all your language servers. It's like programming on an iPhone.
If you sell gambling ads to an addicted gambler, the gambler doesn't get useful information.
Niche interests might get a pass. But then again: if I’m getting an ad for a 3D printing product on a 3D printing review site, its very likely that the advertised product wasn’t actually the best and is just artificially pushed on me.
It assumes that “ads” = useful information, but that's rare at best. Most ads focus on stealing your attention and creating a fear of missing out. NordVPN isn't educating you. They just manufacture a need and then hope that you won't invest time in researching a better option.
Why would I give them more leverage to do that?
A backup of my 2TB MacBook literally takes weeks.
Because JS is single threaded, fs.readSync will freeze the entire app. The only case where I would find that acceptable is in cli-scripts. But that could also be achieved with nodejs’ support for top-level await. There's perhaps a slight overhead from the Promise being created, but JS-Engines have so many optimizations that I don't even know if that matters. If nothing else is scheduled, awaiting a promise is functionally the same as blocking. Even in rare cases where you do want to block other scheduled events from running, you could achieve that with an explicit locking mechanism instead.
You could argue that filesystem access is fast so blocking everything is fine, but what if the file happens to be on a NAS somewhere?
The other advantage is a rough classification in the type system. Not marking a function as async means that the author believes it can be run in a reasonable amount of time and is safe to run eg. on a UI main thread. In that sense, the propagation through the call hierarchy is a feature, not a bug.
I can see that maintaining multiple versions of a function is annoying for library authors, but on the other hand, functions like fs.readSync shouldn’t even exist. Other code could be running on this thread, so it's not acceptable to just freeze it arbitrarily.