Skip to content

Instantly share code, notes, and snippets.

View fpapado's full-sized avatar

Fotis Papadogeorgopoulos fpapado

View GitHub Profile
@fpapado
fpapado / README.md
Last active March 8, 2021 08:49
Duolingo (more) Accessible Styles

Installation

Install directly with Stylus

To install this stylesheet, you will need a userstyle extension. For example:

Then, you will need to open the link below, which the extension will pick up and prompt you to install:

@fpapado
fpapado / README.md
Last active June 22, 2021 19:50
:focus-visible progressive enhancement mixin

Find the full post on fotis.xyz

:focus-visible is a standard way of only showing focus styles for keyboard and focus-based modalities. When using it, however, you must take care to not remove :focus altogether, where :focus-visible is not supported.

With CSS, we can achieve progressive enhancement of :focus to :focus-visible:

/* Styles where only focus is supported */
button:focus,
@fpapado
fpapado / 0_Validating_URLs.md
Last active November 7, 2023 07:31
Validating URLs with the URL constructor

Validating URLs is hard! On the face of it, you could use a RegEx to match on the URL structure, but that is likely only going to match a narrow subset of URLs, whether intentionally or accidentally.

Beyond having a "valid" URL, an application might be applying extra conditions on top. For example, accepting only http: or https: URLs, but not file: and others. This might be ok depending on the application, but knowing that takes some active design work to figure out. For the purpose of handling user errors, and offering suggestions, it also helps to know in what manner the URL failed validation. For example, we might be able to offer precise suggestions for our application-specific errors, while general URL parsing issues can be out of scope.

To make life easier, let's separate the term "valid" and "invalid" into a few different ones:

  • Valid URL: a URL that can be parsed successfully according to the standard (which, uhm, I am reluctant to dive into, or rather I feel unqualified to give you an overvi
@fpapado
fpapado / state.njk
Last active March 28, 2020 19:15
Roasters by State
---js
{
pagination: {
// Go over the roaster data
data: "roasters",
// Convert the list of roaster to {[state]: {name: string, roasters: Array<Roaster>}}
// (You could do without the {name, roasters} and only have data, but then the iteration is uglier imo)
before: function(roasters) {
let roastersByState = {};
for (let roaster of roasters) {
@fpapado
fpapado / 0_useLeftRightAutoPosition.tsx
Last active June 6, 2019 08:03
useLeftRightAutoPosition
import {useLayoutEffect, useState} from 'react';
/**
* React Hook to measure a DOM element and set its `position` depending on
* whether it would overflow left or right.
*
* Uses useLayoutEffect for batched DOM measurements and painting.
*
* @param toggle a boolean on whether to run the effect. Runs cleanup when it changes.
* You might want a toggle if the element is always present in the DOM, and its display toggled.
@fpapado
fpapado / split_panels.js
Created July 23, 2018 09:01
SpeedCurve split panels
(function() {
'use strict';
// Your code here...
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
@fpapado
fpapado / SketchSystems.spec
Last active July 10, 2018 21:26
Unpublished*
Unpublished*
publish -> Published
Published
unpublish -> Unpublished
event exists -> Event
no event exists -> No Event
Placeholder*
@fpapado
fpapado / FauxButton.tsx
Last active July 12, 2018 12:58
Accessible `<button>` usurper
import React from "react";
/**
* Accessible "button" usurper.
* Establishes the correct role, tabindex, and key/mouse interaction if interactive.
* Buttons activate on space and enter.
*
* NOTE: Gives 'disabled' attribute if interaction not provided.
*
* @see https://www.w3.org/TR/wai-aria-practices-1.1/#button
@fpapado
fpapado / graphana_pride.css
Created June 27, 2018 15:45
Grafana Custom CSS for Pride
.scroll-canvas--dashboard {
background: linear-gradient(180deg, #f00000, #f00000 16.67%, #ff8000 16.67%, #ff8000 33.33%, #ffff00 33.33%, #ffff00 50%, #007940 50%, #007940 66.67%, #4040ff 66.67%, #4040ff 83.33%, #a000c0 83.33%, #a000c0) fixed;
}
@fpapado
fpapado / 01_failing.js
Created March 18, 2018 15:27
nanotiming overlapping timers
// Three operations (loops for simplicity).
// We want to time the first two separately and all three of them together.
// Ideally, the ordering of starting the timers would not matter.
// This case fails because the timer for the first two loops is started first
var nanotiming = require('nanotiming')
try {
var performance = require('perf_hooks').performance
var timeFirstTwo = nanotiming('my-loop')