Inference

Telling you how we see the world.

Cadmus Twitter API

Posted by Frank on May 24th, 2010

The main goal of Cadmus has always been to be able to provide a service that helped you figure out what are the most important topics your friends are talking about. We have provided an API right from the beginning and recently we have been working on a Twitter specific API that makes Cadmus really easy to integrate with. Our new Twitter like API allows you to do the following with your stream:

If you are working with our API we would love to hear from you; feel free to contact me over email or via Twitter.

A Sliding Puzzle While You Wait

Posted by Jay on Apr 24th, 2010

One of the issues we have had with Cadmus is that the first time you sign in or if you sign in after a while you would need to wait a bit before we show you your updates. On an average it takes around a minute to process your Twitter stream. We are working on ways to improve that but in the meanwhile we wanted to do something to improve the user experience during that delay.

We decided to add in a game that users could play around with while they waited for the process to complete. Inspired by the pong preloaders on some of the console games and the Highrise Tic-Tac-Toe setup game we set out to build one of our own. I looked at the various options and settled on the Sliding Puzzles since it was moderately difficult to play, relatively simple to build and easy to brand! The result is a fun to play 9-piece sliding puzzle that uses the Cadmus logo as the image.

puzzle

The puzzle was intended only for new users and users that have been inactive for a while but it was so fun to test/play; I decided to make it available for existing users as well. You can check it out @ http://thecadmus.com/?puzzle. You need to be logged in before visiting that URL.

The Details

Lets dive right into some the things that I used to build the puzzle. Firstly the puzzle image which is a single image of the Cadmus logo. I wanted each of the pieces in the puzzle to seem like a piece on a board. Meaning it needed to have a shadow to give a feel that it is sitting on top of the board. I did this by using the CSS3 box-shadow property and the rgba properties to give the effect of a shadow.

div.puzzle div.piece {
	width: 100px;
	height: 100px;
	background: transparent url(puzzle-image.png) no-repeat top left;
	position: absolute;
	cursor: pointer;
	box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
	-moz-box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
	-webkit-box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
}
div.puzzle div.piece-0 {
	background-position: 0 0;
}
div.puzzle div.piece-1 {
	background-position: -100px 0;
}
...

The second part of creating the puzzle was the board itself. As with all the other elements it is important that it fits in with the rest of the application. I went with the look where the board is cut into the canvas because it reminds me of how most sliding puzzles are in reality. They are usually set into the surface so the pieces don’t slide off the board.

Picture 6

The grid within the board are also cutting further into the board to give a really crisp feel to the whole thing. Lets look at the effects used to create the board in a little more detail.

board

  1. A 1 pixel stroke on the outside of the board that is lighter than the background giving the impression that the board is set into the canvas. There is also an inner shadow on the board to further the effect. It is a matter of playing around with these effects to figure out how much the board is cut into the canvas.
  2. The texture and color of the board is different from the texture of the canvas to give you the feel that there is something underneath the canvas. I used a layer of noise and a layer of the Gray Granite texture in Photoshop to create it. My general rule of thumb with textures is that they should be noisy but not too noisy. It means that it should be noisy enough to give you the feel of the texture but not too noisy that you see the Photoshop layer effects instead of the texture itself.
  3. There is also a slight inner glow to further the effect of the shadow the canvas casts on the board.
  4. The grid is three 1 pixel lines; the two outer ones are white and the inner one is black in color. The three lines have 13%, 45% and 43% opacity respectively. The values would differ depending on the background but it is important to remember that it is the third line’s job to highlight the second one. The effect does not work if they don’t play well together.
  5. Finally, there is a slight gradient across the whole board that is darker at the top and lighter at the bottom. Again, further adding to the effect that the board is cut into the canvas.

The final part of creating the puzzle is the JS portion of it. Most of it is really straight forward; I have an array representation of the board, an array of possible moves for each position and an array of CSS left and top values for each position. And so every time a piece is clicked the following function runs.

'onPieceClick': function(e, el, args) {
	var from = this.getPositionForPiece(args.position),
	to = this.getAvailableMove(from);
 
	return (to === null)
		? this
		: this
			.stopMoveAnimation()
			.setCurrentPieceEl(args.el)
			.movePiece(args.position, args.el, from, to)
			.checkStatus();
},

We find the position given the piece number (pieces are numbered 0-8) and find the available moves given the current position. If there is a move then we stop any current animations (the last piece could still be sliding into place), save a reference to the current piece, move the piece and check the status of the board to see if the puzzle has been solved.

To start the game we need to randomize the board. But a number of possible positions for this puzzle are unsolvable. So I wrote up this function that shuffles the pieces along in a similar manner a user would click around the board to shuffle it up.

