6.S063 Design for the Web: Languages and User Interfaces

↑ All studios

Studio 10

User Testing

To prepare for HW10, we will be doing user testing of each other's Balsamiq/Figma mockups. Note that this is not the user testing required for HW10, but merely practice to help you prepare for it. Think of one task, as described in Exercise 2 of HW8. Take turns as faciliatator and user. Make sure to explain to your subject what you are building, and what users it is for. The course staff will be observing, to give you feedback about how to better conduct user tests.

Color game

Spend some time playing this color guessing game.

Let's do a little experiment:

First, restrict yourself to only using rectangular color models (rgb(), hex, lab(), oklab()). See what score and times you get.

Then, try using only cylindrical color models (hsl(), hwb(), lch(), oklch()). Did you get a better or worse average score? What about average time?

User Name Resolution

In your homework this week you will start working on implementing a chat application! We have provided you with a working chat application template, which you can try out here. You can read more about it in your homework instructions and the chat template documentation.

Log in to the template app and do some exploring. It's pretty awful! Your goal this week is to make this basic version usable before adding your own cool features.

The template chat application uses an infrastructure called Graffiti to handle sending, receiving, and storing data. When a user logs in to Graffiti, they are assigned a randomly generated and unique "actor ID" that is tied to their account. Check out some of the actor IDs displayed in the chat app - they're impossible to read!

If you navigate to the "Private Messaging" section of the template app, there is an input where you can paste someone's actor ID to start a chat with them. This is extremely unusable, so in this studio you're going to implement a tried and true system for uniquely referring to users: usernames.

Note that the app already let's you set a name. This can be whatever you want and it is not necessarily unique. Usernames, however, are unique.

Experimenting with the API

We have provided you a "username resolver" that lets you request a username, map usernames to actor IDs, and map actor IDs to usernames.

Before using this in our code, let's experiment with the API in the browser console. First import the graffiti API:

const { default: Graffiti } = await import('https://graffiti.garden/graffiti-js/graffiti.js')
const gf = new Graffiti()

Then print out your actor ID, gf.me. If it is null that means you're not logged in. Log in by calling gf.toggleLogIn() and then try displaying your actor ID again. Note that the page refreshes and the console clears when you log in or out so you will need to reimport Graffiti.

Now let's experiment with the resolver. Import and initialize the resolver as follows:

const { default: Resolver } = await import('https://graffiti.garden/chat-lab/resolver.js')
const resolver = new Resolver(gf)

Now you should be able to use three functions of the resolver requestUsername, actorToUsername, and usernameToActor. First try out requestUsername:

await resolver.requestUsername("my-cool-username")

Now see if you can resolve your actor ID to the username and vice versa:

await resolver.actorToUsername(gf.me)
await resolver.usernameToActor("my-cool-username")

Can you resolve the actor ID or username of a friend? What happens if you try and request a username that another account has already taken? What happens if you call requestUsername multiple times from the same account? Can you have multiple usernames?

Adding a "Request Username" Form

The first step of adding usernames to your chat application, is to add a form somewhere that let's a user request a particular username.

Fork the homework 10 repository to get started. The template already does the work of importing and setting up Graffiti and the resolver. You can access them via $gf and resolver in template code and via this.$gf and this.resolver in the Vue component definition.

Be careful when you're defining methods to call! There are two methods sections in chat.js, one within the main app and one within the Name component, which is what handles display names not usernames. Be sure you're putting your code within the methods section under app.

Did you see in your experiments what happens when you try to request a username that is already taken? Make sure you give appropriate feedback to the user!

You can make sure that your request form is working by verifying the username changes when you fetch it via the console interface.

Searching by Username

When you switch the radio button to "Private Messaging", there is a box that let's you paste an actor ID to start chatting. Let's change it so you can type in a username instead.

Create a field for typing in a username and a "Search" button. When the search button is pressed you should you call the usernameToActor function and once the asynchronous function resolves, change the actor ID the user is chatting with.

What should happen when there is no matching username? Can you provide a loading indicator before the search completes?

Test this out by typing the usernames of other people in the class and chatting with them.

Displaying username

Now you can chat with someone by their username, but you wouldn't know what their username is unless they specifically told it to you. Implement a way for users to discover the usernames of other users in the application.

There are lots of ways to do this. Perhaps the usernames are always displayed next to a user's display name like on Twitter. Perhaps users have a separate "profile" page that displays their username. Feel free to be creative!

Depending on your design, it might be useful to cache the usernames that your app has already fetched, that way all future fetches will be practically instantaneous.

Bonus: Autocomplete

When you search for a username, it would be nice if those usernames autocompleted so the user only has to type in the first couple letters. Can you store usernames that your application has encountered and search through them as the user types?