惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
Spread Privacy
Spread Privacy
T
Threatpost
C
Cisco Blogs
P
Palo Alto Networks Blog
AI
AI
Cyberwarzone
Cyberwarzone
NISL@THU
NISL@THU
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
Latest news
Latest news
AWS News Blog
AWS News Blog
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
WordPress大学
WordPress大学
Vercel News
Vercel News
S
Securelist
爱范儿
爱范儿
J
Java Code Geeks
Know Your Adversary
Know Your Adversary
S
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
F
Fortinet All Blogs
Last Week in AI
Last Week in AI
D
DataBreaches.Net
宝玉的分享
宝玉的分享
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
K
Kaspersky official blog
美团技术团队
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
量子位
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
腾讯CDC
T
Threat Research - Cisco Blogs
雷峰网
雷峰网
有赞技术团队
有赞技术团队
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
S
Security Affairs

Linear Blog

Teaching an agent to auto-fix bugs - Linear Now Linear writes the code, too - Linear Reviewing code in the agent era - Linear Code review should be fast - Linear Code Intelligence for Linear Agent - Linear How we hire at Linear - Linear Output isn’t design - Linear How we use Linear Agent at Linear Post mortem on Linear security incident on March 24th, 2026 A calmer interface for a product in motion Design is more than code - Linear How our Customer Experience team works in Linear - Linear Continuous planning in Linear - Linear Designing remote work at Linear - Linear Self-driving SaaS: When software runs itself - Linear A Linear spin on Liquid Glass - Linear Best practices for designing Linear Dashboards - Linear Why we committed to a zero-bugs policy - Linear How Commure uses Dashboards to track performance and guide planning - Linear How we built Triage Intelligence - Linear Giving our team liquidity through Linear’s first tender offer - Linear How Cursor integrated with Linear for Agents - Linear Quality Wednesdays: How we trained our team to see what doesn’t work - Linear Our approach to building the Agent Interaction SDK - Linear Inside Mercury’s six-month journey building with AI agents - Linear Building our way: Announcing our Series C - Linear Why is quality so rare? - Linear Design for the AI age Building what customers need, not just what they ask for - Linear The profitable startup - Linear Why and how Scale migrated to Linear - Linear Simplifying support at scale: How Pleo uses Linear Asks - Linear How we built multi-region support for Linear How we redesigned the Linear UI (part Ⅱ) - Linear A design reset (part I) Rethinking the startup MVP: Building a competitive product | Linear Descript's internal guide for using Linear Post mortem on Linear incident from Jan 24th, 2024 | Linear Why and how we do work trials at Linear Using AI to detect similar issues Planning for unplanned work How we run projects at Linear - Linear Linear raises $35M Series B led by Accel - Linear How we think about customer experience at Linear - Linear Scaling the Linear Sync Engine - Linear Welcoming Cristina Cordova to Linear How we built Project Updates Settings are not a design failure Linear – 2021 Wrapped Fast growing startups are built on Linear Building at the early stage Linear raises $13M in Series A funding from Sequoia Capital Practices for Building — Linear is now open for all Startups, Write Changelogs Linear’s Next Chapter: Announcing our $4.2M Seed Round
Invisible details - Building contextual menus - Linear
Andreas Eldh · 2020-09-18 · via Linear Blog

We recently added contextual menus to Linear. This makes the app faster and easier to use for people who prefer their mouse.

One small thing that you won’t see or think about but will hopefully *feel* is a detail we designed into how sub-menus work.

You may know contextual menus as “right click” or “pop up” menus. Right click with your mouse on this post (or Ctrl+ Click with your trackpad) and you’ll see a short contextual menu appear on your screen with options to reload or save the page. Contextual menus were first popularized by applications such as Microsoft Word which added them so users could more easily copy and paste. You’ll find them in most web and desktop-based applications.

Link to tweet

Tweet from Andreas Eldh about a safe area between the cursor and the menu when navigating contextual menus in Linear.