'shufflePiece': function(i, position, lastPosition) {
	if (i > 0) {
		var from = this.getRandomExcept(
			this.movesList[position],
			this.getExcludeList(lastPosition)
		),
		piece = this.getPieceForPosition(from);
 
		return this.movePiece(
			piece,
			this.getPieceEl(piece),
			from,
			position,
			function() {
				return this.shufflePiece(i - 1, from, position);
			}
		);
	}
 
	return (this.isSolved())
		? this.shufflePiece(this.shuffleCount, 9, null)
		: this.startGame();
},
...
this.shufflePiece(this.shuffleCount, 9, null);
...

I get the available moves for the given empty position in the board and I also exclude the previous empty position since I don’t want the randomizer to pick the previous move. This function calls itself as it shuffles every move. I start it off by passing in the number of times I want it shuffled and the first empty position on the board. Now at the end of all the shuffling I might end up right where I started so I have a simple check that restarts the shuffling if that happens. A better approach would be to calculate the distance of the shuffled state from the solved state and set a lower limit on that.

The entire code for the game is actually quite small and it was relatively simple to implement (not to mention fun to test). We will keep an eye on how this impacts the experience for a new user and see if it actually helps.

By going into the different aspects (CSS, Photoshop and JS) of building this feature, I am hoping it would help others venture out into areas that they have been previously shying away from.

Notes

If you have any questions or would like me to go into further detail; just let me know on Twitter.

Also, check out the 37signals post about the Tic-Tac-Toe game in their Highrise iPhone app.

Share

Please do share this on Twitter.

Thanks for all the mentions

Posted by Jay on Apr 11th, 2010

Just wanted to make a quick post about the press Cadmus has gotten recently.

The Tweet House panel at SXSW with @brian_wong, @scobleizer, @markmilian, @domLink (around 13:07)

Opening up opportunity with Twitter at Mix10 by @rsarver and @raffiLink (around 20:39)

A Cinchcast with @louisgrayLink

With @scobleizer at the Palo Alto Apple Store – Link

Thanks guys!

Lists and Topics in Cadmus

Posted by Jay on Mar 24th, 2010

We recently rolled out the Lists feature for everybody. This means that Cadmus will find top conversations and trending topics from your lists. You can use this to stay updated on a certain topic (like social media) without having to follow all the related people on Twitter. You can simply follow a list (Cadmus will sync your lists automatically) and you can keep up with them really easily.

We used this idea to create a page that helped people stay up to date with the SXSWi speakers. We simply used the list created by @sxsw and started finding the top content from that list. And now we extended the idea to other topics. Earlier this week @raffi tweeted about the suggested users API. We used that API to create lists for certain topics and have created public pages where you can see their trending topics and conversations. For example, you can see the top content from the topic of technology here and you can see all the topics we have here.

A quick note on syncing lists; if you find that a list that you have just followed or un-followed is not showing up in Cadmus it might be because we haven’t synced it yet. But if you want to see the changes right away, you can head over to the Services page and click on your Twitter service and then hit the Sync Service button.

Let us know what you think of the Lists and Topics feature on Twitter.

I had previously created the Cadmus “post” button in Photoshop and it was essentially three images for the different states. I wanted to use this style for all our buttons, but doing it with single images is not a good idea. So I set about creating the same style of the buttons with CSS3. And this is what I ended up with.

post-buttons

I want to go into detail on the steps I took to create the button and the effects that make it work.

The Devil is in the Details

The whole idea is to use a combination of subtle effects to create a three dimensional object. Mike Rundle covers some of the ideas used here in his post about subtlety in interfaces. I’m hoping to expand a bit more on that. The idea is that:

  • The button is set into the canvas.
  • The texture of the button is different from the canvas and the surface is slightly raised.
  • And the text of the button is pressed into it.

Lets take a deeper look at the button and the various effects that we use to create this idea. The HTML used for the button is a bit excessive, but it will make sense when we go into detail.

<a class="button"><b class="o"><b class="m"><b>Post</b></b></b></a>

Now onto the styles.

  1. A simple gradient that is lighter at the top to show that the light source is above it and the surface is slightly raised. We use a 1px width background image for this.
  2. a.button b.m {
    	background: transparent url(button.png) repeat-x 0 0;
    }
  3. A lighter border around it to show that light is reflecting off the edges. We use the CSS3 rgba property for this. We need the alpha blending because the reflected light is far more visible at the bottom than the top.
  4. A hard 1px top border to show that light reflects off the top edge more than the other edges.
  5. a.button b.m {
    	border-width: 1px;
    	border-style: solid;
    	border-color: #FFF rgba(255, 255, 255, 0.33) rgba(255, 255, 255, 0.33);
    }
  6. A lighter 1px bottom border to create the effect that the button is sitting right in the canvas.
  7. a.button {
    	border-width: 1px;
    	border-style: solid;
    	border-color: transparent transparent rgba(255, 255, 255, 0.63);
    }
  8. A 1px border around the button to show the shadow of the button on the canvas. Again using the rgba.
  9. a.button b.o {
    	border: 1px solid rgba(0, 0, 0, 0.56);
    }
  10. And finally the shadow on the button text to show that it is pressed into the surface.
  11. a.button b.m b {
    	text-shadow: 0 1px 0 #DDD;
    	color: #262626;
    }

The State of Buttons

I like adding hover states to my buttons and the simplest way is to lighten the background color of the button. For the active or mouse down state of the button the effect we are trying to achieve is that of a raised surface pressed inwards. Hence, the lighting of the button should reflect that. Now there are a couple of different ways to do this.

I like the idea where the surface is pressed in, but the top edge doesn’t move. Instead of having the entire button moving in, just the raised part gets pressed in. We go from a convex shape to a concave shape when it is pressed.

Lets look at it in detail again.

  1. Flip the gradient from before. The darker shade of the gradient is darker than the darkest shade of the previous gradient. This is important because the light hitting the bottom of a convex shape should reflect more than the light hitting the top of a concave shape.
  2. a.button:active b.m {
    	background-position: 0 -160px;
    }
  3. A light top border to emphasize that the top edge doesn’t move when the shape of the surface changes.
  4. The bottom border is lighter as well since the bottom edge doesn’t move either.
  5. The borders of the side are a bit lighter, but not very much since they do move with the surface.
  6. a.button:active b.m {
    	border-color: rgba(255, 255, 255, 0.11) rgba(255, 255, 255, 0.23) rgba(255, 255, 255, 0.27);
    }

Show and Tell

The result is a great looking button with CSS3. Below is a live demo of it tested on Firefox 3.6, Safari 4 and Chrome. On IE8 the rounded corners and active state are missing, and I haven’t tested it on Opera yet. If you do either of them, please ping me on Twitter and let me know.

Below is most of the CSS and here is the image sprite that is used. I use the yui reset CSS on the page so it might be a bit different for you.

a.button {
	text-decoration: none;
	border-color: transparent transparent #ECECEC; /** rgba fallback **/
	border-color: transparent transparent rgba(255, 255, 255, 0.63);
	cursor: pointer;
	outline: none;
}
a.button:hover {
	text-decoration: none;
}
a.button,
a.button b.o,
a.button b.m {
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
	border-radius: 4px;
	border-width: 1px;
	border-style: solid;
	display: block;
}
a.button b.o {
	border-color: #5A5A5A; /** rgba fallback **/
	border-color: rgba(0, 0, 0, 0.56);
}
a.button b.m {
	background: transparent url(button.png) repeat-x 0 0;
	border-color: #FFF transparent #C7C7C7; /** rgba fallback **/
	border-color: #FFF rgba(255, 255, 255, 0.33) rgba(255, 255, 255, 0.33);
}
a.button:hover b.m {
	background-position: 0 -80px;
}
a.button:active b.m {
	background-position: 0 -160px;
	border-color: #B7B7B7 transparent #D4D4D4; /** rgba fallback **/
	border-color: rgba(255, 255, 255, 0.11) rgba(255, 255, 255, 0.23) rgba(255, 255, 255, 0.27);
}
a.button b.m b {
	display: block;
	font-weight: bold;
	padding: 4px 8px;
	text-shadow: 0 1px 0 #DDD;
	color: #262626;
	/** Make the text unselectable **/
	-moz-user-select: none;
	-webkit-user-select: none;
}

I use the innermost b tag in some other buttons to add an icon to the background. The b.m tag is required because the alpha blending for the b.o border needs to have its own “layer”. Otherwise the b.o border would be on top of the background image and the shading would change according to it.

I am hoping that by going into the detail you can use these techniques in your designs and as Mike mentions in his post; think about your designs in 3D. It is less about using the specific border effects and more about using them together to achieve an overall look.

Notes

I would love to hear your feedback and comments; just catch me on Twitter.

Also, check out zurb’s super awesome CSS3 buttons. They have a take on CSS3 buttons and the buttons are super awesome!

Share

Please do share this on Twitter.

Updates

I have received some really impressive feedback for this post. And I am glad that people have taken my ideas further and have done a great job with it. Here are some of the ones that I found. Please let me know on Twitter if I am missing some.

Thanks to @mliao for reading over this post.

Anomaly Follow us on Twitter Contact us via Email