Contextual menus make applications faster and easier to use when navigating a page with your mouse. On Linear, we let you take almost any action on an issue from the contextual menu: set the issue status or priority, assign the issue to a different member of your team, change the estimate, mark it as blocking or a blocker to another issue, mark it as a duplicate, add the issue to a cycle or project, copy the git branch name and even archive the issue to remove it from your active issues list.

Nested contextual menu within Linear, open to the Issue Status submenu.

A contextual menu in Linear

We’re learning that contextual menus are also a great tool for onboarding and teaching people how to use our popular keyboard shortcuts. You can take almost every action in Linear without lifting your fingers off of the keyboard or using a mouse at all. For instance, instead of moving your cursor to the purple plus sign and clicking on it to create a Linear issue, you can just type C.

We find many Linear users prefer keyboard shortcuts for their speed but it can take some time to learn all of them. It’s also easy to forget the less-used keyboard shortcuts such as the one that lets you move an issue between teams (Cmd / Ctrl +Shift +M). Previously you had to open the command menu with (Cmd / Ctrl + K) and then type out a search query to find a keyboard shortcut you forgot or type ? and then search our long list. Now you can simply right-click to take the action with the mouse or remind yourself of the keyboard shortcut.

In the first iteration of our menu, to access an item in a sub-menu you would have to move the cursor out in a straight line from the selected item onto the sub-menu, then move down from the top of the sub-menu to the item you wanted to click. You basically have to make an upside down L shape with your mouse.

The original design had a couple of problems:

One, it’s not intuitive. It feels more natural to move the cursor in a diagonal line from the selected menu item to the sub-menu item you want to click. If you did that, though, the sub-menu would disappear before you could select the sub-menu item.

Two, it takes longer. At Linear we care a lot about speed. It may only take a fraction to 1–2 seconds longer to move your mouse in an upside down L shape but the seconds add up when you’re taking the action multiple times. Some product and engineering managers take hundreds of interactions a day on Linear. Add in the time required to recoup after a menu disappears on you and the related frustration and it starts to feel like an important interaction to improve.

If you think about it, there’s no real reason why we build contextual menus that require this longer path when there’s an alternative. The shortest distance will always be the Euclidian, or diagonal, distance compared to the Manhattan distance, the distance taken when following the lines of a grid.

Diving into the code

Adding safe areas to contextual menus is not a new problem. Amazon, Khan Academy and others have all implemented mechanisms to handle contextual menus better on their web apps. Native operating systems have followed these design pattern for many years. However, it’s a detail that’s often overlooked early in a web application’s development.

There are a few ways of approaching how to build contextual menus that let users scroll easily to the sub-menu items. We thought the best way would be to draw a triangle between the mouse cursor and the sub-menu to create a safe space where the mouse could move without triggering the sub-menu to close. So we built a component to do just that.

The safe area between the main and sub contextual menu is highlighted in red

The safe area lets you move the mouse along the shortest path without closing the sub-menu

Here’s how to build a React component that creates a “safe area”:

The component gets a reference to the sub-menu as its only prop so that it can measure its size and position on the screen.

const { x = 0, y = 0, height = 0, width = 0 } = props.subMenuRef.current?.getBoundingClientRect() || {};

2. Get the mouse coordinates

For this we built a custom hook that listens to the mouse movement. It’s used like this:

const [mouseX, mouseY] = useMousePosition();

3. Calculate the safe area

Now we have all the information we need to calculate what area to render between the cursor and the sub-menu. We need to figure out the position and size of the triangle as well as align the corners of the triangle correctly.

const positions = { x, y, height, width, mouseX, mouseY }
return (
  <div
    style={{
      position: 'absolute',
      top: 0,
      height,
      right: getRight(positions),
      left: getLeft(positions),
      width: getWidth(positions),
      clipPath: getClipPath(positions),
    }}
  />
)
 

The most interesting bits in the snippet above are perhaps the functions that calculate left, right, width and clipPath:

clip-path is a cool css property that lets you define a region of the component that should be drawn to the screen. In this case we use a polygon to draw a triangle.

Not too bad! It only took about 40 lines of code all in all. Hopefully people using Linear will feel the difference.

If you’re curious, here’s a gist with the full implementation.